From 410ad4d0f9ff166610655bae31328e4120b17ef2 Mon Sep 17 00:00:00 2001 From: Hubert Denkmair Date: Wed, 8 Mar 2023 12:05:58 +0100 Subject: add basic STM32G0 support --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 86 +++++++--- .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 180 +++++++++++++++------ 2 files changed, 198 insertions(+), 68 deletions(-) (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 e49c0b52e..21ae8e6e8 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -216,7 +216,7 @@ TU_ATTR_ALWAYS_INLINE static inline void reg16_clear_bits(__IO uint16_t *reg, ui } // Bits in ISTR are cleared upon writing 0 -TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint16_t mask) { +TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint32_t mask) { USB->ISTR = ~mask; } @@ -242,16 +242,23 @@ void dcd_init (uint8_t rhport) { asm("NOP"); } + +#ifdef PMA_32BIT_ACCESS // CNTR register is 32bits on STM32G0, 16bit on older versions + USB->CNTR &= ~USB_CNTR_PDWN; +#else reg16_clear_bits(&USB->CNTR, USB_CNTR_PDWN);// Remove powerdown +#endif + // Wait startup time, for F042 and F070, this is <= 1 us. for(uint32_t i = 0; i<200; i++) // should be a few us { asm("NOP"); } USB->CNTR = 0; // Enable USB - - USB->BTABLE = DCD_STM32_BTABLE_BASE; +#ifndef STM32G0 // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address + USB->BTABLE = DCD_STM32_BTABLE_BASE; +#endif USB->ISTR = 0; // Clear pending interrupts // Reset endpoints to disabled @@ -312,7 +319,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) } else { - USB->CNTR &= (uint16_t) ~USB_CNTR_SOFM; + USB->CNTR &= ~USB_CNTR_SOFM; } } @@ -358,6 +365,9 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USB_LP_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + NVIC_EnableIRQ(USB_UCPD1_2_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_EnableIRQ(USB_HP_IRQn); NVIC_EnableIRQ(USB_LP_IRQn); @@ -405,6 +415,9 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_LP_IRQn); NVIC_DisableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + NVIC_DisableIRQ(USB_UCPD1_2_IRQn); + #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_DisableIRQ(USB_HP_IRQn); NVIC_DisableIRQ(USB_LP_IRQn); @@ -433,7 +446,7 @@ void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - USB->CNTR |= (uint16_t) USB_CNTR_RESUME; + USB->CNTR |= USB_CNTR_RESUME; remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } @@ -534,9 +547,6 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */ { - // The setup_received function uses memcpy, so this must first copy the setup data into - // user memory, to allow for the 32-bit access that memcpy performs. - uint8_t userMemBuf[8]; uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex); /* Get SETUP Packet*/ if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again. @@ -544,8 +554,15 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) // Must reset EP to NAK (in case it had been stalling) (though, maybe too late here) pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK); pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK); - dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8); +#ifdef PMA_32BIT_ACCESS + dcd_event_setup_received(0, (uint8_t*)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true); +#else + // The setup_received function uses memcpy, so this must first copy the setup data into + // user memory, to allow for the 32-bit access that memcpy performs. + uint8_t userMemBuf[8]; + dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB,EPindex), 8); dcd_event_setup_received(0, (uint8_t*)userMemBuf, true); +#endif } } else @@ -568,7 +585,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if (count != 0U) { - uint16_t addr = *pcd_ep_rx_address_ptr(USB, EPindex); + uint16_t addr = pcd_get_ep_rx_address(USB, EPindex); if (xfer->ff) { @@ -672,8 +689,13 @@ void dcd_int_handler(uint8_t rhport) { if (int_status & USB_ISTR_WKUP) { +#ifdef PMA_32BIT_ACCESS // CNTR register is 32bits on STM32G0, 16bit on older versions + USB->CNTR &= ~USB_CNTR_LPMODE; + USB->CNTR &= ~USB_CNTR_FSUSP; +#else reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE); reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP); +#endif clear_istr_bits(USB_ISTR_WKUP); dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } @@ -695,7 +717,7 @@ void dcd_int_handler(uint8_t rhport) { if(int_status & USB_ISTR_ESOF) { if(remoteWakeCountdown == 1u) { - USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME); + USB->CNTR &= ~USB_CNTR_RESUME; } if(remoteWakeCountdown > 0u) { @@ -722,8 +744,13 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re uint8_t const dev_addr = (uint8_t) request->wValue; // Setting new address after the whole request is complete +#ifdef PMA_32BIT_ACCESS + USB->DADDR &= ~USB_DADDR_ADD; + USB->DADDR = (USB->DADDR & ~USB_DADDR_ADD_Msk) | dev_addr; // leave the enable bit set +#else reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD); USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set +#endif } } @@ -925,14 +952,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc if( (dir == TUSB_DIR_IN) || (wType == USB_EP_ISOCHRONOUS) ) { - *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr; + pcd_set_ep_tx_address(USB, ep_idx, pma_addr); pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size); pcd_clear_tx_dtog(USB, ep_idx); } if( (dir == TUSB_DIR_OUT) || (wType == USB_EP_ISOCHRONOUS) ) { - *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr; + pcd_set_ep_rx_address(USB, ep_idx, pma_addr); pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size); pcd_clear_rx_dtog(USB, ep_idx); } @@ -1011,10 +1038,10 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); - - *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr; - *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr; - + + pcd_set_ep_tx_address(USB, ep_idx, pma_addr); + pcd_set_ep_rx_address(USB, ep_idx, pma_addr); + return true; } @@ -1063,7 +1090,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) } uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix); - uint16_t addr_ptr = *pcd_ep_tx_address_ptr(USB,ep_ix); + uint16_t addr_ptr = pcd_get_ep_tx_address(USB, ep_ix); if (xfer->ff) { @@ -1197,6 +1224,19 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) } } +#ifdef PMA_32BIT_ACCESS +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes) +{ + // FIXME original function uses byte-access to source memory (to support non-aligned buffers) + const uint32_t* src32 = (uint32_t*)(src); + uint32_t* dst32 = (uint32_t*)(USB_PMAADDR + dst); + for (unsigned n=wNBytes/4; n>0; --n) { + *dst32++ = *src32++; + } + *dst32 = (*src32) & ((1<<8*(wNBytes % 4)) - 1); + return true; +} +#else // Packet buffer access can only be 8- or 16-bit. /** * @brief Copy a buffer from user memory area to packet memory area (PMA). @@ -1239,6 +1279,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si return true; } +#endif /** * @brief Copy from FIFO to packet memory area (PMA). @@ -1290,6 +1331,14 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN return true; } +#ifdef PMA_32BIT_ACCESS +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes) +{ + // FIXME this should probably be modified for possible unaligned access? + memcpy(dst, (void*)(USB_PMAADDR+src), wNBytes); + return true; +} +#else /** * @brief Copy a buffer from packet memory area (PMA) to user memory area. * Uses byte-access of system memory and 16-bit access of packet memory @@ -1323,6 +1372,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN } return true; } +#endif /** * @brief Copy a buffer from user packet memory area (PMA) to FIFO. 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 index 015b177cf..686bfaa66 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -82,6 +82,34 @@ #include "stm32g4xx.h" #define PMA_LENGTH (1024u) +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #include "STM32/stm32g0xx.h" + #define PMA_32BIT_ACCESS + #define PMA_LENGTH (1024u) // FIXME it is 2048, really + #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 PMA_LENGTH (1024u) @@ -105,15 +133,31 @@ #define PMA_STRIDE (1u) #endif -// And for type-safety create a new macro for the volatile address of PMAADDR +// 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 PMA_32BIT_ACCESS +static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR; +#else // 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; -// prototypes -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx); -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx); -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue); +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 *= 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) @@ -131,13 +175,22 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si /* SetENDPOINT */ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { +#ifdef PMA_32BIT_ACCESS + __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 } /* GetENDPOINT */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef PMA_32BIT_ACCESS + __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; } @@ -187,34 +240,22 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, */ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { +#ifdef PMA_32BIT_ACCESS + 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 PMA_32BIT_ACCESS + return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; +#else __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); return *regPtr & 0x3ffU; -} - -/** - * @brief Sets counter of rx buffer with no. of blocks. - * @param dwReg Register - * @param wCount Counter. - * @param wNBlocks no. of Blocks. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwReg, size_t 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 */ - *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); +#endif } /** @@ -233,57 +274,96 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { - size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; - total_word_offset *= PMA_STRIDE; - return &(pma[total_word_offset]); +#ifdef PMA_32BIT_ACCESS + return pma32[2*bEpIdx] & 0x0000FFFFu ; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); +#endif } -// Pointers to the PMA table entries (using the ARM address space) -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); -} -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); +#ifdef PMA_32BIT_ACCESS + return pma32[2*bEpIdx + 1] & 0x0000FFFFu; +#else + return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); +#endif } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); +#ifdef PMA_32BIT_ACCESS + 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 __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); +#ifdef PMA_32BIT_ACCESS + 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) +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef PMA_32BIT_ACCESS + 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) +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { +#ifdef PMA_32BIT_ACCESS + 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_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) +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) { - __IO uint16_t *pdwReg = pcd_ep_tx_cnt_ptr((USBx),(bEpIdx)); - wCount = pcd_aligned_buffer_size(wCount); - pcd_set_ep_cnt_reg(pdwReg, wCount); + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ +#ifdef PMA_32BIT_ACCESS + 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_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) { - __IO uint16_t *pdwReg = pcd_ep_rx_cnt_ptr((USBx),(bEpIdx)); wCount = pcd_aligned_buffer_size(wCount); - pcd_set_ep_cnt_reg(pdwReg, 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); } /** -- cgit v1.3.1 From 8ae4f8f0699351e5bba349ccb0fab65b557afed6 Mon Sep 17 00:00:00 2001 From: Hubert Denkmair Date: Wed, 8 Mar 2023 12:05:58 +0100 Subject: add basic STM32G0 support --- src/common/tusb_mcu.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 257d08a85..957df5e9e 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -191,6 +191,11 @@ #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_STM32G0) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 + #elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 -- cgit v1.3.1 From b3ad560e629be18146fd52e32235cc2ed72dc70b Mon Sep 17 00:00:00 2001 From: Hubert Denkmair Date: Wed, 8 Mar 2023 14:22:11 +0100 Subject: fix path to stm32g0xx.h --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') 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 index 686bfaa66..00791eeb7 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -83,7 +83,7 @@ #define PMA_LENGTH (1024u) #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #include "STM32/stm32g0xx.h" + #include "stm32g0xx.h" #define PMA_32BIT_ACCESS #define PMA_LENGTH (1024u) // FIXME it is 2048, really #undef USB_PMAADDR -- cgit v1.3.1 From f8a21fff171aa272360c89dab5faca4f688a656a Mon Sep 17 00:00:00 2001 From: Hubert Denkmair Date: Sun, 12 Mar 2023 15:51:07 +0100 Subject: dcd_write_packet_memory: use volatile modifier for destination pointer --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (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 21ae8e6e8..e2e1cf484 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -1228,8 +1228,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes) { // FIXME original function uses byte-access to source memory (to support non-aligned buffers) - const uint32_t* src32 = (uint32_t*)(src); - uint32_t* dst32 = (uint32_t*)(USB_PMAADDR + dst); + const uint32_t* src32 = (const uint32_t*)(src); + volatile uint32_t* dst32 = (volatile uint32_t*)(USB_PMAADDR + dst); for (unsigned n=wNBytes/4; n>0; --n) { *dst32++ = *src32++; } -- cgit v1.3.1 From 413b0a7da5b9ef1e519e4087a577bfc6d6681d97 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 14 Apr 2023 17:12:47 +0200 Subject: Use PLL clock. --- hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.h | 38 +++++++++++---------------- hw/bsp/stm32g0/family.c | 14 +++------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 + 3 files changed, 21 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.h b/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.h index 3f5bc60b7..60357d1e8 100644 --- a/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.h +++ b/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.h @@ -62,7 +62,7 @@ static inline void board_clock_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_CRSInitTypeDef pInit = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 }; /** Tick priority is used in HAL_RCC_OscConfig, so we need to enable it now */ @@ -75,38 +75,32 @@ static inline void board_clock_init(void) /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI48; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; - RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1; + RCC_OscInitStruct.PLL.PLLN = 12; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; HAL_RCC_OscConfig(&RCC_OscInitStruct); + /* Select HSI48 as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0); - /** Enable the SYSCFG APB clock - */ - __HAL_RCC_CRS_CLK_ENABLE(); - - /** Configures CRS - */ - pInit.Prescaler = RCC_CRS_SYNC_DIV1; - pInit.Source = RCC_CRS_SYNC_SOURCE_USB; - pInit.Polarity = RCC_CRS_SYNC_POLARITY_RISING; - pInit.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000); - pInit.ErrorLimitValue = 34; - pInit.HSI48CalibrationValue = 32; - - HAL_RCCEx_CRSConfig(&pInit); } #ifdef __cplusplus diff --git a/hw/bsp/stm32g0/family.c b/hw/bsp/stm32g0/family.c index 585398974..be356efe9 100644 --- a/hw/bsp/stm32g0/family.c +++ b/hw/bsp/stm32g0/family.c @@ -53,6 +53,9 @@ void board_init(void) __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + UART_CLK_EN(); #if CFG_TUSB_OS == OPT_OS_NONE @@ -119,16 +122,7 @@ void board_init(void) __HAL_RCC_USB_CLK_ENABLE(); /* Enable VDDUSB */ - if(__HAL_RCC_PWR_IS_CLK_DISABLED()) - { - __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWREx_EnableVddUSB(); - __HAL_RCC_PWR_CLK_DISABLE(); - } - else - { - HAL_PWREx_EnableVddUSB(); - } + HAL_PWREx_EnableVddUSB(); } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 36b9133be..23b328b49 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -44,6 +44,7 @@ * L0x2, L0x3 1024 byte buffer * L1 512 byte buffer * L4x2, L4x3 1024 byte buffer + * G0 2048 byte buffer * * To use this driver, you must: * - If you are using a device with crystal-less USB, set up the clock recovery system (CRS) -- cgit v1.3.1 From 2f2c8ce9ec4a567603cbd5e0420fc3dcaffbdfb6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 14 Apr 2023 17:54:25 +0200 Subject: Fix GCC build. --- hw/bsp/board_mcu.h | 3 +++ hw/bsp/stm32g0/family.mk | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 12 ++++++++++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 11 +++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index cd195a19b..6d40aa0d1 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -101,6 +101,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #include "stm32g0xx.h" + #elif CFG_TUSB_MCU == OPT_MCU_CXD56 // no header needed diff --git a/hw/bsp/stm32g0/family.mk b/hw/bsp/stm32g0/family.mk index faf92dca9..76f59fc34 100644 --- a/hw/bsp/stm32g0/family.mk +++ b/hw/bsp/stm32g0/family.mk @@ -51,7 +51,7 @@ INC += \ $(TOP)/$(ST_HAL_DRIVER)/Inc # For freeRTOS port source -FREERTOS_PORT = ARM_CM0 +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 # flash target using on-board stlink flash: flash-stlink diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 23b328b49..32bab2bed 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -367,7 +367,11 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USBWakeUp_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - NVIC_EnableIRQ(USB_UCPD1_2_IRQn); + #ifdef STM32G0B0xx + NVIC_EnableIRQ(USB_IRQn); + #else + NVIC_EnableIRQ(USB_UCPD1_2_IRQn); + #endif #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_EnableIRQ(USB_HP_IRQn); @@ -420,7 +424,11 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USBWakeUp_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - NVIC_DisableIRQ(USB_UCPD1_2_IRQn); + #ifdef STM32G0B0xx + NVIC_DisableIRQ(USB_IRQn); + #else + NVIC_DisableIRQ(USB_UCPD1_2_IRQn); + #endif #elif CFG_TUSB_MCU == OPT_MCU_STM32WB NVIC_DisableIRQ(USB_HP_IRQn); 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 index c0f923c8f..32f715e6e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -184,6 +184,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { #ifdef PMA_32BIT_ACCESS + (void) USBx; __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4); *reg = wRegValue; #else @@ -195,6 +196,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, ui /* GetENDPOINT */ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { #ifdef PMA_32BIT_ACCESS + (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); @@ -249,6 +251,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { #ifdef PMA_32BIT_ACCESS + (void) USBx; return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; #else __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); @@ -259,6 +262,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USB TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { #ifdef PMA_32BIT_ACCESS + (void) USBx; return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; #else __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); @@ -285,6 +289,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { #ifdef PMA_32BIT_ACCESS + (void) USBx; return pma32[2*bEpIdx] & 0x0000FFFFu ; #else return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); @@ -294,6 +299,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { #ifdef PMA_32BIT_ACCESS + (void) USBx; return pma32[2*bEpIdx + 1] & 0x0000FFFFu; #else return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); @@ -303,6 +309,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { #ifdef PMA_32BIT_ACCESS + (void) USBx; pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu); #else *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr; @@ -312,6 +319,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USB TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { #ifdef PMA_32BIT_ACCESS + (void) USBx; pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu); #else *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr; @@ -321,6 +329,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USB TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { #ifdef PMA_32BIT_ACCESS + (void) USBx; pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); #else __IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); @@ -331,6 +340,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, u TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { #ifdef PMA_32BIT_ACCESS + (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); @@ -342,6 +352,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDe { /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ #ifdef PMA_32BIT_ACCESS + (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); -- cgit v1.3.1 From 818bda18c23e17c08c689b543d77ecc944681dea Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 14 Apr 2023 23:34:20 +0200 Subject: Fix FIFO transfer and buffer alignment. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 166 +++++++++++++++++---- .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 2 +- 2 files changed, 142 insertions(+), 26 deletions(-) (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 32bab2bed..b8d04331a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -186,12 +186,12 @@ static void dcd_ep_ctr_handler(void); static uint8_t open_ep_count; static uint16_t ep_buf_ptr; ///< Points to first free memory location static void dcd_pma_alloc_reset(void); -static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length); +static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length); static void dcd_pma_free(uint8_t ep_addr); static void dcd_ep_free(uint8_t ep_addr); static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes); -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes); +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes); static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes); static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes); @@ -792,7 +792,7 @@ static void dcd_pma_alloc_reset(void) * * During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually. */ -static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length) +static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length) { xfer_ctl_t* epXferCtl = xfer_ctl_ptr(ep_addr); @@ -804,6 +804,13 @@ static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length) return epXferCtl->pma_ptr; } + // Ensure allocated buffer is aligned +#ifdef PMA_32BIT_ACCESS + length = (length + 3) & ~0x03; +#else + length = (length + 1) & ~0x01; +#endif + open_ep_count++; uint16_t addr = ep_buf_ptr; @@ -814,7 +821,7 @@ static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length) epXferCtl->pma_ptr = addr; epXferCtl->pma_alloc_size = length; - //TU_LOG2("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr); + //TU_LOG1("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr); return addr; } @@ -1240,15 +1247,36 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) } #ifdef PMA_32BIT_ACCESS -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes) +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { - // FIXME original function uses byte-access to source memory (to support non-aligned buffers) - const uint32_t* src32 = (const uint32_t*)(src); + const uint8_t* srcVal = src; volatile uint32_t* dst32 = (volatile uint32_t*)(USB_PMAADDR + dst); - for (unsigned n=wNBytes/4; n>0; --n) { - *dst32++ = *src32++; + + for (uint32_t n = wNBytes / 4; n > 0; --n) { + *dst32++ = tu_unaligned_read32(srcVal); + srcVal += 4; + } + + wNBytes = wNBytes & 0x03; + if (wNBytes) + { + uint32_t wrVal = *srcVal; + wNBytes--; + + if (wNBytes) + { + wrVal |= *++srcVal << 8; + wNBytes--; + + if (wNBytes) + { + wrVal |= *++srcVal << 16; + } + } + + *dst32 = wrVal; } - *dst32 = (*src32) & ((1<<8*(wNBytes % 4)) - 1); + return true; } #else @@ -1263,7 +1291,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si * @param wNBytes no. of bytes to be copied. * @retval None */ -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes) +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; uint16_t temp1, temp2; @@ -1286,7 +1314,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si srcVal++; } - if (wNBytes & 0x01) + if (wNBytes) { temp1 = *srcVal; *pdwVal = temp1; @@ -1313,7 +1341,37 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, // last lin byte will be combined with wrapped part - // To ensure PMA is always access 16bit aligned (dst aligned to 16 bit) + // To ensure PMA is always access aligned (dst aligned to 16 or 32 bit) +#ifdef PMA_32BIT_ACCESS + if((cnt_lin & 0x03) && cnt_wrap) + { + // Copy first linear part + dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin &~0x03); + dst += cnt_lin &~0x03; + + // Copy last linear bytes & first wrapped bytes to buffer + uint32_t i; + uint8_t tmp[4]; + for (i = 0; i < (cnt_lin & 0x03); i++) + { + tmp[i] = ((uint8_t*)info.ptr_lin)[(cnt_lin &~0x03) + i]; + } + uint32_t wCnt = cnt_wrap; + for (; i < 4 && wCnt > 0; i++, wCnt--) + { + tmp[i] = *(uint8_t*)info.ptr_wrap; + info.ptr_wrap = (uint8_t*)info.ptr_wrap + 1; + } + + // Write unaligned buffer + dcd_write_packet_memory(dst, &tmp, 4); + dst += 4; + + // Copy rest of wrapped byte + if (wCnt) + dcd_write_packet_memory(dst, info.ptr_wrap, wCnt); + } +#else if((cnt_lin & 0x01) && cnt_wrap) { // Copy first linear part @@ -1328,6 +1386,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN // Copy rest of wrapped byte dcd_write_packet_memory(dst, ((uint8_t*)info.ptr_wrap) + 1, cnt_wrap - 1); } +#endif else { // Copy linear part @@ -1347,11 +1406,37 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN } #ifdef PMA_32BIT_ACCESS -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes) +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { - // FIXME this should probably be modified for possible unaligned access? - memcpy(dst, (void*)(USB_PMAADDR+src), wNBytes); - return true; + uint8_t* dstVal = dst; + volatile uint32_t* src32 = (volatile uint32_t*)(USB_PMAADDR + src); + + for (uint32_t n = wNBytes / 4; n > 0; --n) { + tu_unaligned_write32(dstVal, *src32++); + dstVal += 4; + } + + wNBytes = wNBytes & 0x03; + if (wNBytes) + { + uint32_t rdVal = *src32; + + *dstVal = tu_u32_byte0(rdVal); + wNBytes--; + + if (wNBytes) + { + *++dstVal = tu_u32_byte1(rdVal); + wNBytes--; + + if (wNBytes) + { + *++dstVal = tu_u32_byte2(rdVal); + } + } + } + + return true; } #else /** @@ -1360,7 +1445,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN * @param wNBytes no. of bytes to be copied. * @retval None */ -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes) +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; // The GCC optimizer will combine access to 32-bit sizes if we let it. Force @@ -1405,9 +1490,39 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); + // We want to read from PMA and write it into the FIFO, if LIN part is ODD and has WRAPPED part, // last lin byte will be combined with wrapped part - // To ensure PMA is always access 16bit aligned (src aligned to 16 bit) + // To ensure PMA is always access aligned (src aligned to 16 or 32 bit) +#ifdef PMA_32BIT_ACCESS + if((cnt_lin & 0x03) && cnt_wrap) + { + // Copy first linear part + dcd_read_packet_memory(info.ptr_lin, src, cnt_lin &~0x03); + src += cnt_lin &~0x03; + + // Copy last linear bytes & first wrapped bytes + uint8_t tmp[4]; + dcd_read_packet_memory(tmp, src, 4); + src += 4; + + uint32_t i; + for (i = 0; i < (cnt_lin & 0x03); i++) + { + ((uint8_t*)info.ptr_lin)[(cnt_lin &~0x03) + i] = tmp[i]; + } + uint32_t wCnt = cnt_wrap; + for (; i < 4 && wCnt > 0; i++, wCnt--) + { + *(uint8_t*)info.ptr_wrap = tmp[i]; + info.ptr_wrap = (uint8_t*)info.ptr_wrap + 1; + } + + // Copy rest of wrapped byte + if (wCnt) + dcd_read_packet_memory(info.ptr_wrap, src, wCnt); + } +#else if((cnt_lin & 0x01) && cnt_wrap) { // Copy first linear part @@ -1415,16 +1530,17 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB src += cnt_lin &~0x01; // Copy last linear byte & first wrapped byte - uint16_t tmp; - dcd_read_packet_memory(&tmp, src, 2); - - ((uint8_t*)info.ptr_lin)[cnt_lin - 1] = (uint8_t)tmp; - ((uint8_t*)info.ptr_wrap)[0] = (uint8_t)(tmp >> 8U); + uint8_t tmp[2]; + dcd_read_packet_memory(tmp, src, 2); src += 2; + ((uint8_t*)info.ptr_lin)[cnt_lin - 1] = tmp[0]; + ((uint8_t*)info.ptr_wrap)[0] = tmp[1]; + // Copy rest of wrapped byte dcd_read_packet_memory(((uint8_t*)info.ptr_wrap) + 1, src, cnt_wrap - 1); } +#endif else { // Copy linear part 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 index 32f715e6e..e6649de5a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -85,7 +85,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #include "stm32g0xx.h" #define PMA_32BIT_ACCESS - #define PMA_LENGTH (1024u) // FIXME it is 2048, really + #define PMA_LENGTH (2048u) #undef USB_PMAADDR #define USB_PMAADDR USB_DRD_PMAADDR #define USB_TypeDef USB_DRD_TypeDef -- cgit v1.3.1 From 412b557a080526fbfe7b42dd8aa07468c16413cc Mon Sep 17 00:00:00 2001 From: Mengsk Date: Mon, 17 Apr 2023 15:34:20 +0200 Subject: Cleanup unnecessary code for 16bit access. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 39 +++++---------------------- 1 file changed, 7 insertions(+), 32 deletions(-) (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 b8d04331a..14cabaf8d 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -210,17 +210,6 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr) return &xfer_status[epnum][dir]; } -// Using a function due to better type checks -// This seems better than having to do type casts everywhere else -TU_ATTR_ALWAYS_INLINE static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { - *reg = (uint16_t)(*reg & ~mask); -} - -// Bits in ISTR are cleared upon writing 0 -TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint32_t mask) { - USB->ISTR = ~mask; -} - //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ @@ -244,11 +233,7 @@ void dcd_init (uint8_t rhport) asm("NOP"); } -#ifdef PMA_32BIT_ACCESS // CNTR register is 32bits on STM32G0, 16bit on older versions USB->CNTR &= ~USB_CNTR_PDWN; -#else - reg16_clear_bits(&USB->CNTR, USB_CNTR_PDWN);// Remove powerdown -#endif // Wait startup time, for F042 and F070, this is <= 1 us. for(uint32_t i = 0; i<200; i++) // should be a few us @@ -492,7 +477,6 @@ static void dcd_handle_bus_reset(void) //__IO uint16_t * const epreg = &(EPREG(0)); USB->DADDR = 0u; // disable USB peripheral by clearing the EF flag - for(uint32_t i=0; iISTR &=~USB_ISTR_SOF; dcd_event_sof(0, USB->FNR & USB_FNR_FN, true); } if(int_status & USB_ISTR_RESET) { // USBRST is start of reset. - clear_istr_bits(USB_ISTR_RESET); + USB->ISTR &=~USB_ISTR_RESET; dcd_handle_bus_reset(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? @@ -704,14 +688,10 @@ void dcd_int_handler(uint8_t rhport) { if (int_status & USB_ISTR_WKUP) { -#ifdef PMA_32BIT_ACCESS // CNTR register is 32bits on STM32G0, 16bit on older versions USB->CNTR &= ~USB_CNTR_LPMODE; USB->CNTR &= ~USB_CNTR_FSUSP; -#else - reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE); - reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP); -#endif - clear_istr_bits(USB_ISTR_WKUP); + + USB->ISTR &=~USB_ISTR_WKUP; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } @@ -725,7 +705,7 @@ void dcd_int_handler(uint8_t rhport) { USB->CNTR |= USB_CNTR_LPMODE; /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - clear_istr_bits(USB_ISTR_SUSP); + USB->ISTR &=~USB_ISTR_SUSP; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } @@ -738,7 +718,7 @@ void dcd_int_handler(uint8_t rhport) { { remoteWakeCountdown--; } - clear_istr_bits(USB_ISTR_ESOF); + USB->ISTR &=~USB_ISTR_ESOF; } } @@ -759,13 +739,8 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re uint8_t const dev_addr = (uint8_t) request->wValue; // Setting new address after the whole request is complete -#ifdef PMA_32BIT_ACCESS USB->DADDR &= ~USB_DADDR_ADD; - USB->DADDR = (USB->DADDR & ~USB_DADDR_ADD_Msk) | dev_addr; // leave the enable bit set -#else - reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD); - USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set -#endif + USB->DADDR |= dev_addr; // leave the enable bit set } } -- cgit v1.3.1