From 27afa568445d193a075c6ca2b7bb1df76039d956 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 31 Mar 2024 18:42:49 +0700 Subject: rename dcd_stm32_fsdev_pvt_st.h to simply dcd_stm32_fsdev.h --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h | 543 +++++++++++++++++++++ .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 543 --------------------- 3 files changed, 544 insertions(+), 544 deletions(-) create mode 100644 src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h delete mode 100644 src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 9c37f1f98..5e54d0f56 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -109,7 +109,7 @@ #ifdef TUP_USBIP_FSDEV_STM32 // Undefine to reduce the dependence on HAL #undef USE_HAL_DRIVER - #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h" + #include "portable/st/stm32_fsdev/dcd_stm32_fsdev.h" #endif /***************************************************** diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h new file mode 100644 index 000000000..15de95d23 --- /dev/null +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h @@ -0,0 +1,543 @@ +/* + * Copyright(c) 2016 STMicroelectronics + * Copyright(c) N Conrad + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the TinyUSB stack. + */ + +// This file contains source copied from ST's HAL, and thus should have their copyright statement. + +// FSDEV_PMA_SIZE is PMA buffer size in bytes. +// On 512-byte devices, access with a stride of two words (use every other 16-bit address) +// On 1024-byte devices, access with a stride of one word (use every 16-bit address) + +#ifndef PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ +#define PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ + +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 + #include "stm32f0xx.h" + #define FSDEV_PMA_SIZE (1024u) + // F0x2 models are crystal-less + // All have internal D+ pull-up + // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support + // PMA dedicated to USB (no sharing with CAN) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 + #include "stm32f1xx.h" + #define FSDEV_PMA_SIZE (512u) + // NO internal Pull-ups + // *B, and *C: 2 x 16 bits/word + + // F1 names this differently from the rest + #define USB_CNTR_LPMODE USB_CNTR_LP_MODE + +#elif defined(STM32F302xB) || defined(STM32F302xC) || \ + defined(STM32F303xB) || defined(STM32F303xC) || \ + defined(STM32F373xC) + #include "stm32f3xx.h" + #define FSDEV_PMA_SIZE (512u) + // NO internal Pull-ups + // *B, and *C: 1 x 16 bits/word + // PMA dedicated to USB (no sharing with CAN) + +#elif defined(STM32F302x6) || defined(STM32F302x8) || \ + defined(STM32F302xD) || defined(STM32F302xE) || \ + defined(STM32F303xD) || defined(STM32F303xE) + #include "stm32f3xx.h" + #define FSDEV_PMA_SIZE (1024u) + // NO internal Pull-ups + // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support + // When CAN clock is enabled, USB can use first 768 bytes ONLY. + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 + #include "stm32l0xx.h" + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 + #include "stm32l1xx.h" + #define FSDEV_PMA_SIZE (512u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 + #include "stm32g4xx.h" + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #include "stm32g0xx.h" + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + #include "stm32h5xx.h" + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32WB + #include "stm32wbxx.h" + #define FSDEV_PMA_SIZE (1024u) + /* ST provided header has incorrect value */ + #undef USB_PMAADDR + #define USB_PMAADDR USB1_PMAADDR + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + #include "stm32l4xx.h" + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L5 + #include "stm32l5xx.h" + #define FSDEV_PMA_SIZE (1024u) + + #ifndef USB_PMAADDR + #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) + #endif + +#else + #error You are using an untested or unimplemented STM32 variant. Please update the driver. + // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 +#endif + +// For purposes of accessing the packet +#if ((FSDEV_PMA_SIZE) == 512u) + #define FSDEV_PMA_STRIDE (2u) +#elif ((FSDEV_PMA_SIZE) == 1024u) + #define FSDEV_PMA_STRIDE (1u) +#endif + +// The fsdev_bus_t type can be used for both register and PMA access necessities +// For type-safety create a new macro for the volatile address of PMAADDR +// The compiler should warn us if we cast it to a non-volatile type? +#ifdef FSDEV_BUS_32BIT +typedef uint32_t fsdev_bus_t; +static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR; + +#else +typedef uint16_t fsdev_bus_t; +// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) +static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; + +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) { + size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; + total_word_offset *= FSDEV_PMA_STRIDE; + return &(pma[total_word_offset]); +} + +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { + return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); +} + +TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { + return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); +} +#endif + +/* Aligned buffer size according to hardware */ +TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) { + /* The STM32 full speed USB peripheral supports only a limited set of + * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ + uint16_t blocksize = (size > 62) ? 32 : 2; + + // Round up while dividing requested size by blocksize + uint16_t numblocks = (size + blocksize - 1) / blocksize ; + + return numblocks * blocksize; +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4); + *reg = wRegValue; +#else + __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u); + *reg = (uint16_t)wRegValue; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + __I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4); +#else + __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u); +#endif + return *reg; +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= (uint32_t)USB_EP_T_MASK; + regVal |= wType; + regVal |= USB_EP_CTR_RX | USB_EP_CTR_TX; // These clear on write0, so must set high + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EP_T_FIELD; + return regVal; +} + +/** + * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @retval None + */ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPREG_MASK; + regVal &= ~USB_EP_CTR_RX; + regVal |= USB_EP_CTR_TX; // preserve CTR_TX (clears on writing 0) + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPREG_MASK; + regVal &= ~USB_EP_CTR_TX; + regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0) + pcd_set_endpoint(USBx, bEpIdx,regVal); +} + +/** + * @brief gets counter of the tx buffer. + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @retval Counter value + */ +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; +#else + __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); + return *regPtr & 0x3ffU; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + /* WA: few cycles for RX PMA descriptor to update, otherwise doesn't return the correct value. + Note: required for G0, U5, H5 etc. + This workaround is ported from stm32h5xx_hal_pcd.h and fixes the issue when calling this function fast enough. + Reproduced with GCC ast optimization(O2/O3) and stm32h573i_dk with an high frequency. + Observed on Windows 10 where tud_task() is scheduled by interrupt handler. + */ + volatile uint32_t count = 10; // defined as PCD_RX_PMA_CNT in stm32 hal_driver + while (count > 0U) { + count--; + } + return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; +#else + __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); + return *regPtr & 0x3ffU; +#endif +} + +/** + * @brief Sets address in an endpoint register. + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @param bAddr Address. + * @retval None + */ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPREG_MASK; + regVal |= bAddr; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpIdx,regVal); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return pma32[2*bEpIdx] & 0x0000FFFFu ; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + return pma32[2*bEpIdx + 1] & 0x0000FFFFu; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#else + *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#else + *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); +#else + __IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); + *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); +#else + __IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); + *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, + uint32_t blocksize, uint32_t numblocks) { + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ +#ifdef FSDEV_BUS_32BIT + (void) USBx; + pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26); +#else + __IO uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u); + *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) { + wCount = pcd_aligned_buffer_size(wCount); + + /* We assume that the buffer size is already aligned to hardware requirements. */ + uint16_t blocksize = (wCount > 62) ? 1 : 0; + uint16_t numblocks = wCount / (blocksize ? 32 : 2); + + /* There should be no remainder in the above calculation */ + TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); + + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ + pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { + pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { + pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount); +} + +/** + * @brief sets the status for tx transfer (bits STAT_TX[1:0]). + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @param wState new state + * @retval None + */ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPTX_DTOGMASK; + + /* toggle first bit ? */ + if((USB_EPTX_DTOG1 & (wState))!= 0U) + { + regVal ^= USB_EPTX_DTOG1; + } + /* toggle second bit ? */ + if((USB_EPTX_DTOG2 & ((uint32_t)(wState)))!= 0U) + { + regVal ^= USB_EPTX_DTOG2; + } + + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +/** + * @brief sets the status for rx transfer (bits STAT_TX[1:0]) + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @param wState new state + * @retval None + */ + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPRX_DTOGMASK; + + /* toggle first bit ? */ + if((USB_EPRX_DTOG1 & wState)!= 0U) { + regVal ^= USB_EPRX_DTOG1; + } + /* toggle second bit ? */ + if((USB_EPRX_DTOG2 & wState)!= 0U) { + regVal ^= USB_EPRX_DTOG2; + } + + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + return (regVal & USB_EPRX_STAT) >> (12u); +} + + +/** + * @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register. + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @retval None + */ +TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPREG_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX; + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPREG_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX; + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +/** + * @brief Clears DTOG_RX / DTOG_TX bit in the endpoint register. + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @retval None + */ +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + if((regVal & USB_EP_DTOG_RX) != 0) { + pcd_rx_dtog(USBx,bEpIdx); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + if((regVal & USB_EP_DTOG_TX) != 0) { + pcd_tx_dtog(USBx,bEpIdx); + } +} + +/** + * @brief set & clear EP_KIND bit. + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @retval None + */ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal |= USB_EP_KIND; + regVal &= USB_EPREG_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPKIND_MASK; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpIdx, regVal); +} + +// This checks if the device has "LPM" +#if defined(USB_ISTR_L1REQ) +#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ) +#else +#define USB_ISTR_L1REQ_FORCED ((uint16_t)0x0000U) +#endif + +#define USB_ISTR_ALL_EVENTS (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | \ + USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED ) + +// Number of endpoints in hardware +// TODO should use TUP_DCD_ENDPOINT_MAX +#define STFSDEV_EP_COUNT (8u) + +#endif /* PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ */ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h deleted file mode 100644 index 15de95d23..000000000 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright(c) 2016 STMicroelectronics - * Copyright(c) N Conrad - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the TinyUSB stack. - */ - -// This file contains source copied from ST's HAL, and thus should have their copyright statement. - -// FSDEV_PMA_SIZE is PMA buffer size in bytes. -// On 512-byte devices, access with a stride of two words (use every other 16-bit address) -// On 1024-byte devices, access with a stride of one word (use every 16-bit address) - -#ifndef PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ -#define PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ - -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 - #include "stm32f0xx.h" - #define FSDEV_PMA_SIZE (1024u) - // F0x2 models are crystal-less - // All have internal D+ pull-up - // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support - // PMA dedicated to USB (no sharing with CAN) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - #define FSDEV_PMA_SIZE (512u) - // NO internal Pull-ups - // *B, and *C: 2 x 16 bits/word - - // F1 names this differently from the rest - #define USB_CNTR_LPMODE USB_CNTR_LP_MODE - -#elif defined(STM32F302xB) || defined(STM32F302xC) || \ - defined(STM32F303xB) || defined(STM32F303xC) || \ - defined(STM32F373xC) - #include "stm32f3xx.h" - #define FSDEV_PMA_SIZE (512u) - // NO internal Pull-ups - // *B, and *C: 1 x 16 bits/word - // PMA dedicated to USB (no sharing with CAN) - -#elif defined(STM32F302x6) || defined(STM32F302x8) || \ - defined(STM32F302xD) || defined(STM32F302xE) || \ - defined(STM32F303xD) || defined(STM32F303xE) - #include "stm32f3xx.h" - #define FSDEV_PMA_SIZE (1024u) - // NO internal Pull-ups - // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support - // When CAN clock is enabled, USB can use first 768 bytes ONLY. - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 - #include "stm32l0xx.h" - #define FSDEV_PMA_SIZE (1024u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 - #include "stm32l1xx.h" - #define FSDEV_PMA_SIZE (512u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 - #include "stm32g4xx.h" - #define FSDEV_PMA_SIZE (1024u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #include "stm32g0xx.h" - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 - #include "stm32h5xx.h" - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN - -#elif CFG_TUSB_MCU == OPT_MCU_STM32WB - #include "stm32wbxx.h" - #define FSDEV_PMA_SIZE (1024u) - /* ST provided header has incorrect value */ - #undef USB_PMAADDR - #define USB_PMAADDR USB1_PMAADDR - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - #define FSDEV_PMA_SIZE (1024u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L5 - #include "stm32l5xx.h" - #define FSDEV_PMA_SIZE (1024u) - - #ifndef USB_PMAADDR - #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) - #endif - -#else - #error You are using an untested or unimplemented STM32 variant. Please update the driver. - // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 -#endif - -// For purposes of accessing the packet -#if ((FSDEV_PMA_SIZE) == 512u) - #define FSDEV_PMA_STRIDE (2u) -#elif ((FSDEV_PMA_SIZE) == 1024u) - #define FSDEV_PMA_STRIDE (1u) -#endif - -// The fsdev_bus_t type can be used for both register and PMA access necessities -// For type-safety create a new macro for the volatile address of PMAADDR -// The compiler should warn us if we cast it to a non-volatile type? -#ifdef FSDEV_BUS_32BIT -typedef uint32_t fsdev_bus_t; -static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR; - -#else -typedef uint16_t fsdev_bus_t; -// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) -static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; - -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) { - size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; - total_word_offset *= FSDEV_PMA_STRIDE; - return &(pma[total_word_offset]); -} - -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); -} - -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); -} -#endif - -/* Aligned buffer size according to hardware */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) { - /* The STM32 full speed USB peripheral supports only a limited set of - * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ - uint16_t blocksize = (size > 62) ? 32 : 2; - - // Round up while dividing requested size by blocksize - uint16_t numblocks = (size + blocksize - 1) / blocksize ; - - return numblocks * blocksize; -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4); - *reg = wRegValue; -#else - __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u); - *reg = (uint16_t)wRegValue; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - __I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4); -#else - __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u); -#endif - return *reg; -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= (uint32_t)USB_EP_T_MASK; - regVal |= wType; - regVal |= USB_EP_CTR_RX | USB_EP_CTR_TX; // These clear on write0, so must set high - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EP_T_FIELD; - return regVal; -} - -/** - * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal &= ~USB_EP_CTR_RX; - regVal |= USB_EP_CTR_TX; // preserve CTR_TX (clears on writing 0) - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal &= ~USB_EP_CTR_TX; - regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0) - pcd_set_endpoint(USBx, bEpIdx,regVal); -} - -/** - * @brief gets counter of the tx buffer. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval Counter value - */ -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; -#else - __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); - return *regPtr & 0x3ffU; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - /* WA: few cycles for RX PMA descriptor to update, otherwise doesn't return the correct value. - Note: required for G0, U5, H5 etc. - This workaround is ported from stm32h5xx_hal_pcd.h and fixes the issue when calling this function fast enough. - Reproduced with GCC ast optimization(O2/O3) and stm32h573i_dk with an high frequency. - Observed on Windows 10 where tud_task() is scheduled by interrupt handler. - */ - volatile uint32_t count = 10; // defined as PCD_RX_PMA_CNT in stm32 hal_driver - while (count > 0U) { - count--; - } - return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; -#else - __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); - return *regPtr & 0x3ffU; -#endif -} - -/** - * @brief Sets address in an endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @param bAddr Address. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal |= bAddr; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx,regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - return pma32[2*bEpIdx] & 0x0000FFFFu ; -#else - return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - return pma32[2*bEpIdx + 1] & 0x0000FFFFu; -#else - return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu); -#else - *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu); -#else - *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); -#else - __IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); - *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); -#else - __IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); - *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, - uint32_t blocksize, uint32_t numblocks) { - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ -#ifdef FSDEV_BUS_32BIT - (void) USBx; - pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26); -#else - __IO uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u); - *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) { - wCount = pcd_aligned_buffer_size(wCount); - - /* We assume that the buffer size is already aligned to hardware requirements. */ - uint16_t blocksize = (wCount > 62) ? 1 : 0; - uint16_t numblocks = wCount / (blocksize ? 32 : 2); - - /* There should be no remainder in the above calculation */ - TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); - - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { - pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { - pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount); -} - -/** - * @brief sets the status for tx transfer (bits STAT_TX[1:0]). - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @param wState new state - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPTX_DTOGMASK; - - /* toggle first bit ? */ - if((USB_EPTX_DTOG1 & (wState))!= 0U) - { - regVal ^= USB_EPTX_DTOG1; - } - /* toggle second bit ? */ - if((USB_EPTX_DTOG2 & ((uint32_t)(wState)))!= 0U) - { - regVal ^= USB_EPTX_DTOG2; - } - - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -/** - * @brief sets the status for rx transfer (bits STAT_TX[1:0]) - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @param wState new state - * @retval None - */ - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPRX_DTOGMASK; - - /* toggle first bit ? */ - if((USB_EPRX_DTOG1 & wState)!= 0U) { - regVal ^= USB_EPRX_DTOG1; - } - /* toggle second bit ? */ - if((USB_EPRX_DTOG2 & wState)!= 0U) { - regVal ^= USB_EPRX_DTOG2; - } - - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - return (regVal & USB_EPRX_STAT) >> (12u); -} - - -/** - * @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -/** - * @brief Clears DTOG_RX / DTOG_TX bit in the endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_RX) != 0) { - pcd_rx_dtog(USBx,bEpIdx); - } -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_TX) != 0) { - pcd_tx_dtog(USBx,bEpIdx); - } -} - -/** - * @brief set & clear EP_KIND bit. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal |= USB_EP_KIND; - regVal &= USB_EPREG_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPKIND_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -// This checks if the device has "LPM" -#if defined(USB_ISTR_L1REQ) -#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ) -#else -#define USB_ISTR_L1REQ_FORCED ((uint16_t)0x0000U) -#endif - -#define USB_ISTR_ALL_EVENTS (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | \ - USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED ) - -// Number of endpoints in hardware -// TODO should use TUP_DCD_ENDPOINT_MAX -#define STFSDEV_EP_COUNT (8u) - -#endif /* PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ */ -- cgit v1.3.1