From 86d3b56bfb45b27553f54e8001cba22c6206d373 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 1 May 2014 10:47:25 +0000 Subject: Experimental STM32 OTG fix. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@6901 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/OTGv1/usb_lld.c | 29 +++++++++++++++++++++++++---- os/hal/platforms/STM32/OTGv1/usb_lld.h | 4 ++++ 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'os/hal') 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; /** -- cgit v1.2.3