From f6d6d2068a2b890a5edc3b4e7d9482cf28bf4a2d Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Wed, 9 Sep 2015 09:06:50 +0000 Subject: [PATCH] Experimental isochronous capability added to STM32 OTGv1 driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8289 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h | 2 + os/hal/ports/STM32/LLD/OTGv1/usb_lld.c | 100 ++++++++++++++++++++++- readme.txt | 1 + testhal/STM32/STM32F4xx/USB_CDC/Makefile | 4 +- 4 files changed, 101 insertions(+), 6 deletions(-) diff --git a/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h b/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h index 60f1d25ab..e64038f21 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h +++ b/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h @@ -678,6 +678,8 @@ typedef struct { SOF mask. */ #define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received SOF value. */ +#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received + SOF value. */ #define DSTS_EERR (1U<<3) /**< Erratic error. */ #define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */ #define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c index 6d8e01538..6d94f2e07 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c +++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c @@ -562,6 +562,69 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) { } } +/** + * @brief Isochronous IN transfer failed handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void otg_isoc_in_failed_handler(USBDriver *usbp) { + usbep_t ep; + stm32_otg_t *otgp = usbp->otg; + + for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { + if (((otgp->ie[ep].DIEPCTL & DIEPCTL_EPTYP_MASK) == DIEPCTL_EPTYP_ISO) && + ((otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) != 0)) { + /* Endpoint enabled -> ISOC IN transfer failed */ + /* Disable endpoint */ + otgp->ie[ep].DIEPCTL |= (DIEPCTL_EPDIS | DIEPCTL_SNAK); + while (otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) + ; + + /* Flush FIFO */ + otg_txfifo_flush(usbp, ep); + + /* Prepare data for next frame */ + _usb_isr_invoke_in_cb(usbp, ep); + + /* Pump out data for next frame */ + osalSysLockFromISR(); + otgp->DIEPEMPMSK &= ~(1 << ep); + usbp->txpending |= (1 << ep); + osalThreadResumeI(&usbp->wait, MSG_OK); + osalSysUnlockFromISR(); + } + } +} + +/** + * @brief Isochronous OUT transfer failed handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ + +static void otg_isoc_out_failed_handler(USBDriver *usbp) { + usbep_t ep; + stm32_otg_t *otgp = usbp->otg; + + for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) { + if (((otgp->oe[ep].DOEPCTL & DOEPCTL_EPTYP_MASK) == DOEPCTL_EPTYP_ISO) && + ((otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) != 0)) { + /* Endpoint enabled -> ISOC OUT transfer failed */ + /* Disable endpoint */ + /* FIXME: Core stucks here */ + /*otgp->oe[ep].DOEPCTL |= (DOEPCTL_EPDIS | DOEPCTL_SNAK); + while (otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) + ;*/ + /* Prepare transfer for next frame */ + _usb_isr_invoke_out_cb(usbp, ep); + } + } +} + /** * @brief OTG shared ISR. * @@ -622,6 +685,16 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) { _usb_isr_invoke_sof_cb(usbp); } + /* Isochronous IN failed handling */ + if (sts & GINTSTS_IISOIXFR) { + otg_isoc_in_failed_handler(usbp); + } + + /* Isochronous OUT failed handling */ + if (sts & GINTSTS_IISOOXFR) { + otg_isoc_out_failed_handler(usbp); + } + /* RX FIFO not empty handling.*/ if (sts & GINTSTS_RXFLVL) { /* The interrupt is masked while the thread has control or it would @@ -830,7 +903,7 @@ void usb_lld_start(USBDriver *usbp) { - USB turn-around time = TRDT_VALUE_HS or TRDT_VALUE_FS.*/ #if defined(BOARD_OTG2_USES_ULPI) /* High speed ULPI PHY.*/ - otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_HS) | /*XXXXXXXXXXX*/ + otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_HS) | GUSBCFG_SRPCAP | GUSBCFG_HNPCAP; #else otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) | @@ -893,10 +966,12 @@ void usb_lld_start(USBDriver *usbp) { otgp->DAINTMSK = 0; if (usbp->config->sof_cb == NULL) otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | - GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM; + GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | + GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM; else otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | + GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM | GINTMSK_SOFM; /* Clears all pending IRQs, if any. */ @@ -1225,7 +1300,8 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { /* 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) | + /* TODO: Support more than one packet per frame for isochronous transfers.*/ + usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) | DIEPTSIZ_XFRSIZ(isp->txsize); } } @@ -1240,7 +1316,15 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { */ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { - usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_CNAK; + if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { + /* Odd/even bit toggling for isochronous endpoint.*/ + if (usbp->otg->DSTS & DSTS_FNSOF_ODD) + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM; + else + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM; + } + + usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK; } /** @@ -1253,6 +1337,14 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { */ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { + /* Odd/even bit toggling.*/ + if (usbp->otg->DSTS & DSTS_FNSOF_ODD) + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SEVNFRM; + else + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM; + } + usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK; usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); } diff --git a/readme.txt b/readme.txt index 6d3ba394b..11968466b 100644 --- a/readme.txt +++ b/readme.txt @@ -73,6 +73,7 @@ ***************************************************************************** *** 3.1.0 *** +- HAL: Experimental isochronous capability added to STM32 OTGv1 driver. - HAL: Modified the serial-USB driver to reject write/read attempts if the underlying USB is not in active state. In case of disconnection the SDU driver broadcasts a CHN_DISCONNECTED event. diff --git a/testhal/STM32/STM32F4xx/USB_CDC/Makefile b/testhal/STM32/STM32F4xx/USB_CDC/Makefile index 48f6caeb3..3ccc3cbf8 100644 --- a/testhal/STM32/STM32F4xx/USB_CDC/Makefile +++ b/testhal/STM32/STM32F4xx/USB_CDC/Makefile @@ -92,8 +92,8 @@ include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk # HAL-OSAL files (optional). include $(CHIBIOS)/os/hal/hal.mk include $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/platform.mk -include $(CHIBIOS)/os/hal/boards/OLIMEX_STM32_E407/board.mk -#include $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.mk +#include $(CHIBIOS)/os/hal/boards/OLIMEX_STM32_E407/board.mk +include $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.mk include $(CHIBIOS)/os/hal/osal/rt/osal.mk # RTOS files (optional). include $(CHIBIOS)/os/rt/rt.mk