aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.c29
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.h4
2 files changed, 29 insertions, 4 deletions
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c
index 7d0c3f216..58c3e2400 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.c
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c
@@ -33,7 +33,9 @@
/* Driver local definitions. */
/*===========================================================================*/
-#define TRDT_VALUE 5
+#define TRDT_VALUE 5
+
+#define EP0_MAX_INSIZE 64
/*===========================================================================*/
/* Driver exported variables. */
@@ -556,7 +558,23 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
}
if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) {
/* Transmit transfer complete.*/
- _usb_isr_invoke_in_cb(usbp, ep);
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ if (isp->txsize < isp->totsize) {
+ /* In case the transaction covered only part of the total transfer
+ then another transaction is immediately started in order to
+ cover the remaining.*/
+ isp->txsize = isp->totsize - isp->txsize;
+ isp->txcnt = 0;
+ usb_lld_prepare_transmit(usbp, ep);
+ chSysLockFromIsr();
+ usb_lld_start_in(usbp, ep);
+ chSysUnlockFromIsr();
+ }
+ else {
+ /* End on IN transfer.*/
+ _usb_isr_invoke_in_cb(usbp, ep);
+ }
}
if ((epint & DIEPINT_TXFE) &&
(otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) {
@@ -1215,18 +1233,21 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
/* Transfer initialization.*/
+ isp->totsize = isp->txsize;
if (isp->txsize == 0) {
/* Special case, sending zero size packet.*/
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
}
else {
+ if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
+ isp->txsize = EP0_MAX_INSIZE;
+
/* Normal case.*/
uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) /
usbp->epc[ep]->in_maxsize;
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
- DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
+ DIEPTSIZ_XFRSIZ(isp->txsize);
}
-
}
/**
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h
index 5be12e66e..2dae8c2ba 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.h
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h
@@ -226,6 +226,10 @@ typedef struct {
OutputQueue *txqueue;
} queue;
} mode;
+ /**
+ * @brief Total transmit transfer size.
+ */
+ size_t totsize;
} USBInEndpointState;
/**