diff options
Diffstat (limited to 'os/hal/ports/STM32/LLD/USBHv1')
-rw-r--r-- | os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h | 929 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c | 396 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h | 34 |
3 files changed, 275 insertions, 1084 deletions
diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h b/os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h deleted file mode 100644 index ca2dc49..0000000 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_stm32_otg.h +++ /dev/null @@ -1,929 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file stm32_otg.h - * @brief STM32 OTG registers layout header. - * - * @addtogroup USB - * @{ - */ - - -#ifndef _STM32_OTG_H_ -#define _STM32_OTG_H_ - -/** - * @brief Number of the implemented endpoints in OTG_FS. - * @details This value does not include the endpoint 0 that is always present. - */ -#define STM32_OTG1_ENDOPOINTS_NUMBER 3 - -/** - * @brief Number of the implemented endpoints in OTG_HS. - * @details This value does not include the endpoint 0 that is always present. - */ -#define STM32_OTG2_ENDOPOINTS_NUMBER 5 - -/** - * @brief OTG_FS FIFO memory size in words. - */ -#define STM32_OTG1_FIFO_MEM_SIZE 320 - -/** - * @brief OTG_HS FIFO memory size in words. - */ -#define STM32_OTG2_FIFO_MEM_SIZE 1024 - -/** - * @brief Host channel registers group. - */ -typedef struct { - volatile uint32_t HCCHAR; /**< @brief Host channel characteristics - register. */ - volatile uint32_t resvd8; - volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/ - volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask - register. */ - volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size - register. */ - volatile uint32_t resvd14; - volatile uint32_t resvd18; - volatile uint32_t resvd1c; -} stm32_otg_host_chn_t; - -/** - * @brief Device input endpoint registers group. - */ -typedef struct { - volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint - control register. */ - volatile uint32_t resvd4; - volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt - register. */ - volatile uint32_t resvdC; - volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size - register. */ - volatile uint32_t resvd14; - volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO - status register. */ - volatile uint32_t resvd1C; -} stm32_otg_in_ep_t; - -/** - * @brief Device output endpoint registers group. - */ -typedef struct { - volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint - control register. */ - volatile uint32_t resvd4; - volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt - register. */ - volatile uint32_t resvdC; - volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer - size register. */ - volatile uint32_t resvd14; - volatile uint32_t resvd18; - volatile uint32_t resvd1C; -} stm32_otg_out_ep_t; - -/** - * @brief USB registers memory map. - */ -typedef struct { - volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/ - volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */ - volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */ - volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */ - volatile uint32_t GRSTCTL; /**< @brief Reset register size. */ - volatile uint32_t GINTSTS; /**< @brief Interrupt register. */ - volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */ - volatile uint32_t GRXSTSR; /**< @brief Receive status debug read - register. */ - volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop - register. */ - volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */ - volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size - register. */ - volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue - status register. */ - volatile uint32_t resvd30; - volatile uint32_t resvd34; - volatile uint32_t GCCFG; /**< @brief General core configuration. */ - volatile uint32_t CID; /**< @brief Core ID register. */ - volatile uint32_t resvd58[48]; - volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size - register. */ - volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO - size registers. */ - volatile uint32_t resvd140[176]; - volatile uint32_t HCFG; /**< @brief Host configuration register. */ - volatile uint32_t HFIR; /**< @brief Host frame interval register. */ - volatile uint32_t HFNUM; /**< @brief Host frame number/frame time - Remaining register. */ - volatile uint32_t resvd40C; - volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue - status register. */ - volatile uint32_t HAINT; /**< @brief Host all channels interrupt - register. */ - volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask - register. */ - volatile uint32_t resvd41C[9]; - volatile uint32_t HPRT; /**< @brief Host port control and status - register. */ - volatile uint32_t resvd444[47]; - stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */ - volatile uint32_t resvd700[64]; - volatile uint32_t DCFG; /**< @brief Device configuration register. */ - volatile uint32_t DCTL; /**< @brief Device control register. */ - volatile uint32_t DSTS; /**< @brief Device status register. */ - volatile uint32_t resvd80C; - volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common - interrupt mask register. */ - volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common - interrupt mask register. */ - volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt - register. */ - volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt - mask register. */ - volatile uint32_t resvd820; - volatile uint32_t resvd824; - volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time - register. */ - volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time - register. */ - volatile uint32_t resvd830; - volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty - interrupt mask register. */ - volatile uint32_t resvd838; - volatile uint32_t resvd83C; - volatile uint32_t resvd840[16]; - volatile uint32_t resvd880[16]; - volatile uint32_t resvd8C0[16]; - stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */ - stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */ - volatile uint32_t resvdD00[64]; - volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control - register. */ - volatile uint32_t resvdE04[127]; - volatile uint32_t FIFO[16][1024]; -} stm32_otg_t; - -/** - * @name GOTGCTL register bit definitions - * @{ - */ -#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */ -#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */ -#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */ -#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */ -#define GOTGCTL_EHEN (1U<<12) -#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */ -#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */ -#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */ -#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */ -#define GOTGCTL_BVALOVAL (1U<<7) -#define GOTGCTL_BVALOEN (1U<<6) -#define GOTGCTL_AVALOVAL (1U<<5) -#define GOTGCTL_AVALOEN (1U<<4) -#define GOTGCTL_VBVALOVAL (1U<<3) -#define GOTGCTL_VBVALOEN (1U<<2) -#define GOTGCTL_SRQ (1U<<1) /**< Session request. */ -#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */ -/** @} */ - -/** - * @name GOTGINT register bit definitions - * @{ - */ -#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */ -#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */ -#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */ -#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success - status change. */ -#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success - status change. */ -#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */ -/** @} */ - -/** - * @name GAHBCFG register bit definitions - * @{ - */ -#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty - level. */ -#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty - level. */ -#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */ -#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS - only). */ -#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS - only). */ -#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */ -/** @} */ - -/** - * @name GUSBCFG register bit definitions - * @{ - */ -#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */ -#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */ -#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */ -#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field - mask. */ -#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field - value. */ -#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */ -#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */ -#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or - USB 1.1 Full-Speed serial - transceiver Select. */ -#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration - field mask. */ -#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration - field value. */ -/** @} */ - -/** - * @name GRSTCTL register bit definitions - * @{ - */ -#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */ -#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */ -#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */ -#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */ -#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */ -#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */ -#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */ -#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */ -/** @} */ - -/** - * @name GINTSTS register bit definitions - * @{ - */ -#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup - detected interrupt. */ -#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session - detected interrupt. */ -#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected - interrupt. */ -#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/ -#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */ -#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */ -#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */ -#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic - transfer. */ -#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT - transfer. */ -#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN - transfer. */ -#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */ -#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */ -#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame - interrupt. */ -#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet - dropped interrupt. */ -#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */ -#define GINTSTS_USBRST (1U<<12) /**< USB reset. */ -#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */ -#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */ -#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */ -#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK - effective. */ -#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */ -#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */ -#define GINTSTS_SOF (1U<<3) /**< Start of frame. */ -#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */ -#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */ -#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */ -/** @} */ - -/** - * @name GINTMSK register bit definitions - * @{ - */ -#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup - detected interrupt mask. */ -#define GINTMSK_SRQM (1U<<30) /**< Session request/New session - detected interrupt mask. */ -#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected - interrupt mask. */ -#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change - mask. */ -#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/ -#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt - mask. */ -#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */ -#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic - transfer mask. */ -#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT - transfer mask. */ -#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN - transfer mask. */ -#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt - mask. */ -#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt - mask. */ -#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame - interrupt mask. */ -#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet - dropped interrupt mask. */ -#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */ -#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */ -#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */ -#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */ -#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective - mask. */ -#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK - effective mask. */ -#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty - mask. */ -#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty - mask. */ -#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/ -#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */ -#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt - mask. */ -/** @} */ - -/** - * @name GRXSTSR register bit definitions - * @{ - */ -#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */ -#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */ -#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1) -#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2) -#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3) -#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4) -#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6) -#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */ -#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */ -#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ -#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */ -#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */ -#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */ -#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ -#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ -/** @} */ - -/** - * @name GRXSTSP register bit definitions - * @{ - */ -#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */ -#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */ -#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1) -#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2) -#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3) -#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4) -#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6) -#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */ -#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */ -#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */ -#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */ -#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */ -#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */ -#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */ -#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */ -#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */ -#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */ -/** @} */ - -/** - * @name GRXFSIZ register bit definitions - * @{ - */ -#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */ -#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 - * @{ - */ -#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */ -#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */ -#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B" - device. */ -#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A" - device. */ -#define GCCFG_PWRDWN (1U<<16) /**< Power down. */ -/** @} */ - -/** - * @name HPTXFSIZ register bit definitions - * @{ - */ -#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO - depth mask. */ -#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO - depth value. */ -#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO - Start address mask. */ -#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO - start address value. */ -/** @} */ - -/** - * @name HCFG register bit definitions - * @{ - */ -#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */ -#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select - mask. */ -#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at - 48 MHz. */ -#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at - 6 MHz. */ -/** @} */ - -/** - * @name HFIR register bit definitions - * @{ - */ -#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */ -#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */ -/** @} */ - -/** - * @name HFNUM register bit definitions - * @{ - */ -#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/ -#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/ -#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */ -#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */ -/** @} */ - -/** - * @name HPTXSTS register bit definitions - * @{ - */ -#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic - transmit request queue - mask. */ -#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic - transmit request queue - value. */ -#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request - queue Space Available - mask. */ -#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request - queue Space Available - value. */ -#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data - FIFO Space Available - mask. */ -#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data - FIFO Space Available - value. */ -/** @} */ - -/** - * @name HAINT register bit definitions - * @{ - */ -#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */ -#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */ -/** @} */ - -/** - * @name HAINTMSK register bit definitions - * @{ - */ -#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask - mask. */ -#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask - value. */ -/** @} */ - -/** - * @name HPRT register bit definitions - * @{ - */ -#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */ -#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */ -#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */ -#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */ -#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */ -#define HPRT_PPWR (1U<<12) /**< Port power. */ -#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */ -#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */ -#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */ -#define HPRT_PRST (1U<<8) /**< Port reset. */ -#define HPRT_PSUSP (1U<<7) /**< Port suspend. */ -#define HPRT_PRES (1U<<6) /**< Port Resume. */ -#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */ -#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */ -#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/ -#define HPRT_PENA (1U<<2) /**< Port enable. */ -#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */ -#define HPRT_PCSTS (1U<<0) /**< Port connect status. */ -/** @} */ - -/** - * @name HCCHAR register bit definitions - * @{ - */ -#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */ -#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */ -#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */ -#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */ -#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */ -#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */ -#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */ -#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ -#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */ -#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */ -#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/ -#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */ -#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */ -#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */ -#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */ -#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */ -#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */ -#define HCCHAR_MPS_MASK (0x7FFU<<0) /**< Maximum packet size mask. */ -#define HCCHAR_MPS(n) ((n)<<0) /**< Maximum packet size value. */ -/** @} */ - -/** - * @name HCINT register bit definitions - * @{ - */ -#define HCINT_DTERR (1U<<10) /**< Data toggle error. */ -#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */ -#define HCINT_BBERR (1U<<8) /**< Babble error. */ -#define HCINT_TRERR (1U<<7) /**< Transaction Error. */ -#define HCINT_ACK (1U<<5) /**< ACK response - received/transmitted - interrupt. */ -#define HCINT_NAK (1U<<4) /**< NAK response received - interrupt. */ -#define HCINT_STALL (1U<<3) /**< STALL response received - interrupt. */ -#define HCINT_CHH (1U<<1) /**< Channel halted. */ -#define HCINT_XFRC (1U<<0) /**< Transfer completed. */ -/** @} */ - -/** - * @name HCINTMSK register bit definitions - * @{ - */ -#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */ -#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */ -#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */ -#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */ -#define HCINTMSK_NYET (1U<<6) /**< NYET response received - interrupt mask. */ -#define HCINTMSK_ACKM (1U<<5) /**< ACK Response - received/transmitted - interrupt mask. */ -#define HCINTMSK_NAKM (1U<<4) /**< NAK response received - interrupt mask. */ -#define HCINTMSK_STALLM (1U<<3) /**< STALL response received - interrupt mask. */ -#define HCINTMSK_AHBERRM (1U<<2) -#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */ -#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */ -/** @} */ - -/** - * @name HCTSIZ register bit definitions - * @{ - */ -#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */ -#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */ -#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */ -#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */ -#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */ -#define HCTSIZ_DPID_SETUP (3U<<29) /**< SETUP. */ -#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ -#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */ -#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name DCFG register bit definitions - * @{ - */ -#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval - mask. */ -#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval - value. */ -#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */ -#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */ -#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status - OUT handshake. */ -#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */ -#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */ -#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS - mode. */ -#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1 - transceiver clock is 48 - MHz). */ -/** @} */ - -/** - * @name DCTL register bit definitions - * @{ - */ -#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */ -#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */ -#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */ -#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic - IN NAK. */ -#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic - IN NAK. */ -#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */ -#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */ -#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */ -#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN - NAK status. */ -#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */ -#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */ -/** @} */ - -/** - * @name DSTS register bit definitions - * @{ - */ -#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received - 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 - running at 48 MHz). */ -#define DSTS_ENUMSPD_HS_480 (0U<<1) /**< High speed. */ -#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */ -/** @} */ - -/** - * @name DIEPMSK register bit definitions - * @{ - */ -#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */ -#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective - mask. */ -#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when - TxFIFO empty mask. */ -#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */ -#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled - interrupt mask. */ -#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed - interrupt mask. */ -/** @} */ - -/** - * @name DOEPMSK register bit definitions - * @{ - */ -#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when - endpoint disabled mask. */ -#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */ -#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled - interrupt mask. */ -#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed - interrupt mask. */ -/** @} */ - -/** - * @name DAINT register bit definitions - * @{ - */ -#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt - bits mask. */ -#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt - bits value. */ -#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt - bits mask. */ -#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt - bits value. */ -/** @} */ - -/** - * @name DAINTMSK register bit definitions - * @{ - */ -#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask - bits mask. */ -#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask - bits value. */ -#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask - bits mask. */ -#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask - bits value. */ -/** @} */ - -/** - * @name DVBUSDIS register bit definitions - * @{ - */ -#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge - time mask. */ -#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge - time value. */ -/** @} */ - -/** - * @name DVBUSPULSE register bit definitions - * @{ - */ -#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time - mask. */ -#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time - value. */ -/** @} */ - -/** - * @name DIEPEMPMSK register bit definitions - * @{ - */ -#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty - interrupt mask bit. */ -/** @} */ - -/** - * @name DIEPCTL register bit definitions - * @{ - */ -#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ -#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ -#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ -#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ -#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ -#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ -#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */ -#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */ -#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */ -#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */ -#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */ -#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */ -#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_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. */ -#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ -#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ -#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ -#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ -/** @} */ - -/** - * @name DIEPINT register bit definitions - * @{ - */ -#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */ -#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */ -#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when - TxFIFO is empty. */ -#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */ -#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled - interrupt. */ -#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */ -/** @} */ - -/** - * @name DIEPTSIZ register bit definitions - * @{ - */ -#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */ -#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */ -#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */ -#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ -#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name DTXFSTS register bit definitions. - * @{ - */ -#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space - available. */ -/** @} */ - -/** - * @name DOEPCTL register bit definitions. - * @{ - */ -#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */ -#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */ -#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */ -#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */ -#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */ -#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */ -#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */ -#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */ -#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */ -#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */ -#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */ -#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */ -#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */ -#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */ -#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */ -#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */ -#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */ -#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */ -#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */ -#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */ -#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */ -/** @} */ - -/** - * @name DOEPINT register bit definitions - * @{ - */ -#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets - received. */ -#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when - endpoint disabled. */ -#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */ -#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled - interrupt. */ -#define DOEPINT_XFRC (1U<<0) /**< Transfer completed - interrupt. */ -/** @} */ - -/** - * @name DOEPTSIZ register bit definitions - * @{ - */ -#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */ -#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */ -#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */ -#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */ -#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */ -#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */ -#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */ -#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */ -/** @} */ - -/** - * @name PCGCCTL register bit definitions - * @{ - */ -#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */ -#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */ -#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */ -/** @} */ - -/** - * @brief OTG_FS registers block memory address. - */ -#define OTG_FS_ADDR 0x50000000 - -/** - * @brief OTG_HS registers block memory address. - */ -#define OTG_HS_ADDR 0x40040000 - -/** - * @brief Accesses to the OTG_FS registers block. - */ -#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR) - -/** - * @brief Accesses to the OTG_HS registers block. - */ -#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR) - -#endif /* _STM32_OTG_H_ */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c index 3abab1c..2894907 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c @@ -1,6 +1,6 @@ /* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail) + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,6 +21,53 @@ #include "usbh/internal.h" #include <string.h> +#if STM32_USBH_USE_OTG1 +#if !defined(STM32_OTG1_CHANNELS_NUMBER) +#error "STM32_OTG1_CHANNELS_NUMBER must be defined" +#endif +#if !defined(STM32_OTG1_RXFIFO_SIZE) +#define STM32_OTG1_RXFIFO_SIZE 1024 +#endif +#if !defined(STM32_OTG1_PTXFIFO_SIZE) +#define STM32_OTG1_PTXFIFO_SIZE 128 +#endif +#if !defined(STM32_OTG1_NPTXFIFO_SIZE) +#define STM32_OTG1_NPTXFIFO_SIZE 128 +#endif +#if (STM32_OTG1_RXFIFO_SIZE + STM32_OTG1_PTXFIFO_SIZE + STM32_OTG1_NPTXFIFO_SIZE) > (STM32_OTG1_FIFO_MEM_SIZE * 4) +#error "Not enough memory in OTG1 implementation" +#elif (STM32_OTG1_RXFIFO_SIZE + STM32_OTG1_PTXFIFO_SIZE + STM32_OTG1_NPTXFIFO_SIZE) < (STM32_OTG1_FIFO_MEM_SIZE * 4) +#warning "Spare memory in OTG1; could enlarge RX, PTX or NPTX FIFO sizes" +#endif +#if (STM32_OTG1_RXFIFO_SIZE % 4) || (STM32_OTG1_PTXFIFO_SIZE % 4) || (STM32_OTG1_NPTXFIFO_SIZE % 4) +#error "FIFO sizes must be a multiple of 32-bit words" +#endif +#endif + +#if STM32_USBH_USE_OTG2 +#if !defined(STM32_OTG2_CHANNELS_NUMBER) +#error "STM32_OTG2_CHANNELS_NUMBER must be defined" +#endif +#if !defined(STM32_OTG2_RXFIFO_SIZE) +#define STM32_OTG2_RXFIFO_SIZE 2048 +#endif +#if !defined(STM32_OTG2_PTXFIFO_SIZE) +#define STM32_OTG2_PTXFIFO_SIZE 1024 +#endif +#if !defined(STM32_OTG2_NPTXFIFO_SIZE) +#define STM32_OTG2_NPTXFIFO_SIZE 1024 +#endif +#if (STM32_OTG2_RXFIFO_SIZE + STM32_OTG2_PTXFIFO_SIZE + STM32_OTG2_NPTXFIFO_SIZE) > (STM32_OTG2_FIFO_MEM_SIZE * 4) +#error "Not enough memory in OTG2 implementation" +#elif (STM32_OTG2_RXFIFO_SIZE + STM32_OTG2_PTXFIFO_SIZE + STM32_OTG2_NPTXFIFO_SIZE) < (STM32_OTG2_FIFO_MEM_SIZE * 4) +#warning "Spare memory in OTG2; could enlarge RX, PTX or NPTX FIFO sizes" +#endif +#if (STM32_OTG2_RXFIFO_SIZE % 4) || (STM32_OTG2_PTXFIFO_SIZE % 4) || (STM32_OTG2_NPTXFIFO_SIZE % 4) +#error "FIFO sizes must be a multiple of 32-bit words" +#endif +#endif + + #if USBH_LLD_DEBUG_ENABLE_TRACE #define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__) #define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__) @@ -58,8 +105,15 @@ static void _try_commit_np(USBHDriver *host); static void otg_rxfifo_flush(USBHDriver *usbp); static void otg_txfifo_flush(USBHDriver *usbp, uint32_t fifo); +#if STM32_USBH_USE_OTG1 +USBHDriver USBHD1; +#endif +#if STM32_USBH_USE_OTG2 +USBHDriver USBHD2; +#endif + /*===========================================================================*/ -/* Little helper functions. */ +/* Little helper functions. */ /*===========================================================================*/ static inline void _move_to_pending_queue(usbh_ep_t *ep) { list_move_tail(&ep->node, ep->pending_list); @@ -73,18 +127,8 @@ static inline void _save_dt_mask(usbh_ep_t *ep, uint32_t hctsiz) { ep->dt_mask = hctsiz & HCTSIZ_DPID_MASK; } -#if 1 -#define _transfer_completed _transfer_completedI -#else -static inline void _transfer_completed(usbh_ep_t *ep, usbh_urb_t *urb, usbh_urbstatus_t status) { - osalSysLockFromISR(); - _transfer_completedI(ep, urb, status); - osalSysUnlockFromISR(); -} -#endif - /*===========================================================================*/ -/* Functions called from many places. */ +/* Functions called from many places. */ /*===========================================================================*/ static void _transfer_completedI(usbh_ep_t *ep, usbh_urb_t *urb, usbh_urbstatus_t status) { osalDbgCheckClassI(); @@ -200,7 +244,6 @@ static bool _activate_ep(USBHDriver *host, usbh_ep_t *ep) { ep->xfer.buf = urb->buff; } ep->xfer.error_count = 0; - //urb->status = USBH_URBSTATUS_QUEUED; } else { osalDbgCheck(urb->requestedLength >= urb->actualLength); @@ -340,7 +383,7 @@ static bool _update_urb(usbh_ep_t *ep, uint32_t hctsiz, usbh_urb_t *urb, bool co osalDbgCheck(len == ep->xfer.partial); //TODO: if len == ep->xfer.partial, use this instead of the above code } -#if 1 +#if 0 osalDbgAssert(urb->actualLength + len <= urb->requestedLength, "what happened?"); #else if (urb->actualLength + len > urb->requestedLength) { @@ -412,7 +455,7 @@ static void _purge_queue(USBHDriver *host, struct list_head *list) { _release_channel(host, hcm); _update_urb(ep, hcm->hc->HCTSIZ, urb, FALSE); } - _transfer_completed(ep, urb, USBH_URBSTATUS_DISCONNECTED); + _transfer_completedI(ep, urb, USBH_URBSTATUS_DISCONNECTED); } } @@ -487,12 +530,12 @@ static uint32_t _write_packet(struct list_head *list, uint32_t space_available) /*===========================================================================*/ -/* API. */ +/* API. */ /*===========================================================================*/ void usbh_lld_ep_object_init(usbh_ep_t *ep) { /* CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) - * STALL si sólo DAT/STAT si si si si no no ep->type != ISO && (ep->type != CTRL || ctrlphase != SETUP) + * STALL si solo DAT/STAT si si si si no no ep->type != ISO && (ep->type != CTRL || ctrlphase != SETUP) * ACK si si si si si si no no ep->type != ISO * NAK si si si si si si no no ep->type != ISO * BBERR si no si no si no si no ep->in @@ -548,7 +591,6 @@ void usbh_lld_ep_object_init(usbh_ep_t *ep) { void usbh_lld_ep_open(usbh_ep_t *ep) { uinfof("\t%s: Open EP", ep->name); ep->status = USBH_EPSTATUS_OPEN; - osalOsRescheduleS(); } void usbh_lld_ep_close(usbh_ep_t *ep) { @@ -560,11 +602,22 @@ void usbh_lld_ep_close(usbh_ep_t *ep) { } uinfof("\t%s: Closed", ep->name); ep->status = USBH_EPSTATUS_CLOSED; - osalOsRescheduleS(); +} + +bool usbh_lld_ep_reset(usbh_ep_t *ep) { + ep->dt_mask = HCTSIZ_DPID_DATA0; + return TRUE; } void usbh_lld_urb_submit(usbh_urb_t *urb) { usbh_ep_t *const ep = urb->ep; + USBHDriver *const host = ep->device->host; + + if (!(host->otg->HPRT & HPRT_PENA)) { + uwarnf("\t%s: Can't submit URB, port disabled", ep->name); + _usbh_urb_completeI(urb, USBH_URBSTATUS_DISCONNECTED); + return; + } /* add the URB to the EP's queue */ list_add_tail(&urb->node, &ep->urb_list); @@ -576,7 +629,7 @@ void usbh_lld_urb_submit(usbh_urb_t *urb) { _move_to_pending_queue(ep); if (usbhEPIsPeriodic(ep)) { - ep->device->host->otg->GINTMSK |= GINTMSK_SOFM; + host->otg->GINTMSK |= GINTMSK_SOFM; } else { /* try to queue non-periodic transfers */ _try_commit_np(ep->device->host); @@ -584,6 +637,7 @@ void usbh_lld_urb_submit(usbh_urb_t *urb) { } } +/* usbh_lld_urb_abort may require a reschedule if called from a S-locked state */ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { osalDbgCheck(usbhURBIsBusy(urb)); @@ -596,17 +650,20 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { if (hcm->halt_reason == USBH_LLD_HALTREASON_NONE) { /* The channel is not being halted */ + uinfof("\t%s: usbh_lld_urb_abort: channel is not being halted", hcm->ep->name); urb->status = status; _halt_channel(ep->device->host, hcm, USBH_LLD_HALTREASON_ABORT); } else { /* The channel is being halted, so we can't re-halt it. The CHH interrupt will * be in charge of completing the transfer, but the URB will not have the specified status. */ + uinfof("\t%s: usbh_lld_urb_abort: channel is being halted", hcm->ep->name); } return FALSE; } - /* This URB is active, we can cancel it now */ + /* This URB is inactive, we can cancel it now */ + uinfof("\t%s: usbh_lld_urb_abort: URB is not active", ep->name); _transfer_completedI(ep, urb, status); return TRUE; @@ -614,7 +671,7 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) { /*===========================================================================*/ -/* Channel Interrupts. */ +/* Channel Interrupts. */ /*===========================================================================*/ //CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT) @@ -705,7 +762,7 @@ static void _complete_bulk_int(USBHDriver *host, stm32_hc_management_t *hcm, usb _save_dt_mask(ep, hctsiz); if (_update_urb(ep, hctsiz, urb, TRUE)) { udbgf("\t%s: done", ep->name); - _transfer_completed(ep, urb, USBH_URBSTATUS_OK); + _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); } else { osalDbgCheck(urb->requestedLength > 0x7FFFF); uwarnf("\t%s: incomplete", ep->name); @@ -736,7 +793,7 @@ static void _complete_control(USBHDriver *host, stm32_hc_management_t *hcm, usbh } else { osalDbgCheck(ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_STATUS); udbgf("\t%s: STATUS done", ep->name); - _transfer_completed(ep, urb, USBH_URBSTATUS_OK); + _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); } _try_commit_np(host); } @@ -762,7 +819,7 @@ static void _complete_iso(USBHDriver *host, stm32_hc_management_t *hcm, usbh_ep_ udbgf("\t%s: done", hcm->ep->name); _release_channel(host, hcm); _update_urb(ep, hctsiz, urb, TRUE); - _transfer_completed(ep, urb, USBH_URBSTATUS_OK); + _transfer_completedI(ep, urb, USBH_URBSTATUS_OK); _try_commit_p(host, FALSE); } @@ -847,7 +904,7 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ switch (reason) { case USBH_LLD_HALTREASON_NAK: if ((ep->type == USBH_EPTYPE_INT) && ep->in) { - _transfer_completed(ep, urb, USBH_URBSTATUS_TIMEOUT); + _transfer_completedI(ep, urb, USBH_URBSTATUS_TIMEOUT); } else { ep->xfer.error_count = 0; _move_to_pending_queue(ep); @@ -855,15 +912,19 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ break; case USBH_LLD_HALTREASON_STALL: - if ((ep->type == USBH_EPTYPE_CTRL) && (ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_SETUP)) { - uerrf("\t%s: Faulty device: STALLed SETUP phase", ep->name); + if (ep->type == USBH_EPTYPE_CTRL) { + if (ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_SETUP) { + uerrf("\t%s: Faulty device: STALLed SETUP phase", ep->name); + } + } else { + ep->status = USBH_EPSTATUS_HALTED; } - _transfer_completed(ep, urb, USBH_URBSTATUS_STALL); + _transfer_completedI(ep, urb, USBH_URBSTATUS_STALL); break; case USBH_LLD_HALTREASON_ERROR: if ((ep->type == USBH_EPTYPE_ISO) || done || (ep->xfer.error_count >= 3)) { - _transfer_completed(ep, urb, USBH_URBSTATUS_ERROR); + _transfer_completedI(ep, urb, USBH_URBSTATUS_ERROR); } else { uerrf("\t%s: err=%d, done=%d, retry", ep->name, ep->xfer.error_count, done); _move_to_pending_queue(ep); @@ -872,7 +933,7 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_ case USBH_LLD_HALTREASON_ABORT: uwarnf("\t%s: Abort", ep->name); - _transfer_completed(ep, urb, urb->status); + _transfer_completedI(ep, urb, urb->status); break; default: @@ -926,10 +987,15 @@ static inline void _hcint_int(USBHDriver *host) { haint = host->otg->HAINT; haint &= host->otg->HAINTMSK; +#if USBH_LLD_DEBUG_ENABLE_ERRORS if (!haint) { - uerrf("HAINT=%08x, HAINTMSK=%08x", host->otg->HAINT, host->otg->HAINTMSK); + uint32_t a, b; + a = host->otg->HAINT; + b = host->otg->HAINTMSK; + uerrf("HAINT=%08x, HAINTMSK=%08x", a, b); return; } +#endif #if 1 //channel lookup loop uint8_t i; @@ -951,9 +1017,50 @@ static inline void _hcint_int(USBHDriver *host) { /*===========================================================================*/ -/* Host interrupts. */ +/* Host interrupts. */ /*===========================================================================*/ static inline void _sof_int(USBHDriver *host) { + + /* this is part of the workaround to the LS bug in the OTG core */ +#undef HPRT_PLSTS_MASK +#define HPRT_PLSTS_MASK (3U<<10) + if (host->check_ls_activity) { + stm32_otg_t *const otg = host->otg; + uint16_t remaining = otg->HFNUM >> 16; + if (remaining < 5975) { + uwarnf("LS: ISR called too late (time=%d)", 6000 - remaining); + return; + } + /* 15us loop during which we check if the core generates an actual keep-alive + * (or activity other than idle) on the DP/DM lines. After 15us, we abort + * the loop and wait for the next SOF. If no activity is detected, the upper + * layer will time-out waiting for the reset to happen, and the port will remain + * enabled (though in a dumb state). This will be detected on the next port reset + * request and the OTG core will be reset. */ + for (;;) { + uint32_t line_status = otg->HPRT & HPRT_PLSTS_MASK; + remaining = otg->HFNUM >> 16; + if (!(otg->HPRT & HPRT_PENA)) { + uwarn("LS: Port disabled"); + return; + } + if (line_status != HPRT_PLSTS_DM) { + /* success; report that the port is enabled */ + uinfof("LS: activity detected, line=%d, time=%d", line_status >> 10, 6000 - remaining); + host->check_ls_activity = FALSE; + otg->GINTMSK = (otg->GINTMSK & ~GINTMSK_SOFM) | (GINTMSK_HCM | GINTMSK_RXFLVLM); + host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE; + host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE; + return; + } + if (remaining < 5910) { + udbg("LS: No activity detected"); + return; + } + } + } + + /* real SOF interrupt */ udbg("SOF"); _try_commit_p(host, TRUE); } @@ -1059,9 +1166,6 @@ static inline void _nptxfe_int(USBHDriver *host) { rem += _write_packet(&host->ep_active_lists[USBH_EPTYPE_BULK], otg->HNPTXSTS & HPTXSTS_PTXFSAVL_MASK); -// if (rem) -// otg->GINTMSK |= GINTMSK_NPTXFEM; - if (!rem) otg->GINTMSK &= ~GINTMSK_NPTXFEM; @@ -1073,17 +1177,19 @@ static inline void _ptxfe_int(USBHDriver *host) { uinfo("PTXFE"); } -static inline void _discint_int(USBHDriver *host) { - uint32_t hprt = host->otg->HPRT; - - uwarn("\tDISCINT"); +static void _disable(USBHDriver *host) { + host->rootport.lld_status &= ~(USBH_PORTSTATUS_CONNECTION | USBH_PORTSTATUS_ENABLE); + host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION | USBH_PORTSTATUS_C_ENABLE; - if (!(hprt & HPRT_PCSTS)) { - host->rootport.lld_status &= ~(USBH_PORTSTATUS_CONNECTION | USBH_PORTSTATUS_ENABLE); - host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION | USBH_PORTSTATUS_C_ENABLE; - } _purge_active(host); _purge_pending(host); + + host->otg->GINTMSK &= ~(GINTMSK_HCM | GINTMSK_RXFLVLM); +} + +static inline void _discint_int(USBHDriver *host) { + uinfo("DISCINT: Port disconnection detected"); + _disable(host); } static inline void _hprtint_int(USBHDriver *host) { @@ -1099,8 +1205,6 @@ static inline void _hprtint_int(USBHDriver *host) { uinfo("\tHPRT: Port connection detected"); host->rootport.lld_status |= USBH_PORTSTATUS_CONNECTION; host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION; - } else { - uinfo("\tHPRT: Port disconnection detected"); } } @@ -1108,9 +1212,32 @@ static inline void _hprtint_int(USBHDriver *host) { hprt_clr |= HPRT_PENCHNG; if (hprt & HPRT_PENA) { uinfo("\tHPRT: Port enabled"); - host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE; host->rootport.lld_status &= ~(USBH_PORTSTATUS_HIGH_SPEED | USBH_PORTSTATUS_LOW_SPEED); + /* configure FIFOs */ +#define HNPTXFSIZ DIEPTXF0 +#if STM32_USBH_USE_OTG1 +#if STM32_USBH_USE_OTG2 + if (&USBHD1 == host) +#endif + { + otg->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG1_RXFIFO_SIZE / 4); + otg->HNPTXFSIZ = HPTXFSIZ_PTXSA(STM32_OTG1_RXFIFO_SIZE / 4) | HPTXFSIZ_PTXFD(STM32_OTG1_NPTXFIFO_SIZE / 4); + otg->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4) + (STM32_OTG1_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_PTXFIFO_SIZE / 4); + } +#endif +#if STM32_USBH_USE_OTG2 +#if STM32_USBH_USE_OTG1 + if (&USBHD2 == host) +#endif + { + otg->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG2_RXFIFO_SIZE / 4); + otg->HNPTXFSIZ = HPTXFSIZ_PTXSA(STM32_OTG2_RXFIFO_SIZE / 4) | HPTXFSIZ_PTXFD(STM32_OTG2_NPTXFIFO_SIZE / 4); + otg->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4) + (STM32_OTG2_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_PTXFIFO_SIZE / 4); + } +#endif +#undef HNPTXFSIZ + /* Make sure the FIFOs are flushed. */ otg_txfifo_flush(host, 0x10); otg_rxfifo_flush(host); @@ -1127,9 +1254,23 @@ static inline void _hprtint_int(USBHDriver *host) { host->rootport.lld_status |= USBH_PORTSTATUS_LOW_SPEED; otg->HFIR = 6000; otg->HCFG = (otg->HCFG & ~HCFG_FSLSPCS_MASK) | HCFG_FSLSPCS_6; + + /* Low speed devices connected to the STM32's internal transceiver sometimes + * don't behave correctly. Although HPRT reports a port enable, really + * no traffic is generated, and the core is non-functional. To avoid + * this we won't report the port enable until we are sure that the + * port is working. */ + host->check_ls_activity = TRUE; + otg->GINTMSK |= GINTMSK_SOFM; } else { otg->HFIR = 48000; otg->HCFG = (otg->HCFG & ~HCFG_FSLSPCS_MASK) | HCFG_FSLSPCS_48; + host->check_ls_activity = FALSE; + + /* enable channel and rx interrupts */ + otg->GINTMSK |= GINTMSK_HCM | GINTMSK_RXFLVLM; + host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE; + host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE; } } else { if (hprt & HPRT_PCSTS) { @@ -1141,13 +1282,8 @@ static inline void _hprtint_int(USBHDriver *host) { } else { uerr("\tHPRT: Port disabled due to disconnect"); } - - _purge_active(host); - _purge_pending(host); - - host->rootport.lld_status &= ~USBH_PORTSTATUS_ENABLE; + _disable(host); } - host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE; } if (hprt & HPRT_POCCHNG) { @@ -1179,18 +1315,19 @@ static void usb_lld_serve_interrupt(USBHDriver *host) { } /* check mismatch */ - if (gintsts & GINTSTS_MMIS) { - uerr("Mode Mismatch"); - otg->GINTSTS = gintsts; - return; - } + osalDbgAssert((gintsts & GINTSTS_MMIS) == 0, "mode mismatch"); gintsts &= otg->GINTMSK; if (!gintsts) { - uwarnf("GINTSTS=%08x, GINTMSK=%08x", otg->GINTSTS, otg->GINTMSK); +#if USBH_DEBUG_ENABLE_WARNINGS + uint32_t a, b; + a = otg->GINTSTS; + b = otg->GINTMSK; + uwarnf("Masked bits caused an ISR: GINTSTS=%08x, GINTMSK=%08x (unhandled bits=%08x)", a, b, a & ~b); +#endif return; } -// otg->GINTMSK &= ~(GINTMSK_NPTXFEM | GINTMSK_PTXFEM); + otg->GINTSTS = gintsts; if (gintsts & GINTSTS_SOF) @@ -1214,7 +1351,7 @@ static void usb_lld_serve_interrupt(USBHDriver *host) { /*===========================================================================*/ -/* Interrupt handlers. */ +/* Interrupt handlers. */ /*===========================================================================*/ #if STM32_USBH_USE_OTG1 @@ -1239,7 +1376,7 @@ OSAL_IRQ_HANDLER(STM32_OTG2_HANDLER) { /*===========================================================================*/ -/* Initialization functions. */ +/* Initialization functions. */ /*===========================================================================*/ static void otg_core_reset(USBHDriver *usbp) { stm32_otg_t *const otgp = usbp->otg; @@ -1289,25 +1426,23 @@ static void _init(USBHDriver *host) { #if STM32_USBH_USE_OTG1 #if STM32_USBH_USE_OTG2 - if (&USBHD1 == host) { + if (&USBHD1 == host) #endif + { host->otg = OTG_FS; host->channels_number = STM32_OTG1_CHANNELS_NUMBER; -#if STM32_USBH_USE_OTG2 } #endif -#endif #if STM32_USBH_USE_OTG2 #if STM32_USBH_USE_OTG1 - if (&USBHD2 == host) { + if (&USBHD2 == host) #endif + { host->otg = OTG_HS; host->channels_number = STM32_OTG2_CHANNELS_NUMBER; -#if STM32_USBH_USE_OTG1 } #endif -#endif INIT_LIST_HEAD(&host->ch_free[0]); INIT_LIST_HEAD(&host->ch_free[1]); for (i = 0; i < host->channels_number; i++) { @@ -1341,8 +1476,9 @@ static void _usbh_start(USBHDriver *usbh) { /* Clock activation.*/ #if STM32_USBH_USE_OTG1 #if STM32_USBH_USE_OTG2 - if (&USBHD1 == usbh) { + if (&USBHD1 == usbh) #endif + { /* OTG FS clock enable and reset.*/ rccEnableOTG_FS(FALSE); rccResetOTG_FS(); @@ -1351,27 +1487,25 @@ static void _usbh_start(USBHDriver *usbh) { /* Enables IRQ vector.*/ nvicEnableVector(STM32_OTG1_NUMBER, STM32_USB_OTG1_IRQ_PRIORITY); -#if STM32_USBH_USE_OTG2 } #endif -#endif #if STM32_USBH_USE_OTG2 #if STM32_USBH_USE_OTG1 - if (&USBHD2 == usbh) { + if (&USBHD2 == usbh) #endif + { /* OTG HS clock enable and reset.*/ - rccEnableOTG_HS(FALSE); + rccEnableOTG_HS(TRUE); // Enable HS clock when cpu is in sleep mode + rccDisableOTG_HSULPI(TRUE); // Disable HS ULPI clock when cpu is in sleep mode rccResetOTG_HS(); otgp->GINTMSK = 0; /* Enables IRQ vector.*/ nvicEnableVector(STM32_OTG2_NUMBER, STM32_USB_OTG2_IRQ_PRIORITY); -#if STM32_USBH_USE_OTG1 } #endif -#endif otgp->GUSBCFG = GUSBCFG_PHYSEL | GUSBCFG_TRDT(5); @@ -1386,12 +1520,20 @@ static void _usbh_start(USBHDriver *usbh) { otgp->PCGCCTL = 0; /* Internal FS PHY activation.*/ +#if STM32_OTG_STEPPING == 1 #if defined(BOARD_OTG_NOVBUSSENS) otgp->GCCFG = GCCFG_NOVBUSSENS | GCCFG_PWRDWN; #else otgp->GCCFG = GCCFG_PWRDWN; #endif +#elif STM32_OTG_STEPPING == 2 +#if defined(BOARD_OTG_NOVBUSSENS) + otgp->GCCFG = GCCFG_PWRDWN; +#else + otgp->GCCFG = (GCCFG_VBDEN | GCCFG_PWRDWN); +#endif +#endif /* 48MHz 1.1 PHY.*/ otgp->HCFG = HCFG_FSLSS | HCFG_FSLSPCS_48; @@ -1402,40 +1544,11 @@ static void _usbh_start(USBHDriver *usbh) { otgp->HPRT |= HPRT_PPWR; - /* without this delay, the FIFO sizes are set INcorrectly */ - osalThreadSleepS(MS2ST(200)); - -#define HNPTXFSIZ DIEPTXF0 -#if STM32_USBH_USE_OTG1 -#if STM32_USBH_USE_OTG2 - if (&USBHD1 == usbh) { -#endif - otgp->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG1_RXFIFO_SIZE / 4); - otgp->HNPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_NPTXFIFO_SIZE / 4); - otgp->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4) + (STM32_OTG1_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_PTXFIFO_SIZE / 4); -#if STM32_USBH_USE_OTG2 - } -#endif -#endif -#if STM32_USBH_USE_OTG2 -#if STM32_USBH_USE_OTG1 - if (&USBHD2 == usbh) { -#endif - otgp->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG2_RXFIFO_SIZE / 4); - otgp->HNPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_NPTXFIFO_SIZE / 4); - otgp->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4) + (STM32_OTG2_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_PTXFIFO_SIZE / 4); -#if STM32_USBH_USE_OTG1 - } -#endif -#endif - otg_txfifo_flush(usbh, 0x10); otg_rxfifo_flush(usbh); otgp->GINTSTS = 0xffffffff; - otgp->GINTMSK = GINTMSK_DISCM /*| GINTMSK_PTXFEM*/ | GINTMSK_HCM | GINTMSK_HPRTM - /*| GINTMSK_IPXFRM | GINTMSK_NPTXFEM*/ | GINTMSK_RXFLVLM - /*| GINTMSK_SOFM */ | GINTMSK_MMISM; + otgp->GINTMSK = GINTMSK_DISCM | GINTMSK_HPRTM | GINTMSK_MMISM; usbh->rootport.lld_status = USBH_PORTSTATUS_POWER; usbh->rootport.lld_c_status = 0; @@ -1450,7 +1563,7 @@ void usbh_lld_start(USBHDriver *usbh) { } /*===========================================================================*/ -/* Root Hub request handler. */ +/* Root Hub request handler. */ /*===========================================================================*/ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestType, uint8_t bRequest, uint16_t wvalue, uint16_t windex, uint16_t wlength, uint8_t *buf) { @@ -1469,18 +1582,18 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy break; case ClearPortFeature: - chDbgAssert(windex == 1, "invalid windex"); + osalDbgAssert(windex == 1, "invalid windex"); osalSysLock(); switch (wvalue) { case USBH_PORT_FEAT_ENABLE: case USBH_PORT_FEAT_SUSPEND: case USBH_PORT_FEAT_POWER: - chDbgAssert(0, "unimplemented"); /* TODO */ + osalDbgAssert(0, "unimplemented"); /* TODO */ break; case USBH_PORT_FEAT_INDICATOR: - chDbgAssert(0, "unsupported"); + osalDbgAssert(0, "unsupported"); break; case USBH_PORT_FEAT_C_CONNECTION: @@ -1500,30 +1613,18 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy break; case USBH_PORT_FEAT_C_OVERCURRENT: - usbh->rootport.lld_c_status &= USBH_PORTSTATUS_C_OVERCURRENT; + usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_OVERCURRENT; break; default: osalDbgAssert(0, "invalid wvalue"); break; } - osalOsRescheduleS(); osalSysUnlock(); break; case GetHubDescriptor: - /*dev_dbg(hsotg->dev, "GetHubDescriptor\n"); - hub_desc = (struct usb_hub_descriptor *)buf; - hub_desc->bDescLength = 9; - hub_desc->bDescriptorType = USB_DT_HUB; - hub_desc->bNbrPorts = 1; - hub_desc->wHubCharacteristics = - cpu_to_le16(HUB_CHAR_COMMON_LPSM | - HUB_CHAR_INDV_PORT_OCPM); - hub_desc->bPwrOn2PwrGood = 1; - hub_desc->bHubContrCurrent = 0; - hub_desc->u.hs.DeviceRemovable[0] = 0; - hub_desc->u.hs.DeviceRemovable[1] = 0xff;*/ + osalDbgAssert(0, "unsupported"); break; case GetHubStatus: @@ -1532,26 +1633,25 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy break; case GetPortStatus: - chDbgAssert(windex == 1, "invalid windex"); + osalDbgAssert(windex == 1, "invalid windex"); osalDbgCheck(wlength >= 4); osalSysLock(); *(uint32_t *)buf = usbh->rootport.lld_status | (usbh->rootport.lld_c_status << 16); - osalOsRescheduleS(); osalSysUnlock(); break; case SetHubFeature: - chDbgAssert(0, "unsupported"); + osalDbgAssert(0, "unsupported"); break; case SetPortFeature: - chDbgAssert(windex == 1, "invalid windex"); + osalDbgAssert(windex == 1, "invalid windex"); switch (wvalue) { case USBH_PORT_FEAT_TEST: case USBH_PORT_FEAT_SUSPEND: case USBH_PORT_FEAT_POWER: - chDbgAssert(0, "unimplemented"); /* TODO */ + osalDbgAssert(0, "unimplemented"); /* TODO */ break; case USBH_PORT_FEAT_RESET: { @@ -1560,18 +1660,35 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy uint32_t hprt; otg->PCGCCTL = 0; hprt = otg->HPRT; + if (hprt & HPRT_PENA) { + /* This can occur when the OTG core doesn't generate traffic + * despite reporting a successful por enable. */ + uerr("Detected enabled port; resetting OTG core"); + otg->GAHBCFG = 0; + osalThreadSleepS(OSAL_MS2I(20)); + _usbh_start(usbh); /* this effectively resets the core */ + osalThreadSleepS(OSAL_MS2I(100)); /* during this delay, the core generates connect ISR */ + uinfo("OTG reset ended"); + if (otg->HPRT & HPRT_PCSTS) { + /* if the device is still connected, don't report a C_CONNECTION flag, which would cause + * the upper layer to abort enumeration */ + uinfo("Clear connection change flag"); + usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_CONNECTION; + } + } /* note: writing PENA = 1 actually disables the port */ - hprt &= ~(HPRT_PSUSP | HPRT_PENA | HPRT_PCDET | HPRT_PENCHNG | HPRT_POCCHNG ); + hprt &= ~(HPRT_PSUSP | HPRT_PENA | HPRT_PCDET | HPRT_PENCHNG | HPRT_POCCHNG); + while ((otg->GRSTCTL & GRSTCTL_AHBIDL) == 0); otg->HPRT = hprt | HPRT_PRST; - osalThreadSleepS(MS2ST(60)); + osalThreadSleepS(OSAL_MS2I(15)); otg->HPRT = hprt; + osalThreadSleepS(OSAL_MS2I(10)); usbh->rootport.lld_c_status |= USBH_PORTSTATUS_C_RESET; - osalOsRescheduleS(); osalSysUnlock(); } break; case USBH_PORT_FEAT_INDICATOR: - chDbgAssert(0, "unsupported"); + osalDbgAssert(0, "unsupported"); break; default: @@ -1589,16 +1706,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy } uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh) { - osalSysLock(); - if (usbh->rootport.lld_c_status) { - osalOsRescheduleS(); - osalSysUnlock(); - return 1 << 1; - } - osalOsRescheduleS(); - osalSysUnlock(); - return 0; + return usbh->rootport.lld_c_status ? (1 << 1) : 0; } - #endif diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h index e8df749..fd7f4e0 100644 --- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h +++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h @@ -1,6 +1,6 @@ /* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail) + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,8 +15,8 @@ limitations under the License. */ -#ifndef USBH_LLD_H_ -#define USBH_LLD_H_ +#ifndef HAL_USBH_LLD_H +#define HAL_USBH_LLD_H #include "hal.h" @@ -63,6 +63,8 @@ typedef struct stm32_hc_management { #define _usbhdriver_ll_data \ stm32_otg_t *otg; \ + /* low-speed port reset bug */ \ + bool check_ls_activity; \ /* channels */ \ uint8_t channels_number; \ stm32_hc_management_t channels[STM32_OTG2_CHANNELS_NUMBER]; \ @@ -127,27 +129,37 @@ typedef struct stm32_hc_management { "use USBH_DEFINE_BUFFER() to declare the IO buffers"); \ } while (0) - - void usbh_lld_init(void); void usbh_lld_start(USBHDriver *usbh); void usbh_lld_ep_object_init(usbh_ep_t *ep); void usbh_lld_ep_open(usbh_ep_t *ep); void usbh_lld_ep_close(usbh_ep_t *ep); +bool usbh_lld_ep_reset(usbh_ep_t *ep); void usbh_lld_urb_submit(usbh_urb_t *urb); bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status); usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestType, uint8_t bRequest, uint16_t wvalue, uint16_t windex, uint16_t wlength, uint8_t *buf); uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh); -#define usbh_lld_epreset(ep) do {(ep)->dt_mask = HCTSIZ_DPID_DATA0;} while (0); - #ifdef __IAR_SYSTEMS_ICC__ -#define USBH_LLD_DEFINE_BUFFER(type, name) type name +#define USBH_LLD_DEFINE_BUFFER(var) _Pragma("data_alignment=4") var +#define USBH_LLD_DECLARE_STRUCT_MEMBER_H1(x, y) x ## y +#define USBH_LLD_DECLARE_STRUCT_MEMBER_H2(x, y) USBH_LLD_DECLARE_STRUCT_MEMBER_H1(x, y) +#define USBH_LLD_DECLARE_STRUCT_MEMBER(member) unsigned int USBH_LLD_DECLARE_STRUCT_MEMBER_H2(dummy_align_, __COUNTER__); member #else -#define USBH_LLD_DEFINE_BUFFER(type, name) type name __attribute__((aligned(4))) +#define USBH_LLD_DEFINE_BUFFER(var) var __attribute__((aligned(4))) +#define USBH_LLD_DECLARE_STRUCT_MEMBER(member) member __attribute__((aligned(4))) +#endif + + +#if STM32_USBH_USE_OTG1 +extern USBHDriver USBHD1; +#endif + +#if STM32_USBH_USE_OTG2 +extern USBHDriver USBHD2; #endif #endif -#endif /* USBH_LLD_H_ */ +#endif /* HAL_USBH_LLD_H */ |