From 90f1a505d3cf91742927577c45046e4f3d3e7de3 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 10 Apr 2012 17:15:46 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4090 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/OTGv1/stm32_otg.h | 21 ++++- os/hal/platforms/STM32/OTGv1/usb_lld.c | 129 ++++++++++++++++++++++++------- os/hal/platforms/STM32/OTGv1/usb_lld.h | 4 + 3 files changed, 126 insertions(+), 28 deletions(-) diff --git a/os/hal/platforms/STM32/OTGv1/stm32_otg.h b/os/hal/platforms/STM32/OTGv1/stm32_otg.h index fec44c9ad..083f868a5 100644 --- a/os/hal/platforms/STM32/OTGv1/stm32_otg.h +++ b/os/hal/platforms/STM32/OTGv1/stm32_otg.h @@ -35,6 +35,11 @@ */ #define STM32_OTG_ENDOPOINTS_NUMBER 3 +/** + * @brief FIFO memory size in words. + */ +#define STM32_OTG_FIFO_MEM_SIZE 384 + /** * @brief Host channel registers group. */ @@ -386,6 +391,20 @@ typedef struct { #define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */ /** @} */ +/** + * @name DIEPTXFx register bit definitions + * @{ + */ +#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth + mask. */ +#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth + value. */ +#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit + RAM start address mask. */ +#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit + RAM start address value. */ +/** @} */ + /** * @name GCCFG register bit definitions * @{ @@ -746,7 +765,7 @@ typedef struct { #define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */ #define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ #define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ -#define DIEPCTL_EPType_BULK (2U<<18) /**< Bulk. */ +#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ #define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ #define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */ #define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c index be2bccee9..36ef53298 100644 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.c +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c @@ -68,6 +68,11 @@ static union { USBOutEndpointState out; } ep0_state; +/** + * @brief Buffer for the EP0 setup packets. + */ +static uint8_t ep8setup_buffer[8]; + /** * @brief EP0 initialization structure. */ @@ -79,7 +84,8 @@ static const USBEndpointConfig ep0config = { 0x40, 0x40, &ep0_state.in, - &ep0_state.out + &ep0_state.out, + ep8setup_buffer }; /*===========================================================================*/ @@ -114,9 +120,7 @@ static void otg_disable_ep(void) { else OTG->ie[i].DIEPCTL = 0; OTG->ie[i].DIEPTSIZ = 0; - OTG->ie[i].DIEPINT = DIEPINT_INEPNE | DIEPINT_ITTXFE | - DIEPINT_TOC | DIEPINT_EPDISD | - DIEPINT_XFRC; + OTG->ie[i].DIEPINT = 0xFFFFFFFF; /* Disable only if enabled because this sentence in the manual: "The application must set this bit only if Endpoint Enable is already set for this endpoint". @@ -131,38 +135,52 @@ static void otg_disable_ep(void) { else OTG->oe[i].DOEPCTL = 0; OTG->oe[i].DOEPTSIZ = 0; - OTG->oe[i].DOEPINT = DOEPINT_B2BSTUP | DOEPINT_OTEPDIS | - DOEPINT_STUP | DOEPINT_EPDISD | - DOEPINT_XFRC; + OTG->oe[i].DOEPINT = 0xFFFFFFFF; } } +static void otg_rxfifo_flush(void) { + + OTG->GRSTCTL = GRSTCTL_RXFFLSH; + while ((OTG->GRSTCTL & GRSTCTL_RXFFLSH) != 0) + ; +} + +static void otg_txfifo_flush(uint32_t fifo) { + + OTG->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH; + while ((OTG->GRSTCTL & GRSTCTL_TXFFLSH) != 0) + ; +} + /** - * @brief Resets the packet memory allocator. + * @brief Resets the FIFO RAM memory allocator. * * @param[in] usbp pointer to the @p USBDriver object * * @notapi */ -static void otg_pm_reset(USBDriver *usbp) { +static void otg_ram_reset(USBDriver *usbp) { - (void)usbp; + usbp->pmnext = STM32_USB_OTG1_RX_FIFO_SIZE / 4; } /** - * @brief Allocates a block from the packet memory allocator. + * @brief Allocates a block from the FIFO RAM memory. * * @param[in] usbp pointer to the @p USBDriver object - * @param[in] size size of the packet buffer to allocate + * @param[in] size size of the packet buffer to allocate in words * * @notapi */ -static uint32_t otg_pm_alloc(USBDriver *usbp, size_t size) { - - (void)usbp; - (void)size; +static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) { + uint32_t next; - return 0; + next = usbp->pmnext; + usbp->pmnext += size; + chDbgAssert(usbp->pmnext <= STM32_OTG_FIFO_MEM_SIZE, + "otg_fifo_alloc(), #1", "FIFO memory overflow"); + return next; } /** @@ -475,9 +493,6 @@ void usb_lld_start(USBDriver *usbp) { /* PHY enabled.*/ OTG->PCGCCTL = 0; - /* Receive FIFO size initialization, the address is always zero.*/ - OTG->GRXFSIZ = STM32_USB_OTG1_RX_FIFO_SIZE / 4; - /* Endpoints re-initialization.*/ otg_disable_ep(); @@ -537,8 +552,13 @@ void usb_lld_reset(USBDriver *usbp) { OTG->oe[i].DOEPINT = 0xFFFFFFFF; } - /* Resets the packet memory allocator.*/ - otg_pm_reset(usbp); + /* Resets the FIFO memory allocator.*/ + otg_ram_reset(usbp); + + + /* Receive FIFO size initialization, the address is always zero.*/ + OTG->GRXFSIZ = STM32_USB_OTG1_RX_FIFO_SIZE / 4; + otg_rxfifo_flush(); /* Enables also EP-related interrupt sources.*/ OTG->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM; @@ -546,9 +566,18 @@ void usb_lld_reset(USBDriver *usbp) { OTG->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM; // OTG->DAINTMSK = DAINTMSK_OutEpMsk(0) | DAINTMSK_InEpMsk(0); - /* EP0 initialization.*/ + /* EP0 initialization, it is a special case.*/ usbp->epc[0] = &ep0config; - usb_lld_init_endpoint(usbp, 0); + OTG->oe[0].DOEPTSIZ = 0; + OTG->oe[0].DOEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL | + DOEPCTL_MPSIZ(ep0config.out_maxsize); + OTG->ie[0].DIEPTSIZ = 0; + OTG->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL | + DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize); + OTG->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) | + DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, + ep0config.in_maxsize / 4)); + otg_txfifo_flush(0); } /** @@ -572,9 +601,51 @@ void usb_lld_set_address(USBDriver *usbp) { * @notapi */ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + uint32_t ctl, fsize; - (void)usbp; - (void)ep; + /* IN and OUT common parameters.*/ + switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) { + case USB_EP_MODE_TYPE_CTRL: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL; + break; + case USB_EP_MODE_TYPE_ISOC: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO; + break; + case USB_EP_MODE_TYPE_BULK: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK; + break; + case USB_EP_MODE_TYPE_INTR: + ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR; + break; + default: + return; + } + + /* OUT endpoint activation or deactivation.*/ + OTG->oe[ep].DOEPTSIZ = 0; + if (usbp->epc[ep]->out_cb != NULL) + OTG->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize); + else + OTG->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP; + + /* IN endpoint activation or deactivation.*/ + OTG->ie[ep].DIEPTSIZ = 0; + if (usbp->epc[ep]->in_cb != NULL) { + /* FIFO allocation for the IN endpoint.*/ + fsize = usbp->epc[ep]->in_maxsize / 4; + OTG->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) | + DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize)); + otg_txfifo_flush(ep); + + OTG->ie[ep].DIEPCTL = ctl | + DIEPCTL_TXFNUM(ep) | + DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize); + } + else { + OTG->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/ + otg_txfifo_flush(ep); + OTG->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP; + } } /** @@ -586,7 +657,11 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { */ void usb_lld_disable_endpoints(USBDriver *usbp) { - (void)usbp; + /* Resets the FIFO memory allocator.*/ + otg_ram_reset(usbp); + + /* Disabling all endpoints.*/ + otg_disable_ep(); } /** diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h index 752adbfcd..4cc18a05b 100644 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.h +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h @@ -306,6 +306,10 @@ struct USBDriver { USB_DRIVER_EXT_FIELDS #endif /* End of the mandatory fields.*/ + /** + * @brief Pointer to the next address in the packet memory. + */ + uint32_t pmnext; }; /*===========================================================================*/ -- cgit v1.2.3