From f1e6a55322f18fe69293ce9cc4e1da31a589ea6f Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 22 Aug 2017 07:52:33 +0000 Subject: Tentative fix for L4 OTG. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10454 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c | 76 +++++++++++++++--------------- 1 file changed, 39 insertions(+), 37 deletions(-) (limited to 'os/hal/ports/STM32/LLD/OTGv1') diff --git a/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c index 7490c2c8b..b1802bc71 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c +++ b/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c @@ -278,19 +278,21 @@ static void otg_fifo_read_to_buffer(volatile uint32_t *fifop, static void otg_rxfifo_handler(USBDriver *usbp) { uint32_t sts, cnt, ep; + /* Popping the event word out of the RX FIFO.*/ sts = usbp->otg->GRXSTSP; + + /* Event details.*/ + cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; + ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; + switch (sts & GRXSTSP_PKTSTS_MASK) { - case GRXSTSP_SETUP_COMP: - break; case GRXSTSP_SETUP_DATA: - cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; - ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->setup_buf, cnt, 8); break; + case GRXSTSP_SETUP_COMP: + break; case GRXSTSP_OUT_DATA: - cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF; - ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF; otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->out_state->rxbuf, cnt, @@ -299,10 +301,12 @@ static void otg_rxfifo_handler(USBDriver *usbp) { usbp->epc[ep]->out_state->rxbuf += cnt; usbp->epc[ep]->out_state->rxcnt += cnt; break; - case GRXSTSP_OUT_GLOBAL_NAK: case GRXSTSP_OUT_COMP: + break; + case GRXSTSP_OUT_GLOBAL_NAK: + break; default: - ; + break; } } @@ -415,43 +419,41 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) { specific callback.*/ _usb_isr_invoke_setup_cb(usbp, ep); } + if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) { USBOutEndpointState *osp; -#if defined(STM32_OTG_SEQUENCE_WORKAROUND) - /* If an OUT transaction end interrupt is processed after the state - machine advanced to an IN state then it is ignored, this is caused - on some devices (L4) by STUP and XFRCM interrupts arriving in random - order.*/ - if ((ep == 0) && ((usbp->ep0state & USB_OUT_STATE) == 0)) - return; -#else - /* Receive transfer complete, checking if it is a SETUP transfer on EP0, - than it must be ignored, the STUP handler will take care of it.*/ - if ((ep == 0) && (usbp->ep0state == USB_EP0_STP_WAITING)) - return; -#endif - /* OUT state structure pointer for this endpoint.*/ osp = usbp->epc[ep]->out_state; - /* A short packet always terminates a transaction.*/ - if ((ep == 0) && - ((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) && - (osp->rxsize < osp->totsize)) { - /* For EP 0 only, in case the transaction covered only part of the total - transfer then another transaction is immediately started in order to + /* EP0 requires special handling.*/ + if (ep == 0) { + +#if defined(STM32_OTG_SEQUENCE_WORKAROUND) + /* If an OUT transaction end interrupt is processed while the state + machine is not in an OUT state then it is ignored, this is caused + on some devices (L4) apparently injecting spurious data complete + words in the RX FIFO.*/ + if ((usbp->ep0state & USB_OUT_STATE) == 0) + return; +#endif + + /* In case the transaction covered only part of the total transfer + then another transaction is immediately started in order to cover the remaining.*/ - osp->rxsize = osp->totsize - osp->rxsize; - osp->rxcnt = 0; - osalSysLockFromISR(); - usb_lld_start_out(usbp, ep); - osalSysUnlockFromISR(); - } - else { - /* End on OUT transfer.*/ - _usb_isr_invoke_out_cb(usbp, ep); + if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) && + (osp->rxsize < osp->totsize)) { + osp->rxsize = osp->totsize - osp->rxsize; + osp->rxcnt = 0; + osalSysLockFromISR(); + usb_lld_start_out(usbp, ep); + osalSysUnlockFromISR(); + return; + } } + + /* End on OUT transfer.*/ + _usb_isr_invoke_out_cb(usbp, ep); } } -- cgit v1.2.3