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 From 0a43a7b418dc9ba510505eef6abbc2da6f9151e5 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 Apr 2023 19:06:08 +0700 Subject: improve host serial drivers - tuh_control_xfer() update xfer result to user_data if complete callback = NULL (sync/blocking) - refactor host serial driver for acm/ftdi/cp210x --- src/class/cdc/cdc_host.c | 630 ++++++++++++++++++++++++----------------------- src/class/cdc/cdc_host.h | 6 +- src/host/usbh.c | 56 +---- 3 files changed, 343 insertions(+), 349 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e2447d033..b25bc5512 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -39,22 +39,16 @@ #define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF +// Host CDC Interface //--------------------------------------------------------------------+ -enum { - SERIAL_PROTOCOL_ACM = 0, - SERIAL_PROTOCOL_FTDI, - SERIAL_PROTOCOL_CP210X, -}; - typedef struct { uint8_t daddr; uint8_t bInterfaceNumber; uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; - uint8_t serial_protocol; + uint8_t serial_drid; // Serial Driver ID cdc_acm_capability_t acm_capability; uint8_t ep_notif; @@ -76,12 +70,102 @@ typedef struct { } cdch_interface_t; +CFG_TUH_MEM_SECTION +static cdch_interface_t cdch_data[CFG_TUH_CDC]; + //--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION +// Serial Driver //--------------------------------------------------------------------+ -CFG_TUH_MEM_SECTION -static cdch_interface_t cdch_data[CFG_TUH_CDC]; +//------------- ACM prototypes -------------// +static void acm_process_config(tuh_xfer_t* xfer); + +static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + +//------------- FTDI prototypes -------------// +#if CFG_TUH_CDC_FTDI +#include "serial/ftdi_sio.h" + +static uint16_t const ftdi_pids[] = { TU_FTDI_PID_LIST }; +enum { + FTDI_PID_COUNT = sizeof(ftdi_pids) / sizeof(ftdi_pids[0]) +}; + +// Store last request baudrate since divisor to baudrate is not easy +static uint32_t _ftdi_requested_baud; + +static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static void ftdi_process_config(tuh_xfer_t* xfer); + +static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +#endif + +//------------- CP210X prototypes -------------// +#if CFG_TUH_CDC_CP210X +#include "serial/cp210x.h" + +static uint16_t const cp210x_pids[] = { TU_CP210X_PID_LIST }; +enum { + CP210X_PID_COUNT = sizeof(cp210x_pids) / sizeof(cp210x_pids[0]) +}; + +static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +static void cp210x_process_config(tuh_xfer_t* xfer); + +static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +#endif + +enum { + SERIAL_DRIVER_ACM = 0, + +#if CFG_TUH_CDC_FTDI + SERIAL_DRIVER_FTDI, +#endif + +#if CFG_TUH_CDC_CP210X + SERIAL_DRIVER_CP210X, +#endif +}; + +typedef struct { + void (*const process_set_config)(tuh_xfer_t* xfer); + bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +} cdch_serial_driver_t; + +// Note driver list must be in the same order as SERIAL_DRIVER enum +static const cdch_serial_driver_t serial_drivers[] = { + { .process_set_config = acm_process_config, + .set_control_line_state = acm_set_control_line_state, + .set_baudrate = acm_set_baudrate + }, + + #if CFG_TUH_CDC_FTDI + { .process_set_config = ftdi_process_config, + .set_control_line_state = ftdi_sio_set_modem_ctrl, + .set_baudrate = ftdi_sio_set_baudrate + }, + #endif + + #if CFG_TUH_CDC_CP210X + { .process_set_config = cp210x_process_config, + .set_control_line_state = cp210x_set_modem_ctrl, + .set_baudrate = cp210x_set_baudrate + }, + #endif +}; + +enum { + SERIAL_DRIVER_COUNT = sizeof(serial_drivers) / sizeof(serial_drivers[0]) +}; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ static inline cdch_interface_t* get_itf(uint8_t idx) { @@ -130,39 +214,6 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t c static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num); static void cdch_internal_control_complete(tuh_xfer_t* xfer); -//------------- FTDI prototypes -------------// -#if CFG_TUH_CDC_FTDI -#include "serial/ftdi_sio.h" - -static uint16_t const ftdi_pids[] = { TU_FTDI_PID_LIST }; -enum { - FTDI_PID_COUNT = sizeof(ftdi_pids) / sizeof(ftdi_pids[0]) -}; - -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); -static void process_ftdi_config(tuh_xfer_t* xfer); - -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif - -//------------- CP210X prototypes -------------// -#if CFG_TUH_CDC_CP210X -#include "serial/cp210x.h" - -static uint16_t const cp210x_pids[] = { TU_CP210X_PID_LIST }; -enum { - CP210X_PID_COUNT = sizeof(cp210x_pids) / sizeof(cp210x_pids[0]) -}; - -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -static void process_cp210x_config(tuh_xfer_t* xfer); - -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif - - //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ @@ -322,175 +373,86 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) if (xfer->result == XFER_RESULT_SUCCESS) { - if (p_cdc->serial_protocol == SERIAL_PROTOCOL_ACM) { - switch (xfer->setup->bRequest) { - case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); - break; - - case CDC_REQUEST_SET_LINE_CODING: { - uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); - memcpy(&p_cdc->line_coding, xfer->buffer, len); + switch (p_cdc->serial_drid) { + case SERIAL_DRIVER_ACM: + switch (xfer->setup->bRequest) { + case CDC_REQUEST_SET_CONTROL_LINE_STATE: + p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + break; + + case CDC_REQUEST_SET_LINE_CODING: { + uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); + memcpy(&p_cdc->line_coding, xfer->buffer, len); + } + break; + + default: break; } - break; + break; - default: break; - } - } - #if CFG_TUH_CDC_FTDI - else if (p_cdc->serial_protocol == SERIAL_PROTOCOL_FTDI) { - switch (xfer->setup->bRequest) { - case FTDI_SIO_MODEM_CTRL: - p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); - break; + #if CFG_TUH_CDC_FTDI + case SERIAL_DRIVER_FTDI: + switch (xfer->setup->bRequest) { + case FTDI_SIO_MODEM_CTRL: + p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); + break; - default: break; - } - } - #endif - } - - xfer->complete_cb = p_cdc->user_control_cb; - xfer->complete_cb(xfer); -} + case FTDI_SIO_SET_BAUD_RATE: + // convert from divisor to baudrate is not supported + p_cdc->line_coding.bit_rate = _ftdi_requested_baud; + break; -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC ACM Set Control Line State\r\n"); - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = tu_htole16(line_state), - .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), - .wLength = 0 - }; + default: break; + } + break; + #endif - p_cdc->user_control_cb = complete_cb; + #if CFG_TUH_CDC_CP210X + case SERIAL_DRIVER_CP210X: + switch(xfer->setup->bRequest) { + case CP210X_SET_MHS: + p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); + break; + + case CP210X_SET_BAUDRATE: { + uint32_t baudrate; + memcpy(&baudrate, xfer->buffer, sizeof(uint32_t)); + p_cdc->line_coding.bit_rate = tu_le32toh(baudrate); + } + break; + } + break; + #endif - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = cdch_internal_control_complete, - .user_data = user_data - }; + default: break; + } + } - TU_ASSERT(tuh_control_xfer(&xfer)); - return true; + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } } -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - switch(p_cdc->serial_protocol) { - case SERIAL_PROTOCOL_ACM: - TU_VERIFY(p_cdc->acm_capability.support_line_request); - return acm_set_control_line_state(p_cdc, line_state, complete_cb, user_data); - - #if CFG_TUH_CDC_FTDI - case SERIAL_PROTOCOL_FTDI: - return ftdi_sio_set_modem_ctrl(p_cdc, line_state, complete_cb, user_data); - #endif - - #if CFG_TUH_CDC_CP210X - case SERIAL_PROTOCOL_CP210X: - return ftdi_sio_set_modem_ctrl(p_cdc, line_state, complete_cb, user_data); - #endif - - default: - return false; - } + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + return serial_drivers[p_cdc->serial_drid].set_control_line_state(p_cdc, line_state, complete_cb, user_data); } -bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC ACM Set Line Conding\r\n"); - - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_LINE_CODING, - .wValue = 0, - .wIndex = tu_htole16(p_cdc->bInterfaceNumber), - .wLength = tu_htole16(sizeof(cdc_line_coding_t)) - }; - - // use usbh enum buf to hold line coding since user line_coding variable does not live long enough - uint8_t* enum_buf = usbh_get_enum_buf(); - memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t)); - - p_cdc->user_control_cb = complete_cb; - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = enum_buf, - .complete_cb = cdch_internal_control_complete, - .user_data = user_data - }; - - TU_ASSERT(tuh_control_xfer(&xfer)); - return true; +bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdch_interface_t* p_cdc = get_itf(idx); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + return serial_drivers[p_cdc->serial_drid].set_baudrate(p_cdc, baudrate, complete_cb, user_data); } bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - - switch(p_cdc->serial_protocol) { - case SERIAL_PROTOCOL_ACM: - TU_VERIFY(p_cdc->acm_capability.support_line_request); - return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); - - #if CFG_TUH_CDC_FTDI - case SERIAL_PROTOCOL_FTDI: - // FTDI need to set baud rate and data bits, parity, stop bits separately - return ftdi_sio_set_baudrate(p_cdc, line_coding->bit_rate, complete_cb, user_data); - #endif - - #if CFG_TUH_CDC_CP210X - case SERIAL_PROTOCOL_CP210X: - return cp210x_set_baudrate(p_cdc, line_coding->bit_rate, complete_cb, user_data); - #endif - - default: return false; - } -} - -bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - switch(p_cdc->serial_protocol) { - case SERIAL_PROTOCOL_ACM: { - TU_VERIFY(p_cdc->acm_capability.support_line_request); - cdc_line_coding_t line_coding = p_cdc->line_coding; - line_coding.bit_rate = baudrate; - return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); - } - - #if CFG_TUH_CDC_FTDI - case SERIAL_PROTOCOL_FTDI: - // FTDI need to set baud rate and data bits, parity, stop bits separately - return ftdi_sio_set_baudrate(p_cdc, baudrate, complete_cb, user_data); - #endif - - #if CFG_TUH_CDC_CP210X - case SERIAL_PROTOCOL_CP210X: - return cp210x_set_baudrate(p_cdc, baudrate, complete_cb, user_data); - #endif - - default: return false; - } + // only ACM support this set line coding request + TU_VERIFY(p_cdc->serial_drid == SERIAL_DRIVER_ACM && p_cdc->acm_capability.support_line_request); + return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); } //--------------------------------------------------------------------+ @@ -561,7 +523,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t #if CFG_TUH_CDC_FTDI // FTDI reserve 2 bytes for status - if (p_cdc->serial_protocol == SERIAL_PROTOCOL_FTDI) { + if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { uint8_t status[2]; tu_edpt_stream_read(&p_cdc->stream.rx, status, 2); (void) status; // TODO handle status @@ -587,15 +549,10 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ -enum -{ - // ACM - CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, - CONFIG_ACM_SET_LINE_CODING, - CONFIG_ACM_COMPLETE, -}; -static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t const *desc_ep) +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); + +static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const *desc_ep) { for(size_t i=0; i<2; i++) { @@ -618,57 +575,6 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t c return true; } -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - uint8_t const * p_desc_end = ((uint8_t const*) itf_desc) + max_len; - - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - - p_cdc->serial_protocol = SERIAL_PROTOCOL_ACM; - - //------------- Control Interface -------------// - uint8_t const * p_desc = tu_desc_next(itf_desc); - - // Communication Functional Descriptors - while( (p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) ) - { - if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) - { - // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; - } - - p_desc = tu_desc_next(p_desc); - } - - // Open notification endpoint of control interface if any - if (itf_desc->bNumEndpoints == 1) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); - p_cdc->ep_notif = desc_ep->bEndpointAddress; - - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - p_desc = tu_desc_next(p_desc); - - // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); - } - - return true; -} - - bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; @@ -721,7 +627,88 @@ static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t i usbh_driver_set_config_complete(p_cdc->daddr, itf_num); } -static void process_acm_config(tuh_xfer_t* xfer) + +bool cdch_set_config(uint8_t daddr, uint8_t itf_num) +{ + tusb_control_request_t request; + request.wIndex = tu_htole16((uint16_t) itf_num); + + // fake transfer to kick-off process + tuh_xfer_t xfer; + xfer.daddr = daddr; + xfer.result = XFER_RESULT_SUCCESS; + xfer.setup = &request; + xfer.user_data = 0; // initial state + + uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + + serial_drivers[p_cdc->serial_drid].process_set_config(&xfer); + return true; +} + +//--------------------------------------------------------------------+ +// ACM +//--------------------------------------------------------------------+ + +enum { + CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, + CONFIG_ACM_SET_LINE_CODING, + CONFIG_ACM_COMPLETE, +}; + +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + uint8_t const * p_desc_end = ((uint8_t const*) itf_desc) + max_len; + + cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + TU_VERIFY(p_cdc); + + p_cdc->serial_drid = SERIAL_DRIVER_ACM; + + //------------- Control Interface -------------// + uint8_t const * p_desc = tu_desc_next(itf_desc); + + // Communication Functional Descriptors + while( (p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) ) + { + if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) + { + // save ACM bmCapabilities + p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; + } + + p_desc = tu_desc_next(p_desc); + } + + // Open notification endpoint of control interface if any + if (itf_desc->bNumEndpoints == 1) + { + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + + TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; + + p_desc = tu_desc_next(p_desc); + } + + //------------- Data Interface (if any) -------------// + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + { + // next to endpoint descriptor + p_desc = tu_desc_next(p_desc); + + // data endpoints expected to be in pairs + TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); + } + + return true; +} + +static void acm_process_config(tuh_xfer_t* xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); @@ -735,72 +722,103 @@ static void process_acm_config(tuh_xfer_t* xfer) #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM if (p_cdc->acm_capability.support_line_request) { - TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, process_acm_config, - CONFIG_ACM_SET_LINE_CODING), ); + TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, + CONFIG_ACM_SET_LINE_CODING), ); break; } - #endif + #endif TU_ATTR_FALLTHROUGH; case CONFIG_ACM_SET_LINE_CODING: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM if (p_cdc->acm_capability.support_line_request) { cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, process_acm_config, CONFIG_ACM_COMPLETE), ); + TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE), ); break; } - #endif + #endif TU_ATTR_FALLTHROUGH; case CONFIG_ACM_COMPLETE: // itf_num+1 to account for data interface as well set_config_complete(p_cdc, idx, itf_num+1); - break; + break; default: break; } } -bool cdch_set_config(uint8_t daddr, uint8_t itf_num) -{ - tusb_control_request_t request; - request.wIndex = tu_htole16((uint16_t) itf_num); +static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_VERIFY(p_cdc->acm_capability.support_line_request); + TU_LOG_CDCH("CDC ACM Set Control Line State\r\n"); + tusb_control_request_t const request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, + .wValue = tu_htole16(line_state), + .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), + .wLength = 0 + }; - tuh_xfer_t xfer; - xfer.daddr = daddr; - xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; - xfer.user_data = 0; + p_cdc->user_control_cb = complete_cb; - // fake transfer to kick-off process - uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc); + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request, + .buffer = NULL, + .complete_cb = cdch_internal_control_complete, + .user_data = user_data + }; - switch (p_cdc->serial_protocol) { - case SERIAL_PROTOCOL_ACM: - process_acm_config(&xfer); - break; + TU_ASSERT(tuh_control_xfer(&xfer)); + return true; +} - #if CFG_TUH_CDC_FTDI - case SERIAL_PROTOCOL_FTDI: - process_ftdi_config(&xfer); - break; - #endif +static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_CDCH("CDC ACM Set Line Conding\r\n"); - #if CFG_TUH_CDC_CP210X - case SERIAL_PROTOCOL_CP210X: - process_cp210x_config(&xfer); - break; - #endif + tusb_control_request_t const request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_LINE_CODING, + .wValue = 0, + .wIndex = tu_htole16(p_cdc->bInterfaceNumber), + .wLength = tu_htole16(sizeof(cdc_line_coding_t)) + }; - default: return false; - } + // use usbh enum buf to hold line coding since user line_coding variable does not live long enough + uint8_t* enum_buf = usbh_get_enum_buf(); + memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t)); + + p_cdc->user_control_cb = complete_cb; + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request, + .buffer = enum_buf, + .complete_cb = cdch_internal_control_complete, + .user_data = user_data + }; + TU_ASSERT(tuh_control_xfer(&xfer)); return true; } +static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_VERIFY(p_cdc->acm_capability.support_line_request); + cdc_line_coding_t line_coding = p_cdc->line_coding; + line_coding.bit_rate = baudrate; + return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); +} + //--------------------------------------------------------------------+ // FTDI //--------------------------------------------------------------------+ @@ -824,7 +842,7 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint TU_LOG_CDCH("FTDI opened\r\n"); - p_cdc->serial_protocol = SERIAL_PROTOCOL_FTDI; + p_cdc->serial_drid = SERIAL_DRIVER_FTDI; // endpoint pair tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -904,11 +922,13 @@ static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tu TU_LOG_CDCH("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor); p_cdc->user_control_cb = complete_cb; + _ftdi_requested_baud = baudrate; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, cdch_internal_control_complete, user_data)); + return true; } -static void process_ftdi_config(tuh_xfer_t* xfer) { +static void ftdi_process_config(tuh_xfer_t* xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); @@ -918,13 +938,13 @@ static void process_ftdi_config(tuh_xfer_t* xfer) { switch(state) { // Note may need to read FTDI eeprom case CONFIG_FTDI_RESET: - TU_ASSERT(ftdi_sio_reset(p_cdc, process_ftdi_config, CONFIG_FTDI_MODEM_CTRL),); + TU_ASSERT(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL),); break; case CONFIG_FTDI_MODEM_CTRL: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM TU_ASSERT( - ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, process_ftdi_config, CONFIG_FTDI_SET_BAUDRATE),); + ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); break; #else TU_ATTR_FALLTHROUGH; @@ -933,7 +953,7 @@ static void process_ftdi_config(tuh_xfer_t* xfer) { case CONFIG_FTDI_SET_BAUDRATE: { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, line_coding.bit_rate, process_ftdi_config, CONFIG_FTDI_SET_DATA),); + TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, line_coding.bit_rate, ftdi_process_config, CONFIG_FTDI_SET_DATA),); break; #else TU_ATTR_FALLTHROUGH; @@ -986,7 +1006,7 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui TU_VERIFY(p_cdc); TU_LOG_CDCH("CP210x opened\r\n"); - p_cdc->serial_protocol = SERIAL_PROTOCOL_CP210X; + p_cdc->serial_drid = SERIAL_DRIVER_CP210X; // endpoint pair tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -1034,8 +1054,9 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_CDCH("CDC CP210x Set BaudRate = %lu\n", baudrate); - baudrate = tu_htole32(baudrate); - return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baudrate, 4, complete_cb, user_data); + uint32_t baud_le = tu_htole32(baudrate); + p_cdc->user_control_cb = complete_cb; + return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, cdch_internal_control_complete, user_data); } static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) @@ -1045,7 +1066,7 @@ static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, cdch_internal_control_complete, user_data); } -static void process_cp210x_config(tuh_xfer_t* xfer) { +static void cp210x_process_config(tuh_xfer_t* xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); @@ -1054,13 +1075,13 @@ static void process_cp210x_config(tuh_xfer_t* xfer) { switch (state) { case CONFIG_CP210X_IFC_ENABLE: - TU_ASSERT(cp210x_ifc_enable(p_cdc, 1, process_cp210x_config, CONFIG_CP210X_SET_BAUDRATE),); + TU_ASSERT(cp210x_ifc_enable(p_cdc, 1, cp210x_process_config, CONFIG_CP210X_SET_BAUDRATE),); break; case CONFIG_CP210X_SET_BAUDRATE: { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(cp210x_set_baudrate(p_cdc, line_coding.bit_rate, process_cp210x_config, CONFIG_CP210X_SET_LINE_CTL),); + TU_ASSERT(cp210x_set_baudrate(p_cdc, line_coding.bit_rate, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),); break; #else TU_ATTR_FALLTHROUGH; @@ -1078,7 +1099,8 @@ static void process_cp210x_config(tuh_xfer_t* xfer) { case CONFIG_CP210X_SET_DTR_RTS: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, process_cp210x_config, CONFIG_CP210X_COMPLETE),); + TU_ASSERT( + cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),); break; #else TU_ATTR_FALLTHROUGH; diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 971ebe2ae..f6cc3812f 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -134,7 +134,11 @@ bool tuh_cdc_read_clear (uint8_t idx); //--------------------------------------------------------------------+ // Control Endpoint (Request) API -// Each Function will make a USB transfer request to/from device +// Each Function will make a USB control transfer request to/from device +// - If complete_cb is provided, the function will return immediately and invoke +// the callback when request is complete. +// - If complete_cb is NULL, the function will block until request is complete. +// In this case, user_data should be pointed to xfer_result_t to hold the transfer result. //--------------------------------------------------------------------+ // Request to Set Control Line State: DTR (bit 0), RTS (bit 1) diff --git a/src/host/usbh.c b/src/host/usbh.c index 3953d5b21..24ce47a7f 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -571,19 +571,19 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); - while (result == XFER_RESULT_INVALID) - { + while (result == XFER_RESULT_INVALID) { // Note: this can be called within an callback ie. part of tuh_task() // therefore event with RTOS tuh_task() still need to be invoked - if (tuh_task_event_ready()) - { + if (tuh_task_event_ready()) { tuh_task(); } - // TODO probably some timeout to prevent hanged } - // update transfer result + // update transfer result, user_data is expected to point to xfer_result_t + if (xfer->user_data != 0) { + *((xfer_result_t*) xfer->user_data) = result; + } xfer->result = result; xfer->actual_len = _ctrl_xfer.actual_len; } @@ -877,7 +877,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) //--------------------------------------------------------------------+ // generic helper to get a descriptor -// if blocking, user_data could be pointed to xfer_result +// if blocking, user_data is pointed to xfer_result static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -905,15 +905,7 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t .user_data = user_data }; - bool const ret = tuh_control_xfer(&xfer); - - // if blocking, user_data could be pointed to xfer_result - if ( !complete_cb && user_data ) - { - *((xfer_result_t*) user_data) = xfer.result; - } - - return ret; + return tuh_control_xfer(&xfer); } bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, @@ -971,7 +963,7 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* } // Get HID report descriptor -// if blocking, user_data could be pointed to xfer_result +// if blocking, user_data is pointed to xfer_result bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -1000,15 +992,7 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ .user_data = user_data }; - bool const ret = tuh_control_xfer(&xfer); - - // if blocking, user_data could be pointed to xfer_result - if ( !complete_cb && user_data ) - { - *((xfer_result_t*) user_data) = xfer.result; - } - - return ret; + return tuh_control_xfer(&xfer); } bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, @@ -1040,15 +1024,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, .user_data = user_data }; - bool ret = tuh_control_xfer(&xfer); - - // if blocking, user_data could be pointed to xfer_result - if ( !complete_cb && user_data ) - { - *((xfer_result_t*) user_data) = xfer.result; - } - - return ret; + return tuh_control_xfer(&xfer); } bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, @@ -1080,15 +1056,7 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, .user_data = user_data }; - bool ret = tuh_control_xfer(&xfer); - - // if blocking, user_data could be pointed to xfer_result - if ( !complete_cb && user_data ) - { - *((xfer_result_t*) user_data) = xfer.result; - } - - return ret; + return tuh_control_xfer(&xfer); } //--------------------------------------------------------------------+ -- cgit v1.3.1 From fb5fe3360fb29a5d937cb6d6f1baa7695c04c361 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 Apr 2023 21:50:54 +0700 Subject: allow call tuh cdc with blocking (callback = NULL) - tuh_cdc_set_control_line_state() - tuh_cdc_set_baudrate() - tuh_cdc_set_line_coding() --- src/class/cdc/cdc_host.c | 83 +++++++++++++++++++++++++++++++++++++++++------- src/class/cdc/cdc_host.h | 1 + 2 files changed, 73 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index b25bc5512..858fdd9a7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -437,22 +437,78 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - return serial_drivers[p_cdc->serial_drid].set_control_line_state(p_cdc, line_state, complete_cb, user_data); + cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + + if ( complete_cb ) { + return driver->set_control_line_state(p_cdc, line_state, complete_cb, user_data); + }else { + // blocking + xfer_result_t result; + bool ret = driver->set_control_line_state(p_cdc, line_state, complete_cb, (uintptr_t) &result); + + if (user_data) { + // user_data is not NULL, return result via user_data + *((xfer_result_t*) user_data) = result; + } + + if (result == XFER_RESULT_SUCCESS) { + p_cdc->line_state = (uint8_t) line_state; + } + + return ret; + } } bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - return serial_drivers[p_cdc->serial_drid].set_baudrate(p_cdc, baudrate, complete_cb, user_data); + cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + + if ( complete_cb ) { + return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data); + }else { + // blocking + xfer_result_t result; + bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result); + + if (user_data) { + // user_data is not NULL, return result via user_data + *((xfer_result_t*) user_data) = result; + } + + if (result == XFER_RESULT_SUCCESS) { + p_cdc->line_coding.bit_rate = baudrate; + } + + return ret; + } } bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); // only ACM support this set line coding request - TU_VERIFY(p_cdc->serial_drid == SERIAL_DRIVER_ACM && p_cdc->acm_capability.support_line_request); - return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); + TU_VERIFY(p_cdc && p_cdc->serial_drid == SERIAL_DRIVER_ACM); + TU_VERIFY(p_cdc->acm_capability.support_line_request); + + if ( complete_cb ) { + return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); + }else { + // blocking + xfer_result_t result; + bool ret = acm_set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); + + if (user_data) { + // user_data is not NULL, return result via user_data + *((xfer_result_t*) user_data) = result; + } + + if (result == XFER_RESULT_SUCCESS) { + p_cdc->line_coding = *line_coding; + } + + return ret; + } } //--------------------------------------------------------------------+ @@ -752,6 +808,7 @@ static void acm_process_config(tuh_xfer_t* xfer) static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); TU_LOG_CDCH("CDC ACM Set Control Line State\r\n"); + tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, @@ -771,7 +828,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st .ep_addr = 0, .setup = &request, .buffer = NULL, - .complete_cb = cdch_internal_control_complete, + .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call .user_data = user_data }; @@ -804,7 +861,7 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const .ep_addr = 0, .setup = &request, .buffer = enum_buf, - .complete_cb = cdch_internal_control_complete, + .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call .user_data = user_data }; @@ -886,7 +943,8 @@ static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state { TU_LOG_CDCH("CDC FTDI Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, cdch_internal_control_complete, user_data)); + TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, + complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -923,7 +981,8 @@ static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tu p_cdc->user_control_cb = complete_cb; _ftdi_requested_baud = baudrate; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, cdch_internal_control_complete, user_data)); + TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, + complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -1056,14 +1115,16 @@ static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_ TU_LOG_CDCH("CDC CP210x Set BaudRate = %lu\n", baudrate); uint32_t baud_le = tu_htole32(baudrate); p_cdc->user_control_cb = complete_cb; - return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, cdch_internal_control_complete, user_data); + return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, + complete_cb ? cdch_internal_control_complete : NULL, user_data); } static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_CDCH("CDC CP210x Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; - return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, cdch_internal_control_complete, user_data); + return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, + complete_cb ? cdch_internal_control_complete : NULL, user_data); } static void cp210x_process_config(tuh_xfer_t* xfer) { diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index f6cc3812f..8544ff740 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -148,6 +148,7 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set Line Coding (ACM only) +// Should only use if you don't work with serial devices such as FTDI/CP210x bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Get Line Coding (ACM only) -- cgit v1.3.1 From 1763eede4839d0131cda077e2dd9631f315ce115 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 Apr 2023 22:14:14 +0700 Subject: more update to host serial API --- src/class/cdc/cdc_host.c | 27 ++++++++++++--------------- src/class/cdc/cdc_host.h | 3 ++- 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 858fdd9a7..fe3691bf4 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -443,7 +443,7 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c return driver->set_control_line_state(p_cdc, line_state, complete_cb, user_data); }else { // blocking - xfer_result_t result; + xfer_result_t result = XFER_RESULT_INVALID; bool ret = driver->set_control_line_state(p_cdc, line_state, complete_cb, (uintptr_t) &result); if (user_data) { @@ -451,11 +451,10 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c *((xfer_result_t*) user_data) = result; } - if (result == XFER_RESULT_SUCCESS) { - p_cdc->line_state = (uint8_t) line_state; - } + TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - return ret; + p_cdc->line_state = (uint8_t) line_state; + return true; } } @@ -468,7 +467,7 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data); }else { // blocking - xfer_result_t result; + xfer_result_t result = XFER_RESULT_INVALID; bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result); if (user_data) { @@ -476,11 +475,10 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete *((xfer_result_t*) user_data) = result; } - if (result == XFER_RESULT_SUCCESS) { - p_cdc->line_coding.bit_rate = baudrate; - } + TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - return ret; + p_cdc->line_coding.bit_rate = baudrate; + return true; } } @@ -495,7 +493,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); }else { // blocking - xfer_result_t result; + xfer_result_t result = XFER_RESULT_INVALID; bool ret = acm_set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); if (user_data) { @@ -503,11 +501,10 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, *((xfer_result_t*) user_data) = result; } - if (result == XFER_RESULT_SUCCESS) { - p_cdc->line_coding = *line_coding; - } + TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - return ret; + p_cdc->line_coding = *line_coding; + return true; } } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 8544ff740..19552f1ee 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -138,7 +138,8 @@ bool tuh_cdc_read_clear (uint8_t idx); // - If complete_cb is provided, the function will return immediately and invoke // the callback when request is complete. // - If complete_cb is NULL, the function will block until request is complete. -// In this case, user_data should be pointed to xfer_result_t to hold the transfer result. +// - In this case, user_data should be pointed to xfer_result_t to hold the transfer result. +// - The function will return true if transfer is successful, false otherwise. //--------------------------------------------------------------------+ // Request to Set Control Line State: DTR (bit 0), RTS (bit 1) -- cgit v1.3.1 From 8a9d2b4b759990f9609a33c313b154cc7314bec7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 May 2023 23:29:37 +0700 Subject: wip --- examples/device/cdc_msc/CMakeLists.txt | 7 +++++++ hw/bsp/imxrt/family.cmake | 17 +++++++++++++++-- src/CMakeLists.txt | 31 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/CMakeLists.txt b/examples/device/cdc_msc/CMakeLists.txt index 7eddc2422..1115f51d1 100644 --- a/examples/device/cdc_msc/CMakeLists.txt +++ b/examples/device/cdc_msc/CMakeLists.txt @@ -29,6 +29,13 @@ target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) +# define tinyusb_config target +add_library(tinyusb_config INTERFACE) + +target_include_directories(tinyusb_config INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT}) diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 95c4c0415..c18fb01ab 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -73,9 +73,22 @@ function(family_configure_target TARGET) ${SDK_DIR}/drivers/lpuart ) + # define tinyusb_config target + + #target_include_directories(tinyusb_config INTERFACE + # ) + + target_compile_definitions(tinyusb_config PUBLIC + ) + # include tinyusb cmake - include(${TOP}/src/CMakeLists.txt) - add_tinyusb(${TARGET}) + add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + target_link_libraries(${TARGET} PUBLIC + tinyusb + ) + + #include(${TOP}/src/CMakeLists.txt) + #add_tinyusb(${TARGET}) endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a270ea8b7..ec7fe32c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,37 @@ cmake_minimum_required(VERSION 3.17) +if (NOT TARGET tinyusb_config) + message(FATAL_ERROR "tinyusb_config target is not defined") +endif() + +add_library(tinyusb STATIC + ${CMAKE_CURRENT_LIST_DIR}/tusb.c + ${CMAKE_CURRENT_LIST_DIR}/common/tusb_fifo.c + ${CMAKE_CURRENT_LIST_DIR}/device/usbd.c + ${CMAKE_CURRENT_LIST_DIR}/device/usbd_control.c + ${CMAKE_CURRENT_LIST_DIR}/class/audio/audio_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/cdc/cdc_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/dfu/dfu_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/dfu/dfu_rt_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/hid/hid_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/midi/midi_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/msc/msc_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/net/ecm_rndis_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/net/ncm_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/usbtmc/usbtmc_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/vendor/vendor_device.c + ${CMAKE_CURRENT_LIST_DIR}/class/video/video_device.c + ) + +target_include_directories(tinyusb PUBLIC + ${CMAKE_CURRENT_LIST_DIR} + ) + +target_link_libraries(tinyusb PUBLIC + tinyusb_config + ) + function(add_tinyusb TARGET) target_sources(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c -- cgit v1.3.1 From cda5ab8b259522be962840a49a448648d3f5d308 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 May 2023 19:15:19 +0700 Subject: more temp work --- hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake | 4 +- hw/bsp/imxrt/family.cmake | 48 +++++++++++++-------- src/CMakeLists.txt | 58 +++++++++++++------------- 3 files changed, 60 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake index 52d1846ea..c43de5ba4 100644 --- a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake +++ b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake @@ -1,10 +1,10 @@ set(MCU_VARIANT MIMXRT1011) -target_sources(${PROJECT} PUBLIC +target_sources(bsp PUBLIC ${CMAKE_CURRENT_LIST_DIR}/evkmimxrt1010_flexspi_nor_config.c ) -target_compile_definitions(${PROJECT} PUBLIC +target_compile_definitions(bsp PUBLIC CPU_MIMXRT1011DAE5A CFG_EXAMPLE_VIDEO_READONLY ) diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index c18fb01ab..53df88c47 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -2,6 +2,7 @@ set(CMAKE_SYSTEM_PROCESSOR cortex-m7 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../../../examples/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + function(family_configure_target TARGET) if (NOT BOARD) message(FATAL_ERROR "BOARD not specified") @@ -17,9 +18,14 @@ function(family_configure_target TARGET) set(SDK_DIR ${TOP}/hw/mcu/nxp/mcux-sdk) set(DEPS_SUBMODULES ${SDK_DIR}) + # define BSP target + add_library(bsp STATIC + ) + + # include board specific cmake include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board.cmake) - target_compile_definitions(${TARGET} PUBLIC + target_compile_definitions(bsp PUBLIC CFG_TUSB_MCU=OPT_MCU_MIMXRT __ARMVFP__=0 __ARMFPV5__=0 @@ -32,11 +38,11 @@ function(family_configure_target TARGET) --specs=nano.specs ) - target_sources(${TARGET} PUBLIC + target_sources(bsp PUBLIC # TinyUSB - ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c - ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c - ${TOP}/src/portable/ehci/ehci.c +# ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c +# ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c +# ${TOP}/src/portable/ehci/ehci.c # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${SDK_DIR}/drivers/common/fsl_common.c @@ -49,18 +55,18 @@ function(family_configure_target TARGET) ) if (TOOLCHAIN STREQUAL "gcc") - target_sources(${TARGET} PUBLIC + target_sources(bsp PUBLIC ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S ) - target_link_options(${TARGET} PUBLIC + target_link_options(bsp PUBLIC "LINKER:--script=${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx_flexspi_nor.ld" ) else () # TODO support IAR endif () - target_include_directories(${TARGET} PUBLIC + target_include_directories(bsp PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} @@ -73,25 +79,31 @@ function(family_configure_target TARGET) ${SDK_DIR}/drivers/lpuart ) - # define tinyusb_config target - - #target_include_directories(tinyusb_config INTERFACE - # ) + if(NOT TARGET tinyusb_config) + message(FATAL_ERROR "tinyusb_config target not found") + endif() - target_compile_definitions(tinyusb_config PUBLIC + target_compile_definitions(tinyusb_config INTERFACE + CFG_TUSB_MCU=OPT_MCU_MIMXRT ) - # include tinyusb cmake + # include tinyusb CMakeList.txt for tinyusb target add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) - target_link_libraries(${TARGET} PUBLIC - tinyusb + + add_library(tinyusb_port STATIC + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c ) - #include(${TOP}/src/CMakeLists.txt) - #add_tinyusb(${TARGET}) + target_link_libraries(${TARGET} PUBLIC + tinyusb + bsp + ) endfunction() + function(family_add_freertos_config TARGET) add_library(freertos_config INTERFACE) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ec7fe32c4..e7e3125a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,33 +34,31 @@ target_link_libraries(tinyusb PUBLIC tinyusb_config ) -function(add_tinyusb TARGET) - target_sources(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/common/tusb_fifo.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd_control.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/audio/audio_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_rt_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/midi/midi_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ecm_rndis_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ncm_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/usbtmc/usbtmc_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_device.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/video/video_device.c - ) - - target_include_directories(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ) - - # enable all possible warnings - target_compile_options(${TARGET} PUBLIC - - ) - -endfunction() +#function(add_tinyusb TARGET) +# target_sources(${TARGET} PUBLIC +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/common/tusb_fifo.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd_control.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/audio/audio_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_rt_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/midi/midi_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ecm_rndis_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ncm_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/usbtmc/usbtmc_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_device.c +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/video/video_device.c +# ) +# +# target_include_directories(${TARGET} PUBLIC +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR} +# ) +# +# # enable all possible warnings +# target_compile_options(${TARGET} PUBLIC +# ) +#endfunction() -- cgit v1.3.1 From f15f79df5d242fdeff06dff14a9550905f29d514 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 6 May 2023 15:14:54 +0700 Subject: cmake work well with imxrt --- examples/CMakeLists.txt | 6 +- examples/device/CMakeLists.txt | 2 +- examples/device/audio_test/CMakeLists.txt | 4 +- .../device/audio_test_multi_rate/CMakeLists.txt | 4 +- examples/device/board_test/CMakeLists.txt | 8 +- examples/device/cdc_dual_ports/CMakeLists.txt | 10 +- examples/device/cdc_msc/CMakeLists.txt | 15 +-- examples/device/cdc_msc_freertos/CMakeLists.txt | 2 +- .../device/hid_composite_freertos/CMakeLists.txt | 2 +- examples/host/cdc_msc_hid/CMakeLists.txt | 2 +- hw/bsp/family_support.cmake | 4 +- hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake | 17 +-- hw/bsp/imxrt/family.cmake | 145 +++++++++++---------- src/CMakeLists.txt | 104 +++++++-------- 14 files changed, 163 insertions(+), 162 deletions(-) (limited to 'src') diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d91d8ca62..a23b4ed62 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.5) #set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(${CMAKE_CURRENT_SOURCE_DIR}/../hw/bsp/family_support.cmake) -project(tinyusb_examples) +project(tinyusb_examples C CXX ASM) add_subdirectory(device) -add_subdirectory(dual) -add_subdirectory(host) +#add_subdirectory(dual) +#add_subdirectory(host) diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index 5520209e0..ac1bbf161 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5) include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake) -project(tinyusb_device_examples) +project(tinyusb_device_examples C CXX ASM) family_initialize_project(tinyusb_device_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY diff --git a/examples/device/audio_test/CMakeLists.txt b/examples/device/audio_test/CMakeLists.txt index b0889285c..87b7d07d4 100644 --- a/examples/device/audio_test/CMakeLists.txt +++ b/examples/device/audio_test/CMakeLists.txt @@ -21,12 +21,12 @@ add_executable(${PROJECT}) target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c -) + ) # Example include target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src -) + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/examples/device/audio_test_multi_rate/CMakeLists.txt b/examples/device/audio_test_multi_rate/CMakeLists.txt index b0889285c..87b7d07d4 100644 --- a/examples/device/audio_test_multi_rate/CMakeLists.txt +++ b/examples/device/audio_test_multi_rate/CMakeLists.txt @@ -21,12 +21,12 @@ add_executable(${PROJECT}) target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c -) + ) # Example include target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src -) + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/examples/device/board_test/CMakeLists.txt b/examples/device/board_test/CMakeLists.txt index c48efdaa5..4ab8d5a65 100644 --- a/examples/device/board_test/CMakeLists.txt +++ b/examples/device/board_test/CMakeLists.txt @@ -19,13 +19,13 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/examples/device/cdc_dual_ports/CMakeLists.txt b/examples/device/cdc_dual_ports/CMakeLists.txt index d142e9c04..87b7d07d4 100644 --- a/examples/device/cdc_dual_ports/CMakeLists.txt +++ b/examples/device/cdc_dual_ports/CMakeLists.txt @@ -19,14 +19,14 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/examples/device/cdc_msc/CMakeLists.txt b/examples/device/cdc_msc/CMakeLists.txt index 1115f51d1..63030e733 100644 --- a/examples/device/cdc_msc/CMakeLists.txt +++ b/examples/device/cdc_msc/CMakeLists.txt @@ -19,20 +19,13 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - -# define tinyusb_config target -add_library(tinyusb_config INTERFACE) - -target_include_directories(tinyusb_config INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src ) diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt index 699860223..75ec33145 100644 --- a/examples/device/cdc_msc_freertos/CMakeLists.txt +++ b/examples/device/cdc_msc_freertos/CMakeLists.txt @@ -35,7 +35,7 @@ target_include_directories(${PROJECT} PUBLIC family_configure_device_example(${PROJECT}) if (NOT TARGET freertos_kernel) -family_add_freertos_config(${PROJECT}) +family_configure_freertos_example(${PROJECT}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/FreeRTOS-Kernel lib/FreeRTOS-Kernel) endif() diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt index 9b0ffa4b6..30729f438 100644 --- a/examples/device/hid_composite_freertos/CMakeLists.txt +++ b/examples/device/hid_composite_freertos/CMakeLists.txt @@ -34,7 +34,7 @@ target_include_directories(${PROJECT} PUBLIC family_configure_device_example(${PROJECT}) if (NOT TARGET freertos_kernel) -family_add_freertos_config(${PROJECT}) +family_configure_freertos_example(${PROJECT}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/FreeRTOS-Kernel lib/FreeRTOS-Kernel) endif() diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index b66ff2382..42dac5be7 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -5,7 +5,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) # gets PROJECT name for the example (e.g. -) family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index cc95dde9e..26baa6365 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -1,4 +1,6 @@ if (NOT TARGET _family_support_marker) + add_library(_family_support_marker INTERFACE) + include(CMakePrintHelpers) # Default to gcc @@ -6,8 +8,6 @@ if (NOT TARGET _family_support_marker) set(TOOLCHAIN gcc) endif() - add_library(_family_support_marker INTERFACE) - if (NOT FAMILY) message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, eps32s2, esp32s3). You can do this via -DFAMILY=xxx on the cmake command line") endif() diff --git a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake index c43de5ba4..d4015e488 100644 --- a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake +++ b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake @@ -1,10 +1,11 @@ set(MCU_VARIANT MIMXRT1011) -target_sources(bsp PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/evkmimxrt1010_flexspi_nor_config.c - ) - -target_compile_definitions(bsp PUBLIC - CPU_MIMXRT1011DAE5A - CFG_EXAMPLE_VIDEO_READONLY - ) +function(update_board TARGET) + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/evkmimxrt1010_flexspi_nor_config.c + ) + target_compile_definitions(${TARGET} PUBLIC + CPU_MIMXRT1011DAE5A + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 53df88c47..1731d9e60 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -1,50 +1,34 @@ +if (TARGET _imxrt_family_inclusion_marker) + return() +endif () + +add_library(_imxrt_family_inclusion_marker INTERFACE) + +if (NOT BOARD) + message(FATAL_ERROR "BOARD not specified") +endif () + # toolchain set up set(CMAKE_SYSTEM_PROCESSOR cortex-m7 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../../../examples/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) -function(family_configure_target TARGET) - if (NOT BOARD) - message(FATAL_ERROR "BOARD not specified") - endif () - # set output name to .elf - set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET}.elf) - - # TOP is absolute path to root directory of TinyUSB git repo - set(TOP "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../..") - get_filename_component(TOP "${TOP}" REALPATH) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +set(BOARD_TARGET board_${BOARD}) +if (NOT TARGET ${BOARD_TARGET}) + # TOP is path to root directory + set(TOP "${CMAKE_CURRENT_LIST_DIR}/../../..") set(SDK_DIR ${TOP}/hw/mcu/nxp/mcux-sdk) - set(DEPS_SUBMODULES ${SDK_DIR}) + set(CMSIS_DIR ${TOP}/lib/CMSIS_5) - # define BSP target - add_library(bsp STATIC - ) - - # include board specific cmake - include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board.cmake) - - target_compile_definitions(bsp PUBLIC - CFG_TUSB_MCU=OPT_MCU_MIMXRT - __ARMVFP__=0 - __ARMFPV5__=0 - XIP_EXTERNAL_FLASH=1 - XIP_BOOT_HEADER_ENABLE=1 - ) - - target_link_options(${TARGET} PUBLIC - --specs=nosys.specs - --specs=nano.specs - ) - - target_sources(bsp PUBLIC - # TinyUSB -# ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c -# ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c -# ${TOP}/src/portable/ehci/ehci.c - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/drivers/common/fsl_common.c ${SDK_DIR}/drivers/igpio/fsl_gpio.c ${SDK_DIR}/drivers/lpuart/fsl_lpuart.c @@ -53,58 +37,87 @@ function(family_configure_target TARGET) ${SDK_DIR}/devices/${MCU_VARIANT}/project_template/clock_config.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUSB_MCU=OPT_MCU_MIMXRT + __ARMVFP__=0 + __ARMFPV5__=0 + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMSIS_DIR}/CMSIS/Core/Include + ${SDK_DIR}/devices/${MCU_VARIANT} + ${SDK_DIR}/devices/${MCU_VARIANT}/project_template + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + ${SDK_DIR}/drivers/common + ${SDK_DIR}/drivers/igpio + ${SDK_DIR}/drivers/lpuart + ) + update_board(${BOARD_TARGET}) if (TOOLCHAIN STREQUAL "gcc") - target_sources(bsp PUBLIC + target_sources(${BOARD_TARGET} PUBLIC ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S ) - - target_link_options(bsp PUBLIC + target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--script=${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx_flexspi_nor.ld" + --specs=nosys.specs + --specs=nano.specs ) else () # TODO support IAR endif () +endif () # BOARD_TARGET + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_target TARGET) + # set output name to .elf + set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET}.elf) + + # TOP is path to root directory + set(TOP "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../..") - target_include_directories(bsp PUBLIC + #---------- BSP_TARGET ---------- + # BSP_TARGET is built for each example since it depends on example's tusb_config.h + set(BSP_TARGET "${TARGET}_bsp_${BOARD}") + add_library(${BSP_TARGET} STATIC + # TinyUSB + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ) + target_include_directories(${BSP_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ${SDK_DIR}/CMSIS/Include - ${SDK_DIR}/devices/${MCU_VARIANT} - ${SDK_DIR}/devices/${MCU_VARIANT}/project_template - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers - ${SDK_DIR}/drivers/common - ${SDK_DIR}/drivers/igpio - ${SDK_DIR}/drivers/lpuart ) - if(NOT TARGET tinyusb_config) - message(FATAL_ERROR "tinyusb_config target not found") - endif() + #---------- TinyUSB ---------- + # tinyusb target is built for each example since it depends on example's tusb_config.h + set(TINYUSB_TARGET_PREFIX ${TARGET}) + add_library(${TARGET}_tinyusb_config INTERFACE) - target_compile_definitions(tinyusb_config INTERFACE + target_include_directories(${TARGET}_tinyusb_config INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + target_compile_definitions(${TARGET}_tinyusb_config INTERFACE CFG_TUSB_MCU=OPT_MCU_MIMXRT ) - # include tinyusb CMakeList.txt for tinyusb target + # tinyusb's CMakeList.txt add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) - add_library(tinyusb_port STATIC - ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c - ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c - ${TOP}/src/portable/ehci/ehci.c - ) - - - target_link_libraries(${TARGET} PUBLIC - tinyusb - bsp - ) + # Link dependencies + target_link_libraries(${BSP_TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}_tinyusb) + target_link_libraries(${TARGET} PUBLIC ${BSP_TARGET} ${TARGET}_tinyusb) endfunction() -function(family_add_freertos_config TARGET) +function(family_configure_freertos_example TARGET) add_library(freertos_config INTERFACE) # add path to FreeRTOSConfig.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e7e3125a2..21aa23d54 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,62 +3,56 @@ cmake_minimum_required(VERSION 3.17) -if (NOT TARGET tinyusb_config) - message(FATAL_ERROR "tinyusb_config target is not defined") -endif() +# Add tinyusb to a target +function(add_tinyusb TARGET) + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/common/tusb_fifo.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd_control.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/audio/audio_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_rt_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/midi/midi_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ecm_rndis_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ncm_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/usbtmc/usbtmc_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/video/video_device.c + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ) + # enable all possible warnings + target_compile_options(${TARGET} PUBLIC + ) +endfunction() -add_library(tinyusb STATIC - ${CMAKE_CURRENT_LIST_DIR}/tusb.c - ${CMAKE_CURRENT_LIST_DIR}/common/tusb_fifo.c - ${CMAKE_CURRENT_LIST_DIR}/device/usbd.c - ${CMAKE_CURRENT_LIST_DIR}/device/usbd_control.c - ${CMAKE_CURRENT_LIST_DIR}/class/audio/audio_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/cdc/cdc_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/dfu/dfu_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/dfu/dfu_rt_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/hid/hid_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/midi/midi_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/msc/msc_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/net/ecm_rndis_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/net/ncm_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/usbtmc/usbtmc_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/vendor/vendor_device.c - ${CMAKE_CURRENT_LIST_DIR}/class/video/video_device.c - ) +set(TINYUSB_TARGET "tinyusb") +set(TINYUSB_CONFIG_TARGET "tinyusb_config") -target_include_directories(tinyusb PUBLIC - ${CMAKE_CURRENT_LIST_DIR} - ) +if (DEFINED TINYUSB_TARGET_PREFIX) + set(TINYUSB_TARGET "${TINYUSB_TARGET_PREFIX}_${TINYUSB_TARGET}") + set(TINYUSB_CONFIG_TARGET "${TINYUSB_TARGET_PREFIX}_${TINYUSB_CONFIG_TARGET}") +endif () -target_link_libraries(tinyusb PUBLIC - tinyusb_config - ) +if (DEFINED TINYUSB_TARGET_SUFFIX) + set(TINYUSB_TARGET "${TINYUSB_TARGET}_${TINYUSB_TARGET_SUFFIX}") + set(TINYUSB_CONFIG_TARGET "${TINYUSB_CONFIG_TARGET}_${TINYUSB_TARGET_SUFFIX}") +endif () + +add_library(${TINYUSB_TARGET} STATIC) +add_tinyusb(${TINYUSB_TARGET}) -#function(add_tinyusb TARGET) -# target_sources(${TARGET} PUBLIC -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/common/tusb_fifo.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd_control.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/audio/audio_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/dfu/dfu_rt_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/midi/midi_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ecm_rndis_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ncm_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/usbtmc/usbtmc_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_device.c -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/video/video_device.c -# ) -# -# target_include_directories(${TARGET} PUBLIC -# ${CMAKE_CURRENT_FUNCTION_LIST_DIR} -# ) -# -# # enable all possible warnings -# target_compile_options(${TARGET} PUBLIC -# ) -#endfunction() +# Link with tinyusb_config target + +if (NOT TARGET ${TINYUSB_CONFIG_TARGET}) + message(FATAL_ERROR "${TINYUSB_CONFIG_TARGET} target is not defined") +endif() + +target_link_libraries(${TINYUSB_TARGET} PUBLIC + ${TINYUSB_CONFIG_TARGET} + ) -- cgit v1.3.1 From 6945c594d53ca6a35f1f0bb120b5a652c6ce9e84 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 7 May 2023 22:09:08 +0700 Subject: update all device cmake example for imx --- .idea/runConfigurations/rt10xx_pyocd.xml | 7 --- examples/CMakeLists.txt | 6 +-- examples/cmake/cpu/cortex-m7.cmake | 18 +++++--- examples/device/CMakeLists.txt | 2 +- examples/device/cdc_msc_freertos/CMakeLists.txt | 10 +---- .../device/hid_composite_freertos/CMakeLists.txt | 10 +---- examples/dual/CMakeLists.txt | 4 +- .../dual/host_hid_to_device_cdc/CMakeLists.txt | 4 +- examples/host/CMakeLists.txt | 4 +- examples/host/bare_api/CMakeLists.txt | 4 +- examples/host/hid_controller/CMakeLists.txt | 4 +- examples/host/msc_file_explorer/CMakeLists.txt | 4 +- hw/bsp/imxrt/FreeRTOSConfig/CMakeLists.txt | 8 ++++ hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake | 3 ++ hw/bsp/imxrt/family.cmake | 52 ++++++++++++++-------- src/CMakeLists.txt | 8 ++-- 16 files changed, 81 insertions(+), 67 deletions(-) delete mode 100644 .idea/runConfigurations/rt10xx_pyocd.xml create mode 100644 hw/bsp/imxrt/FreeRTOSConfig/CMakeLists.txt (limited to 'src') diff --git a/.idea/runConfigurations/rt10xx_pyocd.xml b/.idea/runConfigurations/rt10xx_pyocd.xml deleted file mode 100644 index f5c142690..000000000 --- a/.idea/runConfigurations/rt10xx_pyocd.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a23b4ed62..91c9fb098 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) #set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(${CMAKE_CURRENT_SOURCE_DIR}/../hw/bsp/family_support.cmake) @@ -6,5 +6,5 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../hw/bsp/family_support.cmake) project(tinyusb_examples C CXX ASM) add_subdirectory(device) -#add_subdirectory(dual) -#add_subdirectory(host) +add_subdirectory(dual) +add_subdirectory(host) diff --git a/examples/cmake/cpu/cortex-m7.cmake b/examples/cmake/cpu/cortex-m7.cmake index 2b258726f..458d8b438 100644 --- a/examples/cmake/cpu/cortex-m7.cmake +++ b/examples/cmake/cpu/cortex-m7.cmake @@ -1,6 +1,12 @@ -set(TOOLCHAIN_COMMON_FLAGS - -mthumb - -mcpu=cortex-m7 - -mfloat-abi=hard - -mfpu=fpv5-d16 - ) +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m7 + -mfloat-abi=hard + -mfpu=fpv5-d16 + ) + + set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") +else () + # TODO support IAR +endif () diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index ac1bbf161..5b077a5e1 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake) diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt index 75ec33145..319ad0356 100644 --- a/examples/device/cdc_msc_freertos/CMakeLists.txt +++ b/examples/device/cdc_msc_freertos/CMakeLists.txt @@ -34,11 +34,5 @@ target_include_directories(${PROJECT} PUBLIC # in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT}) -if (NOT TARGET freertos_kernel) -family_configure_freertos_example(${PROJECT}) -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/FreeRTOS-Kernel lib/FreeRTOS-Kernel) -endif() - -target_link_libraries(${PROJECT} PUBLIC - freertos_kernel - ) +# Add FreeRTOS for this example +family_add_freertos(${PROJECT}) diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt index 30729f438..211904cf9 100644 --- a/examples/device/hid_composite_freertos/CMakeLists.txt +++ b/examples/device/hid_composite_freertos/CMakeLists.txt @@ -33,11 +33,5 @@ target_include_directories(${PROJECT} PUBLIC # in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT}) -if (NOT TARGET freertos_kernel) -family_configure_freertos_example(${PROJECT}) -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/FreeRTOS-Kernel lib/FreeRTOS-Kernel) -endif() - -target_link_libraries(${PROJECT} PUBLIC - freertos_kernel - ) +# Add FreeRTOS for this example +family_add_freertos(${PROJECT}) diff --git a/examples/dual/CMakeLists.txt b/examples/dual/CMakeLists.txt index d2f9a42f0..d211c8b83 100644 --- a/examples/dual/CMakeLists.txt +++ b/examples/dual/CMakeLists.txt @@ -1,8 +1,8 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake) -project(tinyusb_dual_examples) +project(tinyusb_dual_examples C CXX ASM) family_initialize_project(tinyusb_dual_examples ${CMAKE_CURRENT_LIST_DIR}) if (FAMILY STREQUAL "rp2040" AND NOT TARGET tinyusb_pico_pio_usb) message("Skipping dual host/device mode examples as Pico-PIO-USB is not available") diff --git a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt index 724d1e119..3505d39eb 100644 --- a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt +++ b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) # gets PROJECT name for the example (e.g. -) family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 758973ab2..bedd2220b 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -1,8 +1,8 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake) -project(tinyusb_host_examples) +project(tinyusb_host_examples C CXX ASM) family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY diff --git a/examples/host/bare_api/CMakeLists.txt b/examples/host/bare_api/CMakeLists.txt index 616edd4ac..b6d8c9c89 100644 --- a/examples/host/bare_api/CMakeLists.txt +++ b/examples/host/bare_api/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) # gets PROJECT name for the example family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt index ac3070b82..e1d2f1642 100644 --- a/examples/host/hid_controller/CMakeLists.txt +++ b/examples/host/hid_controller/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) # gets PROJECT name for the example (e.g. -) family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index 7955b3078..2ab0aa881 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) # gets PROJECT name for the example (e.g. -) family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) diff --git a/hw/bsp/imxrt/FreeRTOSConfig/CMakeLists.txt b/hw/bsp/imxrt/FreeRTOSConfig/CMakeLists.txt new file mode 100644 index 000000000..0bacaf824 --- /dev/null +++ b/hw/bsp/imxrt/FreeRTOSConfig/CMakeLists.txt @@ -0,0 +1,8 @@ +if (NOT TARGET freertos_config) + add_library(freertos_config INTERFACE) + + # add path to FreeRTOSConfig.h + target_include_directories(freertos_config SYSTEM INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ) +endif() diff --git a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake index d4015e488..02955e356 100644 --- a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake +++ b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.cmake @@ -1,5 +1,8 @@ set(MCU_VARIANT MIMXRT1011) +set(JLINK_DEVICE MIMXRT1011DAE5A) +set(PYOCD_TARGET mimxrt1010) + function(update_board TARGET) target_sources(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/evkmimxrt1010_flexspi_nor_config.c diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 1731d9e60..653885bb2 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -81,7 +81,7 @@ function(family_configure_target TARGET) #---------- BSP_TARGET ---------- # BSP_TARGET is built for each example since it depends on example's tusb_config.h - set(BSP_TARGET "${TARGET}_bsp_${BOARD}") + set(BSP_TARGET "${TARGET}-bsp") add_library(${BSP_TARGET} STATIC # TinyUSB ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -98,13 +98,13 @@ function(family_configure_target TARGET) #---------- TinyUSB ---------- # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}) - add_library(${TARGET}_tinyusb_config INTERFACE) + set(TINYUSB_TARGET_PREFIX ${TARGET}-) + add_library(${TARGET}-tinyusb_config INTERFACE) - target_include_directories(${TARGET}_tinyusb_config INTERFACE + target_include_directories(${TARGET}-tinyusb_config INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src ) - target_compile_definitions(${TARGET}_tinyusb_config INTERFACE + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUSB_MCU=OPT_MCU_MIMXRT ) @@ -112,25 +112,41 @@ function(family_configure_target TARGET) add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) # Link dependencies - target_link_libraries(${BSP_TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}_tinyusb) - target_link_libraries(${TARGET} PUBLIC ${BSP_TARGET} ${TARGET}_tinyusb) + target_link_libraries(${BSP_TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) + target_link_libraries(${TARGET} PUBLIC ${BSP_TARGET} ${TARGET}-tinyusb) + + # Flash Target + add_custom_target(${TARGET}-pyocd + COMMAND pyocd flash -t ${PYOCD_TARGET} $ + ) endfunction() -function(family_configure_freertos_example TARGET) - add_library(freertos_config INTERFACE) +function(family_add_freertos TARGET) + # freertos_config + add_subdirectory(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FreeRTOSConfig ${CMAKE_CURRENT_BINARY_DIR}/freertos_config) + + ## freertos + if (NOT TARGET freertos_kernel) + add_subdirectory(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../../lib/FreeRTOS-Kernel ${CMAKE_CURRENT_BINARY_DIR}/freertos_kernel) + endif () - # add path to FreeRTOSConfig.h - target_include_directories(freertos_config SYSTEM INTERFACE - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FreeRTOSConfig + # Add FreeRTOS option to tinyusb_config + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE + CFG_TUSB_OS=OPT_OS_FREERTOS + ) + # tinyusb need to be linked with freeRTOS kernel + target_link_libraries(${TARGET}-tinyusb PUBLIC + freertos_kernel ) - # select freertos port - if (TOOLCHAIN STREQUAL "gcc") - set(FREERTOS_PORT "GCC_ARM_CM7" CACHE INTERNAL "") - else () - # TODO support IAR - endif () + target_link_libraries(${TARGET}-tinyusb PUBLIC + freertos_kernel + ) + + target_link_libraries(${TARGET} PUBLIC + freertos_kernel + ) endfunction() function(family_configure_device_example TARGET) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21aa23d54..02f962f44 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,13 +35,13 @@ set(TINYUSB_TARGET "tinyusb") set(TINYUSB_CONFIG_TARGET "tinyusb_config") if (DEFINED TINYUSB_TARGET_PREFIX) - set(TINYUSB_TARGET "${TINYUSB_TARGET_PREFIX}_${TINYUSB_TARGET}") - set(TINYUSB_CONFIG_TARGET "${TINYUSB_TARGET_PREFIX}_${TINYUSB_CONFIG_TARGET}") + set(TINYUSB_TARGET "${TINYUSB_TARGET_PREFIX}${TINYUSB_TARGET}") + set(TINYUSB_CONFIG_TARGET "${TINYUSB_TARGET_PREFIX}${TINYUSB_CONFIG_TARGET}") endif () if (DEFINED TINYUSB_TARGET_SUFFIX) - set(TINYUSB_TARGET "${TINYUSB_TARGET}_${TINYUSB_TARGET_SUFFIX}") - set(TINYUSB_CONFIG_TARGET "${TINYUSB_CONFIG_TARGET}_${TINYUSB_TARGET_SUFFIX}") + set(TINYUSB_TARGET "${TINYUSB_TARGET}${TINYUSB_TARGET_SUFFIX}") + set(TINYUSB_CONFIG_TARGET "${TINYUSB_CONFIG_TARGET}${TINYUSB_TARGET_SUFFIX}") endif () add_library(${TINYUSB_TARGET} STATIC) -- cgit v1.3.1 From 654f1821769f50c44f786032bedfe417a9ad4d0f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 8 May 2023 00:24:48 +0700 Subject: build host examples with imx --- examples/host/cdc_msc_hid/CMakeLists.txt | 14 ++++---- examples/host/hid_controller/CMakeLists.txt | 10 +++--- examples/host/msc_file_explorer/CMakeLists.txt | 20 +++++------ hw/bsp/board.c | 49 -------------------------- hw/bsp/imxrt/family.cmake | 7 ++++ src/CMakeLists.txt | 9 +++++ 6 files changed, 38 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index 42dac5be7..68b52e274 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -14,16 +14,16 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt index e1d2f1642..e27f83c53 100644 --- a/examples/host/hid_controller/CMakeLists.txt +++ b/examples/host/hid_controller/CMakeLists.txt @@ -14,14 +14,14 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index 2ab0aa881..2d5600059 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -14,19 +14,19 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c - ${TOP}/lib/fatfs/source/ff.c - ${TOP}/lib/fatfs/source/ffsystem.c - ${TOP}/lib/fatfs/source/ffunicode.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c + ${TOP}/lib/fatfs/source/ff.c + ${TOP}/lib/fatfs/source/ffsystem.c + ${TOP}/lib/fatfs/source/ffunicode.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${TOP}/lib/fatfs/source - ${TOP}/lib/embedded-cli - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${TOP}/lib/fatfs/source + ${TOP}/lib/embedded-cli + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/hw/bsp/board.c b/hw/bsp/board.c index e715bdf2e..66ffcb199 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -25,55 +25,6 @@ #include "board.h" -#if 0 -#define LED_PHASE_MAX 8 - -static struct -{ - uint32_t phase[LED_PHASE_MAX]; - uint8_t phase_count; - - bool led_state; - uint8_t current_phase; - uint32_t current_ms; -}led_pattern; - -void board_led_pattern(uint32_t const phase_ms[], uint8_t count) -{ - memcpy(led_pattern.phase, phase_ms, 4*count); - led_pattern.phase_count = count; - - // reset with 1st phase is on - led_pattern.current_ms = board_millis(); - led_pattern.current_phase = 0; - led_pattern.led_state = true; - board_led_on(); -} - -void board_led_task(void) -{ - if ( led_pattern.phase_count == 0 ) return; - - uint32_t const duration = led_pattern.phase[led_pattern.current_phase]; - - // return if not enough time - if (board_millis() - led_pattern.current_ms < duration) return; - - led_pattern.led_state = !led_pattern.led_state; - board_led_write(led_pattern.led_state); - - led_pattern.current_ms += duration; - led_pattern.current_phase++; - - if (led_pattern.current_phase == led_pattern.phase_count) - { - led_pattern.current_phase = 0; - led_pattern.led_state = true; - board_led_on(); - } -} -#endif - //--------------------------------------------------------------------+ // newlib read()/write() retarget //--------------------------------------------------------------------+ diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 653885bb2..b180f725e 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -12,6 +12,8 @@ endif () set(CMAKE_SYSTEM_PROCESSOR cortex-m7 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../../../examples/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(FAMILY_MCUS MIMXRT CACHE INTERNAL "") + # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) @@ -89,6 +91,7 @@ function(family_configure_target TARGET) ${TOP}/src/portable/ehci/ehci.c # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ) target_include_directories(${BSP_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -152,3 +155,7 @@ endfunction() function(family_configure_device_example TARGET) family_configure_target(${TARGET}) endfunction() + +function(family_configure_host_example TARGET) + family_configure_target(${TARGET}) +endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 02f962f44..0b99d8919 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,8 +6,10 @@ cmake_minimum_required(VERSION 3.17) # Add tinyusb to a target function(add_tinyusb TARGET) target_sources(${TARGET} PUBLIC + # common ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/common/tusb_fifo.c + # device ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd_control.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/audio/audio_device.c @@ -22,6 +24,13 @@ function(add_tinyusb TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/usbtmc/usbtmc_device.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_device.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/video/video_device.c + # host + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/host/usbh.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/host/hub.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_host.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_host.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_host.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_host.c ) target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} -- cgit v1.3.1 From 77f0726361c66bf2783c1ce68e0f00bdd5f58229 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 9 May 2023 17:32:14 +0700 Subject: fix ehci issue with portsc when enable port power and port reset fix attached device not regconized if attached before power on --- .idea/runConfigurations/rt1060_redlink.xml | 10 ++ hw/bsp/imxrt/boards/mimxrt1060_evk/board.cmake | 1 + hw/bsp/imxrt/family.cmake | 19 +++- src/portable/ehci/ehci.c | 90 ++++++++++------- src/portable/ehci/ehci.h | 132 +++++++++++++++++-------- 5 files changed, 171 insertions(+), 81 deletions(-) create mode 100644 .idea/runConfigurations/rt1060_redlink.xml (limited to 'src') diff --git a/.idea/runConfigurations/rt1060_redlink.xml b/.idea/runConfigurations/rt1060_redlink.xml new file mode 100644 index 000000000..a6f345fac --- /dev/null +++ b/.idea/runConfigurations/rt1060_redlink.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/hw/bsp/imxrt/boards/mimxrt1060_evk/board.cmake b/hw/bsp/imxrt/boards/mimxrt1060_evk/board.cmake index 033f9fcf9..171d427de 100644 --- a/hw/bsp/imxrt/boards/mimxrt1060_evk/board.cmake +++ b/hw/bsp/imxrt/boards/mimxrt1060_evk/board.cmake @@ -2,6 +2,7 @@ set(MCU_VARIANT MIMXRT1062) set(JLINK_DEVICE MIMXRT1062xxx6A) set(PYOCD_TARGET mimxrt1060) +set(NXPLS_DEVICE MIMXRT1062xxxxA:EVK-MIMXRT1060) function(update_board TARGET) target_sources(${TARGET} PUBLIC diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index e9615a1f4..e38bcf4b1 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -121,15 +121,26 @@ function(family_configure_target TARGET) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # Flash Target + # group target (not yet supported by clion) + set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config + PROPERTIES FOLDER ${TARGET}_sub + ) + + #---------- Flash ---------- + # Flash using pyocd add_custom_target(${TARGET}-pyocd COMMAND pyocd flash -t ${PYOCD_TARGET} $ ) - # group target - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub + # Flash using NXP LinkServer (redlink) + # https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/linkserver-for-microcontrollers:LINKERSERVER + # LinkServer has a bug that can only execute with full path otherwise it throws: + # realpath error: No such file or directory + execute_process(COMMAND which LinkServer OUTPUT_VARIABLE LINKSERVER_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) + add_custom_target(${TARGET}-redlink + COMMAND ${LINKSERVER_PATH} flash ${NXPLS_DEVICE} load $ ) + endfunction() diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 9951aa5da..494e2e50f 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -79,7 +79,8 @@ typedef struct ehci_qhd_t qhd_pool[QHD_MAX]; ehci_qtd_t qtd_pool[QTD_MAX] TU_ATTR_ALIGNED(32); - ehci_registers_t* regs; + ehci_registers_t* regs; // operational register + ehci_cap_registers_t* cap_regs; // capability register volatile uint32_t uframe_number; }ehci_data_t; @@ -87,6 +88,26 @@ typedef struct // Periodic frame list must be 4K alignment CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= EHCI_DBG +static inline void print_portsc(ehci_registers_t* regs) +{ + TU_LOG_HEX(EHCI_DBG, regs->portsc); + TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status); + TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change); + TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled); + TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change); + + TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset); + TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power); +} + +#else +#define print_portsc(_reg) +#endif + //--------------------------------------------------------------------+ // PROTOTYPE //--------------------------------------------------------------------+ @@ -152,11 +173,11 @@ void hcd_port_reset(uint8_t rhport) ehci_registers_t* regs = ehci_data.regs; -// regs->portsc_bm.port_enabled = 0; // disable port before reset -// regs->portsc_bm.port_reset = 1; - - uint32_t portsc = regs->portsc; + // mask out all change bits since they are Write 1 to clear + uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL; + // EHCI Table 2-16 PortSC + // when software writes Port Reset bit to a one, it must also write a zero to the Port Enable bit. portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED); portsc |= EHCI_PORTSC_MASK_PORT_RESET; @@ -167,9 +188,14 @@ void hcd_port_reset_end(uint8_t rhport) { (void) rhport; -#if 0 +#if 0 // TODO check if this is necessary ehci_registers_t* regs = ehci_data.regs; - regs->portsc_bm.port_reset = 0; + + // mask out all change bits since they are Write 1 to clear + uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL; + portsc &= ~(EHCI_PORTSC_MASK_PORT_RESET); + + regs->portsc = portsc; #endif } @@ -240,19 +266,26 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) { - (void) capability_reg; // not used yet - tu_memclr(&ehci_data, sizeof(ehci_data_t)); - ehci_data.regs = (ehci_registers_t* ) operatial_reg; + ehci_data.regs = (ehci_registers_t*) operatial_reg; + ehci_data.cap_regs = (ehci_cap_registers_t*) capability_reg; ehci_registers_t* regs = ehci_data.regs; + // EHCI 4.1 Host Controller Initialization + //------------- CTRLDSSEGMENT Register (skip) -------------// + //------------- USB INT Register -------------// - regs->inten = 0; // 1. disable all the interrupt - regs->status = EHCI_INT_MASK_ALL; // 2. clear all status + // disable all the interrupt + regs->inten = 0; + + // clear all status except port change since device maybe connected before this driver is initialized + regs->status = (EHCI_INT_MASK_ALL & ~EHCI_INT_MASK_PORT_CHANGE); + + // Enable interrupts regs->inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER; @@ -316,7 +349,16 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) FRAMELIST_SIZE_USBCMD_VALUE; //------------- ConfigFlag Register (skip) -------------// - regs->portsc_bm.port_power = 1; // enable port power + + // enable port power bit in portsc. The function of this bit depends on the value of the Port + // Power Control (PPC) field in the HCSPARAMS register. + if (ehci_data.cap_regs->hcsparams_bm.port_power_control) { + // mask out all change bits since they are Write 1 to clear + uint32_t portsc = (regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL); + portsc |= ECHI_PORTSC_MASK_PORT_POWER; + + regs->portsc = portsc; + } return true; } @@ -656,26 +698,6 @@ static void xfer_error_isr(uint8_t hostid) } } -#if CFG_TUSB_DEBUG >= EHCI_DBG - -static inline void print_portsc(ehci_registers_t* regs) -{ - TU_LOG_HEX(EHCI_DBG, regs->portsc); - TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status); - TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change); - TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled); - TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change); - - TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset); - TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power); -} - -#else - -#define print_portsc(_reg) - -#endif - //------------- Host Controller Driver's Interrupt Handler -------------// void hcd_int_handler(uint8_t rhport) { @@ -695,7 +717,7 @@ void hcd_int_handler(uint8_t rhport) if (int_status & EHCI_INT_MASK_PORT_CHANGE) { - uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_ALL; + uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_CHANGE_ALL; print_portsc(regs); if (regs->portsc_bm.connect_status_change) diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 36f8649be..dd090cb36 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -267,16 +267,15 @@ TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); //--------------------------------------------------------------------+ // EHCI Operational Register //--------------------------------------------------------------------+ -enum ehci_interrupt_mask_{ +enum { EHCI_INT_MASK_USB = TU_BIT(0), EHCI_INT_MASK_ERROR = TU_BIT(1), EHCI_INT_MASK_PORT_CHANGE = TU_BIT(2), - EHCI_INT_MASK_FRAMELIST_ROLLOVER = TU_BIT(3), EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR = TU_BIT(4), EHCI_INT_MASK_ASYNC_ADVANCE = TU_BIT(5), - EHCI_INT_MASK_NXP_SOF = TU_BIT(7), + EHCI_INT_MASK_NXP_SOF = TU_BIT(7), EHCI_INT_MASK_NXP_ASYNC = TU_BIT(18), EHCI_INT_MASK_NXP_PERIODIC = TU_BIT(19), @@ -287,7 +286,7 @@ enum ehci_interrupt_mask_{ EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_NXP_PERIODIC }; -enum ehci_usbcmd_pos_ { +enum { EHCI_USBCMD_POS_RUN_STOP = 0, EHCI_USBCMD_POS_FRAMELIST_SIZE = 2, EHCI_USBCMD_POS_PERIOD_ENABLE = 4, @@ -296,24 +295,27 @@ enum ehci_usbcmd_pos_ { EHCI_USBCMD_POS_INTERRUPT_THRESHOLD = 16 }; -enum ehci_portsc_change_mask_{ +enum { EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), - EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), + EHCI_PORTSC_MASK_PORT_ENABLE_CHANGE = TU_BIT(3), EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), + EHCI_PORTSC_MASK_FORCE_RESUME = TU_BIT(6), + EHCI_PORTSC_MASK_PORT_SUSPEND = TU_BIT(7), EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), + ECHI_PORTSC_MASK_PORT_POWER = TU_BIT(12), - EHCI_PORTSC_MASK_ALL = - EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | - EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE | - EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE + EHCI_PORTSC_MASK_CHANGE_ALL = + EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | + EHCI_PORTSC_MASK_PORT_ENABLE_CHANGE | + EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE }; typedef volatile struct { union { - uint32_t command; + uint32_t command; // 0x00 struct { uint32_t run_stop : 1 ; ///< 1=Run. 0=Stop @@ -333,7 +335,7 @@ typedef volatile struct }; union { - uint32_t status; + uint32_t status; // 0x04 struct { uint32_t usb : 1 ; ///< qTD with IOC is retired @@ -357,7 +359,7 @@ typedef volatile struct }; union{ - uint32_t inten; + uint32_t inten; // 0x08 struct { uint32_t usb : 1 ; @@ -375,43 +377,87 @@ typedef volatile struct }inten_bm; }; - uint32_t frame_index ; ///< Micro frame counter - uint32_t ctrl_ds_seg ; ///< Control Data Structure Segment - uint32_t periodic_list_base ; ///< Beginning address of perodic frame list - uint32_t async_list_addr ; ///< Address of next async QHD to be executed + uint32_t frame_index ; ///< 0x0C Micro frame counter + uint32_t ctrl_ds_seg ; ///< 0x10 Control Data Structure Segment + uint32_t periodic_list_base ; ///< 0x14 Beginning address of perodic frame list + uint32_t async_list_addr ; ///< 0x18 Address of next async QHD to be executed uint32_t nxp_tt_control ; ///< nxp embedded transaction translator (reserved by EHCI specs) uint32_t reserved[8] ; - uint32_t config_flag ; ///< not used by NXP + uint32_t config_flag ; ///< 0x40 not used by NXP union { - uint32_t portsc ; ///< port status and control - struct { - uint32_t current_connect_status : 1; ///< 0: No device, 1: Device is present on port - uint32_t connect_status_change : 1; ///< Change in Current Connect Status - uint32_t port_enabled : 1; ///< Ports can only be enabled by HC as a part of the reset and enable. SW can write 0 to disable - uint32_t port_enable_change : 1; ///< Port Enabled has changed - uint32_t over_current_active : 1; ///< Port has an over-current condition - uint32_t over_current_change : 1; ///< Change to Over-current Active - uint32_t force_port_resume : 1; ///< Resume detected/driven on port. This functionality defined for manipulating this bit depends on the value of the Suspend bit. - uint32_t suspend : 1; ///< Port in suspend state - uint32_t port_reset : 1; ///< 1=Port is in Reset. 0=Port is not in Reset - uint32_t nxp_highspeed_status : 1; ///< NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode - uint32_t line_status : 2; ///< D+/D- state: 00: SE0, 10: J-state, 01: K-state - uint32_t port_power : 1; ///< 0= power off, 1= power on - uint32_t port_owner : 1; ///< not used by NXP - uint32_t port_indicator_control : 2; ///< 00b: off, 01b: Amber, 10b: green, 11b: undefined - uint32_t port_test_control : 4; ///< Port test mode, not used by tinyusb - uint32_t wake_on_connect_enable : 1; ///< Enables device connects as wake-up events - uint32_t wake_on_disconnect_enable : 1; ///< Enables device disconnects as wake-up events - uint32_t wake_on_over_current_enable : 1; ///< Enables over-current conditions as wake-up events - uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock - uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. - uint32_t TU_RESERVED : 1; - uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed + // mixed with RW and R/WC bits, care should be taken when writing to this register + uint32_t portsc ; ///< 0x44 port status and control + const struct { + uint32_t current_connect_status : 1; ///< 00: 0: No device, 1: Device is present on port + uint32_t connect_status_change : 1; ///< 01: [R/WC] Change in Current Connect Status + uint32_t port_enabled : 1; ///< 02: Ports can only be enabled by HC as a part of the reset and enable. SW can write 0 to disable + uint32_t port_enable_change : 1; ///< 03: [R/WC] Port Enabled has changed + uint32_t over_current_active : 1; ///< 04: Port has an over-current condition + uint32_t over_current_change : 1; ///< 05: [R/WC] Change to Over-current Active + uint32_t force_port_resume : 1; ///< 06: Resume detected/driven on port. This functionality defined for manipulating this bit depends on the value of the Suspend bit. + uint32_t suspend : 1; ///< 07: Port in suspend state + uint32_t port_reset : 1; ///< 08: 1=Port is in Reset. 0=Port is not in Reset + uint32_t nxp_highspeed_status : 1; ///< 09: NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode + uint32_t line_status : 2; ///< 10-11: D+/D- state: 00: SE0, 10: J-state, 01: K-state + uint32_t port_power : 1; ///< 12: 0= power off, 1= power on + uint32_t port_owner : 1; ///< 13: not used by NXP + uint32_t port_indicator_control : 2; ///< 14-15: 00b: off, 01b: Amber, 10b: green, 11b: undefined + uint32_t port_test_control : 4; ///< 16-19: Port test mode, not used by tinyusb + uint32_t wake_on_connect_enable : 1; ///< 20: Enables device connects as wake-up events + uint32_t wake_on_disconnect_enable : 1; ///< 21: Enables device disconnects as wake-up events + uint32_t wake_on_over_current_enable : 1; ///< 22: Enables over-current conditions as wake-up events + uint32_t nxp_phy_clock_disable : 1; ///< 23: NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock + uint32_t nxp_port_force_fullspeed : 1; ///< 24: NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. + uint32_t TU_RESERVED : 1; ///< 25 + uint32_t nxp_port_speed : 2; ///< 26-27: NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed uint32_t TU_RESERVED : 4; }portsc_bm; }; -}ehci_registers_t; +} ehci_registers_t; + +//--------------------------------------------------------------------+ +// Capability Registers +//--------------------------------------------------------------------+ +typedef volatile struct { + uint8_t caplength; // 0x00 + uint8_t TU_RESERVED; // 0x01 + uint16_t hciversion; // 0x02 + + union { + uint32_t hcsparams; // 0x04 + struct { + uint32_t num_ports : 4; // [00:03] + uint32_t port_power_control : 1; // [04] + uint32_t TU_RESERVED : 2; // [05:06] + uint32_t port_route_rule : 1; // [07] + uint32_t n_pcc : 4; // [08:11] Number of Ports per Companion Controller + uint32_t n_cc : 4; // [12:15] Number of Companion Controllers + uint32_t port_ind : 1; // [16] Port Indicators + uint32_t TU_RESERVED : 3; // [17:19] + uint32_t n_ptt : 4; // [20:23] ChipIdea: Number of Ports per Transaction Translator + uint32_t n_tt : 4; // [24:27] ChipIdea: Number of Transaction Translators + uint32_t TU_RESERVED : 4; // [28:31] + } hcsparams_bm; + }; + + union { + uint32_t hccparams; // 0x08 + struct { + uint32_t addr_64bit : 1; // [00] 64-bit Addressing Capability + uint32_t programmable_frame_list_flag : 1; // [01] Programmable Frame List Flag + uint32_t async_park_cap : 1; // [02] Asynchronous Schedule Park Capability + uint32_t TU_RESERVED : 1; // [03] + uint32_t iso_schedule_threshold : 4; // [4:7] Isochronous Scheduling Threshold + uint32_t eecp : 8; // [8:15] EHCI Extended Capabilities Pointer + uint32_t TU_RESERVED : 16;// [16:31] + } hccparams_bm; + }; + + uint32_t hcsp_portroute; // 0x0C HCSP Port Route Register +} ehci_cap_registers_t; + +TU_VERIFY_STATIC(sizeof(ehci_cap_registers_t) == 16, "size is not correct"); #ifdef __cplusplus } -- cgit v1.3.1 From c0e4c02b9d70240b97aa4924e6002ccb3d8057dd Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 May 2023 11:15:11 +0700 Subject: allow imxrt build with dual exmaples --- examples/cmake/toolchain/set_flags.cmake | 3 ++- examples/dual/CMakeLists.txt | 11 +++++---- .../dual/host_hid_to_device_cdc/CMakeLists.txt | 28 +++++++++++----------- hw/bsp/family_support.cmake | 4 ++-- hw/bsp/imxrt/family.cmake | 4 ++++ src/portable/chipidea/ci_hs/hcd_ci_hs.c | 2 ++ 6 files changed, 30 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/examples/cmake/toolchain/set_flags.cmake b/examples/cmake/toolchain/set_flags.cmake index 27631abcd..3f109b59e 100644 --- a/examples/cmake/toolchain/set_flags.cmake +++ b/examples/cmake/toolchain/set_flags.cmake @@ -8,7 +8,8 @@ foreach(LANG IN ITEMS C CXX ASM) #cmake_print_variables(CMAKE_${LANG}_FLAGS_INIT) # optimization flags - set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-Og") + set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os") + set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0") endforeach() # Linker diff --git a/examples/dual/CMakeLists.txt b/examples/dual/CMakeLists.txt index d211c8b83..15081cf26 100644 --- a/examples/dual/CMakeLists.txt +++ b/examples/dual/CMakeLists.txt @@ -4,9 +4,10 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake) project(tinyusb_dual_examples C CXX ASM) family_initialize_project(tinyusb_dual_examples ${CMAKE_CURRENT_LIST_DIR}) + if (FAMILY STREQUAL "rp2040" AND NOT TARGET tinyusb_pico_pio_usb) - message("Skipping dual host/device mode examples as Pico-PIO-USB is not available") -else() - # family_add_subdirectory will filter what to actually add based on selected FAMILY - family_add_subdirectory(host_hid_to_device_cdc) -endif() + message("Skipping dual host/device mode examples as Pico-PIO-USB is not available") +else () + # family_add_subdirectory will filter what to actually add based on selected FAMILY + family_add_subdirectory(host_hid_to_device_cdc) +endif () diff --git a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt index 3505d39eb..c6d19a720 100644 --- a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt +++ b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt @@ -14,14 +14,14 @@ add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. @@ -29,12 +29,12 @@ family_configure_dual_usb_example(${PROJECT}) # due to warnings from Pico-PIO-USB target_compile_options(${PROJECT} PUBLIC - -Wno-error=shadow - -Wno-error=cast-align - -Wno-error=cast-qual - -Wno-error=redundant-decls - -Wno-error=sign-conversion - -Wno-error=conversion - -Wno-error=sign-compare - -Wno-error=unused-function - ) + -Wno-error=shadow + -Wno-error=cast-align + -Wno-error=cast-qual + -Wno-error=redundant-decls + -Wno-error=sign-conversion + -Wno-error=conversion + -Wno-error=sign-compare + -Wno-error=unused-function + ) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 26baa6365..01e7bb018 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -27,8 +27,8 @@ if (NOT TARGET _family_support_marker) foreach(MCU IN LISTS FAMILY_MCUS) # For each line in only.txt foreach(_line ${ONLYS_LINES}) - # If mcu:xxx exists for this mcu then include - if (${_line} STREQUAL "mcu:${MCU}") + # If mcu:xxx exists for this mcu or board:xxx then include + if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}") set(${RESULT} 1 PARENT_SCOPE) return() endif() diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 85ad104a0..b510c064e 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -173,3 +173,7 @@ endfunction() function(family_configure_host_example TARGET) family_configure_target(${TARGET}) endfunction() + +function(family_configure_dual_usb_example TARGET) + family_configure_target(${TARGET}) +endfunction() diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index d607627b4..b06633f30 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -76,6 +76,8 @@ bool hcd_init(uint8_t rhport) #endif // FIXME force full speed, still have issue with Highspeed enumeration + // 1. Have issue when plug/unplug devices, maybe the port is not reset properly + // 2. Also does not seems to detect disconnection hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD); -- cgit v1.3.1 From 206d63e038744b228cfa6051d701cab50b520fe6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 May 2023 14:26:12 +0700 Subject: correct EHCI reporting failed xfer (instead of stalled) when device is unplugged --- src/class/cdc/cdc_host.c | 21 +++++++++++---------- src/class/hid/hid_host.c | 27 ++++++++++++++++----------- src/class/msc/msc_host.c | 10 +++++++--- src/common/tusb_debug.h | 1 + src/device/usbd_control.c | 9 ++++++--- src/host/hub.c | 9 ++++++++- src/host/usbh.c | 20 +++++++++++++------- src/portable/ehci/ehci.c | 11 ++++++++--- src/tusb.c | 4 ++++ 9 files changed, 74 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index fe3691bf4..9ff666ed4 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -35,8 +35,7 @@ // Debug level, TUSB_CFG_DEBUG must be at least this level for debug message #define CDCH_DEBUG 2 - -#define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) +#define TU_LOG_DRV(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) //--------------------------------------------------------------------+ // Host CDC Interface @@ -537,6 +536,8 @@ void cdch_close(uint8_t daddr) cdch_interface_t* p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { + TU_LOG_DRV(" CDCh close addr = %u index = %u\r\n", daddr, idx); + // Invoke application callback if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx); @@ -804,7 +805,7 @@ static void acm_process_config(tuh_xfer_t* xfer) static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_LOG_CDCH("CDC ACM Set Control Line State\r\n"); + TU_LOG_DRV("CDC ACM Set Control Line State\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -834,7 +835,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st } static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC ACM Set Line Conding\r\n"); + TU_LOG_DRV("CDC ACM Set Line Conding\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -894,7 +895,7 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_CDCH("FTDI opened\r\n"); + TU_LOG_DRV("FTDI opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_FTDI; @@ -938,7 +939,7 @@ static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, u static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC FTDI Set Control Line State\r\n"); + TU_LOG_DRV("CDC FTDI Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -974,7 +975,7 @@ static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); - TU_LOG_CDCH("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor); + TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor); p_cdc->user_control_cb = complete_cb; _ftdi_requested_baud = baudrate; @@ -1061,7 +1062,7 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_CDCH("CP210x opened\r\n"); + TU_LOG_DRV("CP210x opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_CP210X; // endpoint pair @@ -1109,7 +1110,7 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe } static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC CP210x Set BaudRate = %lu\n", baudrate); + TU_LOG_DRV("CDC CP210x Set BaudRate = %lu\n", baudrate); uint32_t baud_le = tu_htole32(baudrate); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, @@ -1118,7 +1119,7 @@ static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_ static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC CP210x Set Control Line State\r\n"); + TU_LOG_DRV("CDC CP210x Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, complete_cb ? cdch_internal_control_complete : NULL, user_data); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index d95d3ef35..3a491937a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -33,6 +33,10 @@ #include "hid_host.h" +// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message +#define HIDH_DEBUG 2 +#define TU_LOG_DRV(...) TU_LOG(HIDH_DEBUG, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -207,7 +211,7 @@ static void set_protocol_complete(tuh_xfer_t* xfer) static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG2("HID Set Protocol = %d\r\n", protocol); + TU_LOG_DRV("HID Set Protocol = %d\r\n", protocol); tusb_control_request_t const request = { @@ -246,7 +250,7 @@ bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) static void set_report_complete(tuh_xfer_t* xfer) { - TU_LOG2("HID Set Report complete\r\n"); + TU_LOG_DRV("HID Set Report complete\r\n"); if (tuh_hid_set_report_complete_cb) { @@ -266,7 +270,7 @@ bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t r hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); - TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + TU_LOG_DRV("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); tusb_control_request_t const request = { @@ -298,7 +302,7 @@ bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t r static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // SET IDLE request, device can stall if not support this request - TU_LOG2("HID Set Idle \r\n"); + TU_LOG_DRV("HID Set Idle \r\n"); tusb_control_request_t const request = { @@ -367,7 +371,7 @@ bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx) bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len) { - TU_LOG2("HID Send Report %d\r\n", report_id); + TU_LOG_DRV("HID Send Report %d\r\n", report_id); hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); @@ -430,7 +434,7 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t if ( dir == TUSB_DIR_IN ) { - TU_LOG2(" Get Report callback (%u, %u)\r\n", daddr, idx); + TU_LOG_DRV(" Get Report callback (%u, %u)\r\n", daddr, idx); TU_LOG3_MEM(p_hid->epin_buf, xferred_bytes, 2); tuh_hid_report_received_cb(daddr, idx, p_hid->epin_buf, (uint16_t) xferred_bytes); }else @@ -448,8 +452,9 @@ void hidh_close(uint8_t daddr) hidh_interface_t* p_hid = &_hidh_itf[i]; if (p_hid->daddr == daddr) { - if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); - p_hid->daddr = 0; + TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i); + if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); + p_hid->daddr = 0; } } } @@ -465,7 +470,7 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_ TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - TU_LOG2("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); + TU_LOG_DRV("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); // len = interface + hid + n*endpoints uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + @@ -592,7 +597,7 @@ static void process_set_config(tuh_xfer_t* xfer) // using usbh enumeration buffer since report descriptor can be very long if( p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) { - TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len); + TU_LOG_DRV("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len); // Driver is mounted without report descriptor config_driver_mount_complete(daddr, idx, NULL, 0); @@ -763,7 +768,7 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, for ( uint8_t i = 0; i < report_num; i++ ) { info = report_info_arr+i; - TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); + TU_LOG_DRV("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); } return report_num; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 1b48813ec..138443de4 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -35,7 +35,6 @@ // Debug level, TUSB_CFG_DEBUG must be at least this level for debug message #define MSCH_DEBUG 2 - #define TU_LOG_MSCH(...) TU_LOG(MSCH_DEBUG, __VA_ARGS__) //--------------------------------------------------------------------+ @@ -82,6 +81,7 @@ CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; +// FIXME potential nul reference TU_ATTR_ALWAYS_INLINE static inline msch_interface_t* get_itf(uint8_t dev_addr) { @@ -305,11 +305,15 @@ void msch_init(void) void msch_close(uint8_t dev_addr) { TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured, ); + + TU_LOG_MSCH(" MSCh close addr = %d\r\n", dev_addr); // invoke Application Callback - if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + if (p_msc->mounted) { + if(tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + } tu_memclr(p_msc, sizeof(msch_interface_t)); } diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 82f682043..36507041f 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -46,6 +46,7 @@ #if CFG_TUSB_DEBUG >= 2 extern char const* const tu_str_speed[]; extern char const* const tu_str_std_request[]; +extern char const* const tu_str_xfer_result[]; #endif void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index ea8eef285..2afe967b5 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -32,7 +32,10 @@ #include "tusb.h" #include "device/usbd_pvt.h" -#if CFG_TUSB_DEBUG >= 2 +// Debug level of USBD Control +#define USBD_CONTROL_DEBUG 2 + +#if CFG_TUSB_DEBUG >= USBD_CONTROL_DEBUG extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif @@ -188,7 +191,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result { TU_VERIFY(_ctrl_xfer.buffer); memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); - TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); + TU_LOG_MEM(USBD_CONTROL_DEBUG, _usbd_ctrl_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += (uint16_t) xferred_bytes; @@ -205,7 +208,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // callback can still stall control in status phase e.g out data does not make sense if ( _ctrl_xfer.complete_cb ) { - #if CFG_TUSB_DEBUG >= 2 + #if CFG_TUSB_DEBUG >= USBD_CONTROL_DEBUG usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif diff --git a/src/host/hub.c b/src/host/hub.c index 386ad6aae..85bf22b3e 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -33,6 +33,10 @@ #include "usbh_classdriver.h" #include "hub.h" +// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message +#define HUB_DEBUG 2 +#define TU_LOG_DRV(...) TU_LOG(HUB_DEBUG, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -218,7 +222,10 @@ void hub_close(uint8_t dev_addr) TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, ); hub_interface_t* p_hub = get_itf(dev_addr); - if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t)); + if (p_hub->ep_in) { + TU_LOG_DRV(" HUB close addr = %d\r\n", dev_addr); + tu_memclr(p_hub, sizeof( hub_interface_t)); + } } bool hub_edpt_status_xfer(uint8_t dev_addr) diff --git a/src/host/usbh.c b/src/host/usbh.c index 24ce47a7f..4cfc7c5c2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -61,6 +61,8 @@ typedef struct uint8_t hub_addr; uint8_t hub_port; uint8_t speed; + + // enumeration is in progress, done when all interfaces are configured volatile uint8_t enumerating; // struct TU_ATTR_PACKED { @@ -436,7 +438,8 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG_USBH("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG_USBH("on EP %02X with %u bytes %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, + tu_str_xfer_result[event.xfer_complete.result]); if (event.dev_addr == 0) { @@ -866,6 +869,10 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) { switch (event->event_id) { +// case HCD_EVENT_DEVICE_REMOVE: +// +// break; + default: osal_queue_send(_usbh_q, event, in_isr); break; @@ -1128,30 +1135,28 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h usbh_device_t* dev = &_usbh_devices[dev_id]; uint8_t const dev_addr = dev_id+1; - // TODO Hub multiple level if (dev->rhport == rhport && (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr = 0 means roothub (hub_port == 0 || dev->hub_port == hub_port) && // hub_port = 0 means all devices of downstream hub dev->connected) { - TU_LOG_USBH(" Address = %u\r\n", dev_addr); + TU_LOG_USBH("Device unplugged address = %u\r\n", dev_addr); if (is_hub_addr(dev_addr)) { - TU_LOG(USBH_DEBUG, "HUB address = %u is unmounted\r\n", dev_addr); + TU_LOG(USBH_DEBUG, " is a HUB device\r\n", dev_addr); // If the device itself is a usb hub, unplug downstream devices. // FIXME un-roll recursive calls to prevent potential stack overflow process_device_unplugged(rhport, dev_addr, 0); }else { - // Invoke callback before closing driver + // Invoke callback before closing driver (maybe call it later ?) if (tuh_umount_cb) tuh_umount_cb(dev_addr); } // Close class driver for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { - TU_LOG_USBH("%s close\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].close(dev_addr); } @@ -1449,6 +1454,7 @@ static uint8_t get_new_address(bool is_hub) { uint8_t start; uint8_t end; + if ( is_hub ) { start = CFG_TUH_DEVICE_MAX; @@ -1459,7 +1465,7 @@ static uint8_t get_new_address(bool is_hub) end = start + CFG_TUH_DEVICE_MAX; } - for ( uint8_t idx = start; idx < end; idx++) + for (uint8_t idx = start; idx < end; idx++) { if (!_usbh_devices[idx].connected) return (idx+1); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 494e2e50f..69e59ce65 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -142,8 +142,11 @@ static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); // determine if a queue head has bus-related error static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd) { - return (p_qhd->qtd_overlay.buffer_err || p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err); - //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error + volatile ehci_qtd_t *qtd_overlay = &p_qhd->qtd_overlay; + + // Error count = 0 often occurs when device disconnected + return (qtd_overlay->err_count == 0 || qtd_overlay->buffer_err || qtd_overlay->babble_err || qtd_overlay->xact_err); + //qtd_overlay->non_hs_period_missed_uframe || qtd_overlay->pingstate_err TODO split transaction error } static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); @@ -630,7 +633,9 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; -// if ( XFER_RESULT_FAILED == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device +// if ( XFER_RESULT_FAILED == error_event ) { +// TU_BREAKPOINT(); // TODO skip unplugged device +// } p_qhd->p_qtd_list_head->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); diff --git a/src/tusb.c b/src/tusb.c index 85fe5a3cc..7327db685 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -439,6 +439,10 @@ char const* const tu_str_std_request[] = "Synch Frame" }; +char const* const tu_str_xfer_result[] = { + "OK", "Failed", "Stalled", "Timeout" +}; + #endif static void dump_str_line(uint8_t const* buf, uint16_t count) -- cgit v1.3.1 From 1c4f22a54cf60e6221995f9b64e2e765fd0a5bfe Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 May 2023 22:18:40 +0700 Subject: EHCI: fix xfer failed with disconnected device as stalled - change CFG_TUH_ENDPOINT_MAX to 16 (max endpoint pair per device) if not defined - change QHD_MAX for EHCI, should be user configurable and more optimized in the future --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- hw/bsp/imxrt/family.c | 5 +++- src/class/hid/hid_host.c | 2 +- src/host/hcd.h | 4 ++- src/portable/ehci/ehci.c | 48 +++++++++++++-------------------- 5 files changed, 27 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index ed53c502d..87e110ab2 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -263,7 +263,7 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c if (!rpt_info) { - printf("Couldn't find the report info for this report !\r\n"); + printf("Couldn't find report info !\r\n"); return; } diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index 52d3bb91b..46adabf0a 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -131,7 +131,10 @@ void board_init(void) freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U); } - LPUART_Init(UART_PORT, &uart_config, freq); + if ( kStatus_Success != LPUART_Init(UART_PORT, &uart_config, freq) ) { + // failed to init uart, probably baudrate is not supported + // TU_BREAKPOINT(); + } //------------- USB -------------// // Note: RT105x RT106x and later have dual USB controllers. diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 3a491937a..6abe298e5 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -72,7 +72,7 @@ tu_static hidh_interface_t _hidh_itf[CFG_TUH_HID]; TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_hid_itf(uint8_t daddr, uint8_t idx) { - TU_ASSERT(daddr && idx < CFG_TUH_HID, NULL); + TU_ASSERT(daddr > 0 && idx < CFG_TUH_HID, NULL); hidh_interface_t* p_hid = &_hidh_itf[idx]; return (p_hid->daddr == daddr) ? p_hid : NULL; } diff --git a/src/host/hcd.h b/src/host/hcd.h index 623c12a12..f4e76f9ef 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -39,8 +39,10 @@ // Configuration //--------------------------------------------------------------------+ +// Max number of endpoints per device +// TODO optimize memory usage #ifndef CFG_TUH_ENDPOINT_MAX - #define CFG_TUH_ENDPOINT_MAX (CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3) + #define CFG_TUH_ENDPOINT_MAX 16 // #ifdef TUP_HCD_ENDPOINT_MAX // #define CFG_TUH_ENDPPOINT_MAX TUP_HCD_ENDPOINT_MAX // #else diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 69e59ce65..080ee9bbc 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -58,7 +58,8 @@ #define FRAMELIST_SIZE (1024 >> FRAMELIST_SIZE_BIT_VALUE) -#define QHD_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX) +// Total queue head pool. TODO should be user configurable and more optimize memory usage in the future +#define QHD_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX + CFG_TUH_HUB) #define QTD_MAX QHD_MAX typedef struct @@ -138,17 +139,6 @@ static inline ehci_qtd_t* qtd_control(uint8_t dev_addr) static inline ehci_qhd_t* qhd_next (ehci_qhd_t const * p_qhd); static inline ehci_qhd_t* qhd_find_free (void); static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); - -// determine if a queue head has bus-related error -static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd) -{ - volatile ehci_qtd_t *qtd_overlay = &p_qhd->qtd_overlay; - - // Error count = 0 often occurs when device disconnected - return (qtd_overlay->err_count == 0 || qtd_overlay->buffer_err || qtd_overlay->babble_err || qtd_overlay->xact_err); - //qtd_overlay->non_hs_period_missed_uframe || qtd_overlay->pingstate_err TODO split transaction error -} - static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); static inline ehci_qtd_t* qtd_find_free (void); @@ -392,15 +382,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// - ehci_qhd_t * p_qhd; - - if ( ep_desc->bEndpointAddress == 0 ) - { - p_qhd = qhd_control(dev_addr); - }else - { - p_qhd = qhd_find_free(); - } + ehci_qhd_t *p_qhd = (ep_desc->bEndpointAddress == 0) ? qhd_control(dev_addr) : qhd_find_free(); TU_ASSERT(p_qhd); qhd_init(p_qhd, dev_addr, ep_desc); @@ -622,18 +604,23 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms) static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) { - if ( (p_qhd->dev_addr != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL - qhd_has_xact_error(p_qhd) ) - { - // current qhd has error in transaction - xfer_result_t error_event; + volatile ehci_qtd_t *qtd_overlay = &p_qhd->qtd_overlay; + + // TD has error + if (qtd_overlay->halted) { + xfer_result_t xfer_result; - // no error bits are set, endpoint is halted due to STALL - error_event = qhd_has_xact_error(p_qhd) ? XFER_RESULT_FAILED : XFER_RESULT_STALLED; + if (qtd_overlay->err_count == 0 || qtd_overlay->buffer_err || qtd_overlay->babble_err || qtd_overlay->xact_err) { + // Error count = 0 often occurs when device disconnected, or other bus-related error + xfer_result = XFER_RESULT_FAILED; + }else { + // no error bits are set, endpoint is halted due to STALL + xfer_result = XFER_RESULT_STALLED; + } p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; -// if ( XFER_RESULT_FAILED == error_event ) { +// if (XFER_RESULT_FAILED == xfer_result ) { // TU_BREAKPOINT(); // TODO skip unplugged device // } @@ -655,7 +642,8 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, error_event, true); + uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0); + hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, xfer_result, true); p_qhd->total_xferred_bytes = 0; } -- cgit v1.3.1 From 2c48050993777c586210af503504e612f31228d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 May 2023 22:21:18 +0700 Subject: add various check for disconncted device, also fix #1511 un-roll recursive hub removal with usbh queue --- src/host/usbh.c | 124 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 4cfc7c5c2..c56ff9459 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -81,10 +81,12 @@ typedef struct { // Device State struct TU_ATTR_PACKED { - volatile uint8_t connected : 1; - volatile uint8_t addressed : 1; - volatile uint8_t configured : 1; - volatile uint8_t suspended : 1; + volatile uint8_t connected : 1; // After 1st transfer + volatile uint8_t addressed : 1; // After SET_ADDR + volatile uint8_t configured : 1; // After SET_CONFIG and all drivers are configured + volatile uint8_t suspended : 1; // Bus suspended + + // volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh }; // Device Descriptor @@ -248,7 +250,7 @@ static inline usbh_device_t* get_device(uint8_t dev_addr) } static bool enum_new_device(hcd_event_t* event); -static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); +static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); @@ -420,7 +422,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) case HCD_EVENT_DEVICE_REMOVE: TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); - process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); + process_removing_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); #if CFG_TUH_HUB // TODO remove @@ -450,7 +452,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) else { usbh_device_t* dev = get_device(event.dev_addr); - TU_ASSERT(dev, ); + TU_VERIFY(dev && dev->connected, ); dev->ep_status[epnum][ep_dir].busy = 0; dev->ep_status[epnum][ep_dir].claimed = 0; @@ -739,29 +741,33 @@ void usbh_int_set(bool enabled) // TODO has some duplication code with device, refactor later bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { + // Note: addr0 only use tuh_control_xfer usbh_device_t* dev = get_device(dev_addr); - - // addr0 only use tuh_control_xfer - TU_ASSERT(dev); + TU_ASSERT(dev && dev->connected); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - return tu_edpt_claim(&dev->ep_status[epnum][dir], _usbh_mutex); + TU_VERIFY(tu_edpt_claim(&dev->ep_status[epnum][dir], _usbh_mutex)); + TU_LOG_USBH("[%u] Claimed EP 0x%02x\r\n", dev_addr, ep_addr); + + return true; } // TODO has some duplication code with device, refactor later bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { + // Note: addr0 only use tuh_control_xfer usbh_device_t* dev = get_device(dev_addr); - - // addr0 only use tuh_control_xfer - TU_ASSERT(dev); + TU_VERIFY(dev && dev->connected); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - return tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex); + TU_VERIFY(tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex)); + TU_LOG_USBH("[%u] Released EP 0x%02x\r\n", dev_addr, ep_addr); + + return true; } // TODO has some duplication code with device, refactor later @@ -870,7 +876,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) switch (event->event_id) { // case HCD_EVENT_DEVICE_REMOVE: -// +// // mark device as removing to prevent further xfer before the event is processed in usbh task // break; default: @@ -1116,7 +1122,7 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i } //--------------------------------------------------------------------+ -// +// Detaching //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE @@ -1125,45 +1131,79 @@ static inline bool is_hub_addr(uint8_t daddr) return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); } +//static void mark_removing_device_isr(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { +// for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { +// usbh_device_t *dev = &_usbh_devices[dev_id]; +// uint8_t const daddr = dev_id + 1; +// +// // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub +// if (dev->rhport == rhport && dev->connected && +// (hub_addr == 0 || dev->hub_addr == hub_addr) && +// (hub_port == 0 || dev->hub_port == hub_port)) { +// if (is_hub_addr(daddr)) { +// // If the device itself is a usb hub, mark all downstream devices. +// // FIXME recursive calls +// mark_removing_device_isr(rhport, daddr, 0); +// } +// +// dev->removing = 1; +// } +// } +//} + // a device unplugged from rhport:hub_addr:hub_port -static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) +static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// // TODO mark as disconnected in ISR, also handle dev0 - for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) - { - usbh_device_t* dev = &_usbh_devices[dev_id]; - uint8_t const dev_addr = dev_id+1; - if (dev->rhport == rhport && - (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr = 0 means roothub - (hub_port == 0 || dev->hub_port == hub_port) && // hub_port = 0 means all devices of downstream hub - dev->connected) - { - TU_LOG_USBH("Device unplugged address = %u\r\n", dev_addr); +#if 0 + // index as hub addr, value is hub port (0xFF for invalid) + uint8_t removing_hubs[CFG_TUH_HUB]; + memset(removing_hubs, TUSB_INDEX_INVALID_8, sizeof(removing_hubs)); - if (is_hub_addr(dev_addr)) - { - TU_LOG(USBH_DEBUG, " is a HUB device\r\n", dev_addr); - // If the device itself is a usb hub, unplug downstream devices. - // FIXME un-roll recursive calls to prevent potential stack overflow - process_device_unplugged(rhport, dev_addr, 0); - }else - { + removing_hubs[hub_addr-CFG_TUH_DEVICE_MAX] = hub_port; + + // consecutive non-removing hub + uint8_t nop_count = 0; +#endif + + for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { + usbh_device_t *dev = &_usbh_devices[dev_id]; + uint8_t const daddr = dev_id + 1; + + // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub + if (dev->rhport == rhport && dev->connected && + (hub_addr == 0 || dev->hub_addr == hub_addr) && + (hub_port == 0 || dev->hub_port == hub_port)) { + TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); + + if (is_hub_addr(daddr)) { + TU_LOG(USBH_DEBUG, " is a HUB device\r\n", daddr); + + // Submit removed event If the device itself is a hub (un-rolled recursive) + // TODO a better to unroll recursrive is using array of removing_hubs and mark it here + hcd_event_t event; + event.rhport = rhport; + event.event_id = HCD_EVENT_DEVICE_REMOVE; + event.connection.hub_addr = daddr; + event.connection.hub_port = 0; + + hcd_event_handler(&event, false); + } else { // Invoke callback before closing driver (maybe call it later ?) - if (tuh_umount_cb) tuh_umount_cb(dev_addr); + if (tuh_umount_cb) tuh_umount_cb(daddr); } // Close class driver - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - usbh_class_drivers[drv_id].close(dev_addr); + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { + usbh_class_drivers[drv_id].close(daddr); } - hcd_device_close(rhport, dev_addr); + hcd_device_close(rhport, daddr); clear_device(dev); // abort on-going control xfer if any - if (_ctrl_xfer.daddr == dev_addr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); + if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); } } } -- cgit v1.3.1 From 1e998ce3bd1ecdf535a8a9feb6823627f3cf7c14 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 May 2023 10:58:42 +0700 Subject: usbd: fix control transfer issue for chipidea hs when previous status and new setup complete in the same isr frame change usbd edpt busy/stalled/claimed value to 0/1 instead of (true/false) since they are 1-bit field. --- .idea/runConfigurations/rt1010.xml | 10 -------- .idea/runConfigurations/rt1010_nxplink.xml | 10 ++++++++ src/device/usbd.c | 39 +++++++++++++++--------------- src/portable/chipidea/ci_hs/dcd_ci_hs.c | 18 +++++++------- 4 files changed, 39 insertions(+), 38 deletions(-) delete mode 100644 .idea/runConfigurations/rt1010.xml create mode 100644 .idea/runConfigurations/rt1010_nxplink.xml (limited to 'src') diff --git a/.idea/runConfigurations/rt1010.xml b/.idea/runConfigurations/rt1010.xml deleted file mode 100644 index 700cb5732..000000000 --- a/.idea/runConfigurations/rt1010.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations/rt1010_nxplink.xml b/.idea/runConfigurations/rt1010_nxplink.xml new file mode 100644 index 000000000..cf3bf842f --- /dev/null +++ b/.idea/runConfigurations/rt1010_nxplink.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/device/usbd.c b/src/device/usbd.c index cee56af60..409a5ec10 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -516,9 +516,9 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) _usbd_dev.connected = 1; // mark both in & out control as free - _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = 0; _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = 0; _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; // Process control request @@ -540,12 +540,13 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) TU_LOG(USBD_DBG, "on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - _usbd_dev.ep_status[epnum][ep_dir].busy = false; + _usbd_dev.ep_status[epnum][ep_dir].busy = 0; _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete + .len); } else { @@ -553,7 +554,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) TU_ASSERT(driver, ); TU_LOG(USBD_DBG, " %s xfer callback\r\n", driver->name); - driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); + driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -1244,7 +1245,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() // could return and USBD task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; + _usbd_dev.ep_status[epnum][dir].busy = 1; if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) { @@ -1252,7 +1253,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t }else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; TU_LOG(USBD_DBG, "FAILED\r\n"); TU_BREAKPOINT(); @@ -1278,7 +1279,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; + _usbd_dev.ep_status[epnum][dir].busy = 1; if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { @@ -1287,7 +1288,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 }else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].busy = 0; _usbd_dev.ep_status[epnum][dir].claimed = 0; TU_LOG(USBD_DBG, "failed\r\n"); TU_BREAKPOINT(); @@ -1317,8 +1318,8 @@ void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = true; - _usbd_dev.ep_status[epnum][dir].busy = true; + _usbd_dev.ep_status[epnum][dir].stalled = 1; + _usbd_dev.ep_status[epnum][dir].busy = 1; } } @@ -1334,8 +1335,8 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; } } @@ -1366,9 +1367,9 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_close(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; + _usbd_dev.ep_status[epnum][dir].claimed = 0; return; } @@ -1403,9 +1404,9 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX); TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; + _usbd_dev.ep_status[epnum][dir].stalled = 0; + _usbd_dev.ep_status[epnum][dir].busy = 0; + _usbd_dev.ep_status[epnum][dir].claimed = 0; return dcd_edpt_iso_activate(rhport, desc_ep); } diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index bc6736cf2..9be79a2f1 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -616,15 +616,6 @@ void dcd_int_handler(uint8_t rhport) uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE; dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge - if (dcd_reg->ENDPTSETUPSTAT) - { - //------------- Set up Received -------------// - // 23.10.10.2 Operational model for setup transfers - dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT; - - dcd_event_setup_received(rhport, (uint8_t*)(uintptr_t) &_dcd_data.qhd[0][0].setup_request, true); - } - // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set // nothing to do, we will submit xfer as error to usbd // if (int_status & INTR_ERROR) { } @@ -637,6 +628,15 @@ void dcd_int_handler(uint8_t rhport) if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN); } } + + // Set up Received + // 23.10.10.2 Operational model for setup transfers + // Must be after normal transfer complete since it is possible to have both previous control status + new setup + // in the same frame and we should handle previous status first. + if (dcd_reg->ENDPTSETUPSTAT) { + dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT; + dcd_event_setup_received(rhport, (uint8_t *) (uintptr_t) &_dcd_data.qhd[0][0].setup_request, true); + } } if (int_status & INTR_SOF) -- cgit v1.3.1 From a9aa0e3a1a9323df16c91d7705aad480033f962a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 May 2023 13:20:09 +0700 Subject: fix error on EHCI causes xfer error in non-queued qhd which cause memory fault --- .idea/cmake.xml | 2 + .../dual/host_hid_to_device_cdc/src/tusb_config.h | 6 +-- src/portable/ehci/ehci.c | 46 ++++++++++++++++------ src/portable/ehci/ehci.h | 2 +- 4 files changed, 37 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/.idea/cmake.xml b/.idea/cmake.xml index bbef86164..7dacd0003 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -2,6 +2,7 @@ + @@ -27,6 +28,7 @@ + \ No newline at end of file diff --git a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h index 2185cd1f1..8133ed418 100644 --- a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h +++ b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h @@ -84,10 +84,6 @@ #define CFG_TUH_RPI_PIO_USB 1 #endif - -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 - /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put * into those specific section. @@ -133,7 +129,7 @@ #endif #ifndef CFG_TUH_MEM_ALIGN -#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4))) +#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4))) #endif #define CFG_TUH_HUB 1 diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 080ee9bbc..8203b0f06 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -93,16 +93,30 @@ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; // Debug //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= EHCI_DBG -static inline void print_portsc(ehci_registers_t* regs) -{ +static inline void print_portsc(ehci_registers_t* regs) { TU_LOG_HEX(EHCI_DBG, regs->portsc); - TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status); - TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change); - TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled); - TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change); - - TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset); - TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power); + TU_LOG(EHCI_DBG, " Connect Status : %u\r\n", regs->portsc_bm.current_connect_status); + TU_LOG(EHCI_DBG, " Connect Change : %u\r\n", regs->portsc_bm.connect_status_change); + TU_LOG(EHCI_DBG, " Enabled : %u\r\n", regs->portsc_bm.port_enabled); + TU_LOG(EHCI_DBG, " Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change); + + TU_LOG(EHCI_DBG, " OverCurr Change: %u\r\n", regs->portsc_bm.over_current_change); + TU_LOG(EHCI_DBG, " Force Resume : %u\r\n", regs->portsc_bm.force_port_resume); + TU_LOG(EHCI_DBG, " Suspend : %u\r\n", regs->portsc_bm.suspend); + TU_LOG(EHCI_DBG, " Reset : %u\r\n", regs->portsc_bm.port_reset); + TU_LOG(EHCI_DBG, " Power : %u\r\n", regs->portsc_bm.port_power); +} + +static inline void print_intr(uint32_t intr) { + TU_LOG_HEX(EHCI_DBG, intr); + TU_LOG(EHCI_DBG, " USB Interrupt : %u\r\n", (intr & EHCI_INT_MASK_USB) ? 1 : 0); + TU_LOG(EHCI_DBG, " USB Error : %u\r\n", (intr & EHCI_INT_MASK_ERROR) ? 1 : 0); + TU_LOG(EHCI_DBG, " Port Change Detect : %u\r\n", (intr & EHCI_INT_MASK_PORT_CHANGE) ? 1 : 0); + TU_LOG(EHCI_DBG, " Frame List Rollover: %u\r\n", (intr & EHCI_INT_MASK_FRAMELIST_ROLLOVER) ? 1 : 0); + TU_LOG(EHCI_DBG, " Host System Error : %u\r\n", (intr & EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR) ? 1 : 0); + TU_LOG(EHCI_DBG, " Async Advance : %u\r\n", (intr & EHCI_INT_MASK_ASYNC_ADVANCE) ? 1 : 0); +// TU_LOG(EHCI_DBG, " Interrupt on Async: %u\r\n", (intr & EHCI_INT_MASK_NXP_ASYNC)); +// TU_LOG(EHCI_DBG, " Periodic Schedule : %u\r\n", (intr & EHCI_INT_MASK_NXP_PERIODIC)); } #else @@ -166,8 +180,8 @@ void hcd_port_reset(uint8_t rhport) ehci_registers_t* regs = ehci_data.regs; - // mask out all change bits since they are Write 1 to clear - uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL; + // mask out Write-1-to-Clear bits + uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; // EHCI Table 2-16 PortSC // when software writes Port Reset bit to a one, it must also write a zero to the Port Enable bit. @@ -347,7 +361,7 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) // Power Control (PPC) field in the HCSPARAMS register. if (ehci_data.cap_regs->hcsparams_bm.port_power_control) { // mask out all change bits since they are Write 1 to clear - uint32_t portsc = (regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL); + uint32_t portsc = (regs->portsc & ~EHCI_PORTSC_MASK_W1C); portsc |= ECHI_PORTSC_MASK_PORT_POWER; regs->portsc = portsc; @@ -621,9 +635,14 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; // if (XFER_RESULT_FAILED == xfer_result ) { +// TU_LOG1(" QHD xfer err count: %d\n", qtd_overlay->err_count); // TU_BREAKPOINT(); // TODO skip unplugged device +// while(1){} // } + // No TD, probably an signal noise ? + TU_VERIFY(p_qhd->p_qtd_list_head, ); + p_qhd->p_qtd_list_head->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); @@ -710,7 +729,8 @@ void hcd_int_handler(uint8_t rhport) if (int_status & EHCI_INT_MASK_PORT_CHANGE) { - uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_CHANGE_ALL; + // Including: Force port resume, over-current change, enable/disable change and connect status change. + uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_W1C; print_portsc(regs); if (regs->portsc_bm.connect_status_change) diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index dd090cb36..a73e43707 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -306,7 +306,7 @@ enum { EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), ECHI_PORTSC_MASK_PORT_POWER = TU_BIT(12), - EHCI_PORTSC_MASK_CHANGE_ALL = + EHCI_PORTSC_MASK_W1C = EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | EHCI_PORTSC_MASK_PORT_ENABLE_CHANGE | EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE -- cgit v1.3.1 From eb89df411540cb8cf5323991516a45590fa0b81d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 May 2023 16:14:35 +0700 Subject: adding hcd_dcache_clean/hcd_dcache_invalidate --- hw/bsp/imxrt/family.cmake | 15 +++++++++++++++ src/host/hcd.h | 10 ++++++++++ src/portable/chipidea/ci_hs/hcd_ci_hs.c | 9 +++++++++ src/portable/ehci/ehci.h | 7 +++++++ 4 files changed, 41 insertions(+) (limited to 'src') diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 77ac05c87..4628abc34 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -144,6 +144,21 @@ function(family_configure_target TARGET) COMMAND ${LINKSERVER_PATH} flash ${NXPLINK_DEVICE} load $ ) + # Flash using jlink + set(JLINKEXE JLinkExe) + file(GENERATE + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.jlink + CONTENT "halt +loadfile $ +r +go +exit" + ) + add_custom_target(${TARGET}-jlink + DEPENDS ${TARGET} + COMMAND ${JLINKEXE} -device ${JLINK_DEVICE} -if swd -JTAGConf -1,-1 -speed auto -CommandFile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.jlink + ) + endfunction() diff --git a/src/host/hcd.h b/src/host/hcd.h index f4e76f9ef..38c89a1d2 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -104,6 +104,16 @@ typedef struct uint8_t speed; } hcd_devtree_info_t; +//--------------------------------------------------------------------+ +// Memory API +//--------------------------------------------------------------------+ + +// clean/flush data cache: write cache -> memory +void hcd_dcache_clean(void* addr, uint32_t data_size) TU_ATTR_WEAK; + +// invalidate data cache: mark cache as invalid, next read will read from memory +void hcd_dcache_invalidate(void* addr, uint32_t data_size) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index b06633f30..56ca01f85 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -41,6 +41,15 @@ #if CFG_TUSB_MCU == OPT_MCU_MIMXRT #include "ci_hs_imxrt.h" + + void hcd_dcache_clean(void* addr, uint32_t data_size) { + SCB_CleanDCache_by_Addr((uint32_t*) addr, (int32_t) data_size); + } + + void hcd_dcache_invalidate(void* addr, uint32_t data_size) { + SCB_InvalidateDCache_by_Addr(addr, (int32_t) data_size); + } + #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) #include "ci_hs_lpc18_43.h" #else diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index a73e43707..56befd306 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -268,6 +268,7 @@ TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); // EHCI Operational Register //--------------------------------------------------------------------+ enum { + // Bit 0-5 has maskable in interrupt enabled register EHCI_INT_MASK_USB = TU_BIT(0), EHCI_INT_MASK_ERROR = TU_BIT(1), EHCI_INT_MASK_PORT_CHANGE = TU_BIT(2), @@ -276,6 +277,12 @@ enum { EHCI_INT_MASK_ASYNC_ADVANCE = TU_BIT(5), EHCI_INT_MASK_NXP_SOF = TU_BIT(7), + + EHCI_INT_MASK_HC_HALTED = TU_BIT(12), + EHCI_INT_MASK_RECLAIMATION = TU_BIT(13), + EHCI_INT_MASK_PERIODIC_SCHED_STATUS = TU_BIT(14), + EHCI_INT_MASK_ASYNC_SCHED_STATUS = TU_BIT(15), + EHCI_INT_MASK_NXP_ASYNC = TU_BIT(18), EHCI_INT_MASK_NXP_PERIODIC = TU_BIT(19), -- cgit v1.3.1 From a3e017bfd2923dcb1ce86d395606a24e2285e54a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 May 2023 10:04:48 +0700 Subject: EHCI adding dcahe support, passing enumertaion --- src/host/hcd.h | 10 +- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 4 + src/portable/ehci/ehci.c | 167 ++++++++++++++++++++------------ src/portable/ehci/ehci.h | 1 + 4 files changed, 117 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/host/hcd.h b/src/host/hcd.h index 38c89a1d2..c6fde2adc 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -108,12 +108,18 @@ typedef struct // Memory API //--------------------------------------------------------------------+ -// clean/flush data cache: write cache -> memory +// clean/flush data cache: write cache -> memory. +// Required before an DMA TX transfer to make sure data is in memory void hcd_dcache_clean(void* addr, uint32_t data_size) TU_ATTR_WEAK; // invalidate data cache: mark cache as invalid, next read will read from memory +// Required BOTH before and after an DMA RX transfer void hcd_dcache_invalidate(void* addr, uint32_t data_size) TU_ATTR_WEAK; +// clean and invalidate data cache +// Required before an DMA transfer where memory is both read/write by DMA +void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ @@ -194,6 +200,7 @@ void hcd_event_device_attach(uint8_t rhport, bool in_isr) event.event_id = HCD_EVENT_DEVICE_ATTACH; event.connection.hub_addr = 0; event.connection.hub_port = 0; + hcd_event_handler(&event, in_isr); } @@ -224,7 +231,6 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred event.xfer_complete.result = result; event.xfer_complete.len = xferred_bytes; - hcd_event_handler(&event, in_isr); } diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index 56ca01f85..ecb1a621c 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -50,6 +50,10 @@ SCB_InvalidateDCache_by_Addr(addr, (int32_t) data_size); } +void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { + SCB_CleanInvalidateDCache_by_Addr(addr, (int32_t) data_size); + } + #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) #include "ci_hs_lpc18_43.h" #else diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 8203b0f06..9023e4b35 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -92,7 +92,7 @@ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= EHCI_DBG +#if CFG_TUSB_DEBUG >= (EHCI_DBG + 1) static inline void print_portsc(ehci_registers_t* regs) { TU_LOG_HEX(EHCI_DBG, regs->portsc); TU_LOG(EHCI_DBG, " Connect Status : %u\r\n", regs->portsc_bm.current_connect_status); @@ -159,7 +159,7 @@ static inline ehci_qtd_t* qtd_find_free (void); static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd); static inline void qtd_insert_to_qhd (ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new); static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd); -static void qtd_init (ehci_qtd_t* p_qtd, void const* buffer, uint16_t total_bytes); +static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes); static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); @@ -325,28 +325,27 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) // 3 --> period_head_arr[3] (8ms) // TODO EHCI_FRAMELIST_SIZE with other size than 8 - for(uint32_t i=0; iterminate = 1; regs->periodic_list_base = (uint32_t) framelist; + if(hcd_dcache_clean) { + hcd_dcache_clean(&ehci_data, sizeof(ehci_data_t)); + } + //------------- TT Control (NXP only) -------------// regs->nxp_tt_control = 0; @@ -430,6 +429,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const // TODO might need to disable async/period list list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); + if(hcd_dcache_clean) { + hcd_dcache_clean(p_qhd, sizeof(ehci_qhd_t)); + hcd_dcache_clean(list_head, sizeof(ehci_link_t)); + } + return true; } @@ -441,9 +445,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; qtd_init(td, setup_packet, 8); - td->pid = EHCI_PID_SETUP; - td->int_on_complete = 1; - td->next.terminate = 1; + td->pid = EHCI_PID_SETUP; + + if (hcd_dcache_clean && hcd_dcache_clean_invalidate) { + hcd_dcache_clean((void *) setup_packet, 8); + hcd_dcache_clean_invalidate(td, sizeof(ehci_qtd_t)); + } // sw region qhd->p_qtd_list_head = td; @@ -452,6 +459,10 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet // attach TD qhd->qtd_overlay.next.address = (uint32_t) td; + if (hcd_dcache_clean_invalidate) { + hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); + } + return true; } @@ -462,41 +473,48 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + ehci_qhd_t* qhd; + ehci_qtd_t* qtd; + if ( epnum == 0 ) { - ehci_qhd_t* qhd = qhd_control(dev_addr); - ehci_qtd_t* qtd = qtd_control(dev_addr); + qhd = qhd_control(dev_addr); + qtd = qtd_control(dev_addr); qtd_init(qtd, buffer, buflen); // first first data toggle is always 1 (data & setup stage) qtd->data_toggle = 1; qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT; - qtd->int_on_complete = 1; - qtd->next.terminate = 1; - - // sw region - qhd->p_qtd_list_head = qtd; - qhd->p_qtd_list_tail = qtd; - - // attach TD - qhd->qtd_overlay.next.address = (uint32_t) qtd; }else { - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - ehci_qtd_t *p_qtd = qtd_find_free(); - TU_ASSERT(p_qtd); + qhd = qhd_get_from_addr(dev_addr, ep_addr); + qtd = qtd_find_free(); + TU_ASSERT(qtd); + + qtd_init(qtd, buffer, buflen); + qtd->pid = qhd->pid; + } - qtd_init(p_qtd, buffer, buflen); - p_qtd->pid = p_qhd->pid; + if (hcd_dcache_clean && hcd_dcache_clean_invalidate) { + // IN transfer: invalidate buffer, OUT transfer: clean buffer + if (dir) { + hcd_dcache_invalidate(buffer, buflen); + }else { + hcd_dcache_clean(buffer, buflen); + } + hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t)); + } - // Insert TD to QH - qtd_insert_to_qhd(p_qhd, p_qtd); + // Software: assign TD to QHD + qhd->p_qtd_list_head = qtd; + qhd->p_qtd_list_tail = qtd; - p_qhd->p_qtd_list_tail->int_on_complete = 1; + // attach TD to QHD start transferring + qhd->qtd_overlay.next.address = (uint32_t) qtd; - // attach head QTD to QHD start transferring - p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; + if (hcd_dcache_clean_invalidate) { + hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); } return true; @@ -551,6 +569,11 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) { ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; + + if (hcd_dcache_invalidate) { + hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); + } + bool const is_ioc = (qtd->int_on_complete != 0); uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0); @@ -573,8 +596,12 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) ehci_qhd_t *p_qhd = async_head; do { - if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr - { + if (hcd_dcache_invalidate) { + hcd_dcache_invalidate(p_qhd, sizeof(ehci_qhd_t)); + } + + // halted or error is processed in error isr + if ( !p_qhd->qtd_overlay.halted ) { qhd_xfer_complete_isr(p_qhd); } p_qhd = qhd_next(p_qhd); @@ -640,8 +667,8 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) // while(1){} // } - // No TD, probably an signal noise ? - TU_VERIFY(p_qhd->p_qtd_list_head, ); + // No TD yet, it is probably the probably an signal noise ? + TU_ASSERT(p_qhd->p_qtd_list_head, ); p_qhd->p_qtd_list_head->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); @@ -714,17 +741,19 @@ static void xfer_error_isr(uint8_t hostid) void hcd_int_handler(uint8_t rhport) { ehci_registers_t* regs = ehci_data.regs; + uint32_t const int_status = regs->status; - uint32_t int_status = regs->status; - int_status &= regs->inten; - - regs->status = int_status; // Acknowledge handled interrupt - - if (int_status == 0) return; + if (int_status & EHCI_INT_MASK_HC_HALTED) { + // something seriously wrong, maybe forget to flush/invalidate cache + TU_BREAKPOINT(); + TU_LOG1(" HC halted\n"); + return; + } if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) { ehci_data.uframe_number += (FRAMELIST_SIZE << 3); + regs->status = EHCI_INT_MASK_FRAMELIST_ROLLOVER; // Acknowledge } if (int_status & EHCI_INT_MASK_PORT_CHANGE) @@ -739,31 +768,41 @@ void hcd_int_handler(uint8_t rhport) } regs->portsc |= port_status; // Acknowledge change bits in portsc + regs->status = EHCI_INT_MASK_PORT_CHANGE; // Acknowledge } if (int_status & EHCI_INT_MASK_ERROR) { xfer_error_isr(rhport); + regs->status = EHCI_INT_MASK_ERROR; // Acknowledge } //------------- some QTD/SITD/ITD with IOC set is completed -------------// if (int_status & EHCI_INT_MASK_NXP_ASYNC) { - async_list_xfer_complete_isr( qhd_async_head(rhport) ); + async_list_xfer_complete_isr(qhd_async_head(rhport)); + regs->status = EHCI_INT_MASK_NXP_ASYNC; // Acknowledge } if (int_status & EHCI_INT_MASK_NXP_PERIODIC) { for (uint32_t i=1; i <= FRAMELIST_SIZE; i *= 2) { - period_list_xfer_complete_isr( rhport, i ); + period_list_xfer_complete_isr(rhport, i); } + regs->status = EHCI_INT_MASK_NXP_PERIODIC; // Acknowledge + } + + if (int_status & EHCI_INT_MASK_USB) { + // TODO standard EHCI xfer complete + regs->status = EHCI_INT_MASK_USB; // Acknowledge } //------------- There is some removed async previously -------------// - if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC - { + // need to place after EHCI_INT_MASK_NXP_ASYNC + if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) { async_advance_isr(rhport); + regs->status = EHCI_INT_MASK_ASYNC_ADVANCE; // Acknowledge } } @@ -918,28 +957,30 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c } } -static void qtd_init(ehci_qtd_t* p_qtd, void const* buffer, uint16_t total_bytes) +static void qtd_init(ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes) { - tu_memclr(p_qtd, sizeof(ehci_qtd_t)); + tu_memclr(qtd, sizeof(ehci_qtd_t)); + qtd->used = 1; - p_qtd->used = 1; + qtd->next.terminate = 1; // init to null + qtd->alternate.terminate = 1; // not used, always set to terminated + qtd->active = 1; + qtd->err_count = 3; // TODO 3 consecutive errors tolerance + qtd->data_toggle = 0; + qtd->int_on_complete = 1; + qtd->total_bytes = total_bytes; + qtd->expected_bytes = total_bytes; - p_qtd->next.terminate = 1; // init to null - p_qtd->alternate.terminate = 1; // not used, always set to terminated - p_qtd->active = 1; - p_qtd->err_count = 3; // TODO 3 consecutive errors tolerance - p_qtd->data_toggle = 0; - p_qtd->total_bytes = total_bytes; - p_qtd->expected_bytes = total_bytes; - - p_qtd->buffer[0] = (uint32_t) buffer; + qtd->buffer[0] = (uint32_t) buffer; for(uint8_t i=1; i<5; i++) { - p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; + qtd->buffer[i] |= tu_align4k(qtd->buffer[i - 1] ) + 4096; } } //------------- List Managing Helper -------------// + +// insert at head static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) { new->address = current->address; diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 56befd306..e76a59401 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -165,6 +165,7 @@ typedef struct TU_ATTR_ALIGNED(32) uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set uint8_t reserved2[2]; + // TODO USBH will only queue 1 TD per QHD, thus we can remove the list ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list } ehci_qhd_t; -- cgit v1.3.1 From e4f4ad5bc3a24f619b9cf6c542aaa3ff8cb37ec4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 May 2023 10:21:11 +0700 Subject: use weak local for dcache function to skip if() --- src/portable/ehci/ehci.c | 65 +++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 9023e4b35..ac715aa60 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -164,6 +164,25 @@ static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes) static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); +TU_ATTR_WEAK void hcd_dcache_clean(void* addr, uint32_t data_size) { + (void) addr; + (void) data_size; +} + +// invalidate data cache: mark cache as invalid, next read will read from memory +// Required BOTH before and after an DMA RX transfer +TU_ATTR_WEAK void hcd_dcache_invalidate(void* addr, uint32_t data_size) { + (void) addr; + (void) data_size; +} + +// clean and invalidate data cache +// Required before an DMA transfer where memory is both read/write by DMA +TU_ATTR_WEAK void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { + (void) addr; + (void) data_size; +} + //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ @@ -342,9 +361,7 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) regs->periodic_list_base = (uint32_t) framelist; - if(hcd_dcache_clean) { - hcd_dcache_clean(&ehci_data, sizeof(ehci_data_t)); - } + hcd_dcache_clean(&ehci_data, sizeof(ehci_data_t)); //------------- TT Control (NXP only) -------------// regs->nxp_tt_control = 0; @@ -429,10 +446,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const // TODO might need to disable async/period list list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); - if(hcd_dcache_clean) { - hcd_dcache_clean(p_qhd, sizeof(ehci_qhd_t)); - hcd_dcache_clean(list_head, sizeof(ehci_link_t)); - } + hcd_dcache_clean(p_qhd, sizeof(ehci_qhd_t)); + hcd_dcache_clean(list_head, sizeof(ehci_link_t)); return true; } @@ -447,10 +462,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet qtd_init(td, setup_packet, 8); td->pid = EHCI_PID_SETUP; - if (hcd_dcache_clean && hcd_dcache_clean_invalidate) { - hcd_dcache_clean((void *) setup_packet, 8); - hcd_dcache_clean_invalidate(td, sizeof(ehci_qtd_t)); - } + hcd_dcache_clean((void *) setup_packet, 8); + hcd_dcache_clean_invalidate(td, sizeof(ehci_qtd_t)); // sw region qhd->p_qtd_list_head = td; @@ -459,9 +472,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet // attach TD qhd->qtd_overlay.next.address = (uint32_t) td; - if (hcd_dcache_clean_invalidate) { - hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); - } + hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); return true; } @@ -496,15 +507,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * qtd->pid = qhd->pid; } - if (hcd_dcache_clean && hcd_dcache_clean_invalidate) { - // IN transfer: invalidate buffer, OUT transfer: clean buffer - if (dir) { - hcd_dcache_invalidate(buffer, buflen); - }else { - hcd_dcache_clean(buffer, buflen); - } - hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t)); + // IN transfer: invalidate buffer, OUT transfer: clean buffer + if (dir) { + hcd_dcache_invalidate(buffer, buflen); + }else { + hcd_dcache_clean(buffer, buflen); } + hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t)); // Software: assign TD to QHD qhd->p_qtd_list_head = qtd; @@ -513,9 +522,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // attach TD to QHD start transferring qhd->qtd_overlay.next.address = (uint32_t) qtd; - if (hcd_dcache_clean_invalidate) { - hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); - } + hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); return true; } @@ -570,9 +577,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) { ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; - if (hcd_dcache_invalidate) { - hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); - } + hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); bool const is_ioc = (qtd->int_on_complete != 0); uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0); @@ -596,9 +601,7 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) ehci_qhd_t *p_qhd = async_head; do { - if (hcd_dcache_invalidate) { - hcd_dcache_invalidate(p_qhd, sizeof(ehci_qhd_t)); - } + hcd_dcache_invalidate(p_qhd, sizeof(ehci_qhd_t)); // halted or error is processed in error isr if ( !p_qhd->qtd_overlay.halted ) { -- cgit v1.3.1 From a0aea52a117246f246529459f9203ce36d2fcd81 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 May 2023 12:39:53 +0700 Subject: more cache, fix an similar issue with OHCI when removing an queue head --- src/portable/ehci/ehci.c | 50 ++++++++++++++++++++++++++---------------------- src/portable/ehci/ehci.h | 2 ++ 2 files changed, 29 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index ac715aa60..0b4202788 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -162,7 +162,7 @@ static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd); static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes); static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); -static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); +static inline ehci_link_t* list_next (ehci_link_t const *p_link); TU_ATTR_WEAK void hcd_dcache_clean(void* addr, uint32_t data_size) { (void) addr; @@ -237,24 +237,22 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed } -static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) -{ - for(ehci_link_t* prev = list_head; - !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head) && prev != NULL; - prev = list_next(prev) ) - { - // TODO check type for ISO iTD and siTD - // TODO Suppress cast-align warning - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); - #pragma GCC diagnostic pop - if ( qhd->dev_addr == dev_addr ) - { +static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr) { + ehci_link_t* prev = list_head; + + while (prev && !prev->terminate) { + ehci_qhd_t* qhd = (ehci_qhd_t*) (uintptr_t) list_next(prev); + + // done if loop back to head + if ( (uintptr_t) qhd == (uintptr_t) list_head) { + break; + } + + if ( qhd->dev_addr == dev_addr ) { // TODO deactivate all TD, wait for QHD to inactive before removal prev->address = qhd->next.address; - // EHCI 4.8.2 link the removed qhd to async head (which always reachable by Host Controller) + // EHCI 4.8.2 link the removed qhd's next to async head (which always reachable by Host Controller) qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1); if ( qhd->int_smask ) @@ -267,6 +265,11 @@ static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) // mark as removing, will completely re-usable when async advance isr occurs qhd->removing = 1; } + + hcd_dcache_clean(qhd, sizeof(ehci_qhd_t)); + hcd_dcache_clean(prev, sizeof(ehci_qhd_t)); + }else { + prev = list_next(prev); } } } @@ -275,15 +278,16 @@ static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // skip dev0 - if (dev_addr == 0) return; + if (dev_addr == 0) { + return; + } // Remove from async list - list_remove_qhd_by_addr( (ehci_link_t*) qhd_async_head(rhport), dev_addr ); + list_remove_qhd_by_daddr((ehci_link_t *) qhd_async_head(rhport), dev_addr); // Remove from all interval period list - for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) - { - list_remove_qhd_by_addr( (ehci_link_t*) &ehci_data.period_head_arr[i], dev_addr); + for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) { + list_remove_qhd_by_daddr((ehci_link_t *) &ehci_data.period_head_arr[i], dev_addr); } // Async doorbell (EHCI 4.8.2 for operational details) @@ -990,9 +994,9 @@ static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t n current->address = ((uint32_t) new) | (new_type << 1); } -static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) +static inline ehci_link_t* list_next(ehci_link_t const *p_link) { - return (ehci_link_t*) tu_align32(p_link_pointer->address); + return (ehci_link_t*) tu_align32(p_link->address); } #endif diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index e76a59401..d7d37d627 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -81,6 +81,8 @@ typedef union { }; }ehci_link_t; +TU_VERIFY_STATIC( sizeof(ehci_link_t) == 4, "size is not correct" ); + /// Queue Element Transfer Descriptor /// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with TU_ATTR_ALIGNED(32) typedef struct -- cgit v1.3.1 From 49e2aabc819f761284dd490fd4f1c5d4ad5c3695 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 May 2023 13:45:38 +0700 Subject: EHCI more improvement - more dcache clean/invalidate - extract init_periodic_list() - improve isr list handling --- src/host/hcd.h | 2 +- src/portable/ehci/ehci.c | 196 +++++++++++++++++++++++++---------------------- 2 files changed, 105 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/host/hcd.h b/src/host/hcd.h index c6fde2adc..5a3b0a087 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -175,7 +175,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); // clear stall, data toggle is also reset to DATA0 -bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); +bool hcd_edpt_clear_stall(uint8_t daddr, uint8_t ep_addr); //--------------------------------------------------------------------+ // USBH implemented API diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 0b4202788..0b45d7b93 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -294,6 +294,40 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) ehci_data.regs->command_bm.async_adv_doorbell = 1; } +static void init_periodic_list(uint8_t rhport) { + // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only + for ( uint32_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++ ) { + ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero + ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive + } + + ehci_link_t * const framelist = ehci_data.period_framelist; + ehci_link_t * const period_1ms = get_period_head(rhport, 1u); + + // all links --> period_head_arr[0] (1ms) + // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms) + // 1, 5 --> period_head_arr[2] (4ms) + // 3 --> period_head_arr[3] (8ms) + + // TODO EHCI_FRAMELIST_SIZE with other size than 8 + for (uint32_t i = 0; i < FRAMELIST_SIZE; i++) { + framelist[i].address = (uint32_t) period_1ms; + framelist[i].type = EHCI_QTYPE_QHD; + } + + for (uint32_t i = 0; i < FRAMELIST_SIZE; i += 2) { + list_insert(framelist + i, get_period_head(rhport, 2u), EHCI_QTYPE_QHD); + } + + for (uint32_t i = 1; i < FRAMELIST_SIZE; i += 4) { + list_insert(framelist + i, get_period_head(rhport, 4u), EHCI_QTYPE_QHD); + } + + list_insert(framelist + 3, get_period_head(rhport, 8u), EHCI_QTYPE_QHD); + + period_1ms->terminate = 1; +} + bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) { tu_memclr(&ehci_data, sizeof(ehci_data_t)); @@ -332,38 +366,8 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) regs->async_list_addr = (uint32_t) async_head; //------------- Periodic List -------------// - // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only - for ( uint32_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++ ) - { - ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero - ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive - } - - ehci_link_t * const framelist = ehci_data.period_framelist; - ehci_link_t * const period_1ms = get_period_head(rhport, 1u); - - // all links --> period_head_arr[0] (1ms) - // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms) - // 1, 5 --> period_head_arr[2] (4ms) - // 3 --> period_head_arr[3] (8ms) - - // TODO EHCI_FRAMELIST_SIZE with other size than 8 - for (uint32_t i = 0; i < FRAMELIST_SIZE; i++) { - framelist[i].address = (uint32_t) period_1ms; - framelist[i].type = EHCI_QTYPE_QHD; - } - - for (uint32_t i = 0; i < FRAMELIST_SIZE; i += 2) { - list_insert(framelist + i, get_period_head(rhport, 2u), EHCI_QTYPE_QHD); - } - - for (uint32_t i = 1; i < FRAMELIST_SIZE; i += 4) { - list_insert(framelist + i, get_period_head(rhport, 4u), EHCI_QTYPE_QHD); - } - list_insert(framelist + 3, get_period_head(rhport, 8u), EHCI_QTYPE_QHD); - period_1ms->terminate = 1; - - regs->periodic_list_base = (uint32_t) framelist; + init_periodic_list(rhport); + regs->periodic_list_base = (uint32_t) ehci_data.period_framelist; hcd_dcache_clean(&ehci_data, sizeof(ehci_data_t)); @@ -491,8 +495,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * ehci_qhd_t* qhd; ehci_qtd_t* qtd; - if ( epnum == 0 ) - { + if (epnum == 0) { qhd = qhd_control(dev_addr); qtd = qtd_control(dev_addr); @@ -501,8 +504,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // first first data toggle is always 1 (data & setup stage) qtd->data_toggle = 1; qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT; - }else - { + } else { qhd = qhd_get_from_addr(dev_addr, ep_addr); qtd = qtd_find_free(); TU_ASSERT(qtd); @@ -531,10 +533,11 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) +bool hcd_edpt_clear_stall(uint8_t daddr, uint8_t ep_addr) { - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - p_qhd->qtd_overlay.halted = 0; + ehci_qhd_t *qhd = qhd_get_from_addr(daddr, ep_addr); + qhd->qtd_overlay.halted = 0; + hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); // TODO reset data toggle ? return true; } @@ -546,22 +549,22 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) // async_advance is handshake between usb stack & ehci controller. // This isr mean it is safe to modify previously removed queue head from async list. // In tinyusb, queue head is only removed when device is unplugged. -static void async_advance_isr(uint8_t rhport) +TU_ATTR_ALWAYS_INLINE static inline +void async_advance_isr(uint8_t rhport) { (void) rhport; - ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; - for(uint32_t i = 0; i < QHD_MAX; i++) - { - if ( qhd_pool[i].removing ) - { + ehci_qhd_t *qhd_pool = ehci_data.qhd_pool; + for (uint32_t i = 0; i < QHD_MAX; i++) { + if (qhd_pool[i].removing) { qhd_pool[i].removing = 0; - qhd_pool[i].used = 0; + qhd_pool[i].used = 0; } } } -static void port_connect_status_change_isr(uint8_t rhport) +TU_ATTR_ALWAYS_INLINE static inline +void port_connect_status_change_isr(uint8_t rhport) { // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device if (ehci_data.regs->portsc_bm.current_connect_status) @@ -574,13 +577,13 @@ static void port_connect_status_change_isr(uint8_t rhport) } } -static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) +TU_ATTR_ALWAYS_INLINE static inline +void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) { // free all TDs from the head td to the first active TD while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) { ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; - hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); bool const is_ioc = (qtd->int_on_complete != 0); @@ -600,7 +603,8 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) } } -static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) +TU_ATTR_ALWAYS_INLINE static inline +void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) { ehci_qhd_t *p_qhd = async_head; do @@ -611,46 +615,55 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) if ( !p_qhd->qtd_overlay.halted ) { qhd_xfer_complete_isr(p_qhd); } + p_qhd = qhd_next(p_qhd); }while(p_qhd != async_head); // async list traversal, stop if loop around } -static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms) +TU_ATTR_ALWAYS_INLINE static inline +void period_list_xfer_complete_isr(uint8_t rhport, uint32_t interval_ms) { - uint16_t max_loop = 0; - uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u); - ehci_link_t next_item = * get_period_head(hostid, interval_ms); + uint32_t const period_1ms_addr = (uint32_t) get_period_head(rhport, 1u); + ehci_link_t next_link = * get_period_head(rhport, interval_ms); - // TODO abstract max loop guard for period - while( !next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && - max_loop < (QHD_MAX + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) - { - switch ( next_item.type ) - { - case EHCI_QTYPE_QHD: - { - ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); - if ( !p_qhd_int->qtd_overlay.halted ) - { - qhd_xfer_complete_isr(p_qhd_int); + while (!next_link.terminate) { + if (interval_ms > 1 && period_1ms_addr == tu_align32(next_link.address)) { + // 1ms period list is end of list for all larger interval + break; + } + + uintptr_t const entry_addr = tu_align32(next_link.address); + + switch (next_link.type) { + case EHCI_QTYPE_QHD: { + ehci_qhd_t *qhd = (ehci_qhd_t *) entry_addr; + hcd_dcache_invalidate(qhd, sizeof(ehci_qhd_t)); + + if (!qhd->qtd_overlay.halted) { + qhd_xfer_complete_isr(qhd); } } - break; + break; + + case EHCI_QTYPE_ITD: + // TODO support hs ISO + break; - case EHCI_QTYPE_ITD: // TODO support hs/fs ISO case EHCI_QTYPE_SITD: - case EHCI_QTYPE_FSTN: + // TODO support split ISO + break; - default: break; + case EHCI_QTYPE_FSTN: + default: + break; } - next_item = *list_next(&next_item); - max_loop++; + next_link = *list_next(&next_link); } } -static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) +TU_ATTR_ALWAYS_INLINE static inline +void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) { volatile ehci_qtd_t *qtd_overlay = &p_qhd->qtd_overlay; @@ -666,22 +679,22 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) xfer_result = XFER_RESULT_STALLED; } - p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; - // if (XFER_RESULT_FAILED == xfer_result ) { // TU_LOG1(" QHD xfer err count: %d\n", qtd_overlay->err_count); // TU_BREAKPOINT(); // TODO skip unplugged device // while(1){} // } - // No TD yet, it is probably the probably an signal noise ? - TU_ASSERT(p_qhd->p_qtd_list_head, ); + ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; + TU_ASSERT(qtd, ); // No TD yet, probably a race condition or cache issue !? - p_qhd->p_qtd_list_head->used = 0; // free QTD + hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); + p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes; + + qtd->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); - if ( 0 == p_qhd->ep_number ) - { + if ( 0 == p_qhd->ep_number ) { // control cannot be halted --> clear all qtd list p_qhd->p_qtd_list_head = NULL; p_qhd->p_qtd_list_tail = NULL; @@ -702,13 +715,15 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } } -static void xfer_error_isr(uint8_t hostid) +TU_ATTR_ALWAYS_INLINE static inline +void xfer_error_isr(uint8_t hostid) { //------------- async list -------------// ehci_qhd_t * const async_head = qhd_async_head(hostid); ehci_qhd_t *p_qhd = async_head; do { + hcd_dcache_invalidate(p_qhd, sizeof(ehci_qhd_t)); qhd_xfer_error_isr( p_qhd ); p_qhd = qhd_next(p_qhd); }while(p_qhd != async_head); // async list traversal, stop if loop around @@ -728,6 +743,8 @@ static void xfer_error_isr(uint8_t hostid) case EHCI_QTYPE_QHD: { ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); + hcd_dcache_invalidate(p_qhd_int, sizeof(ehci_qhd_t)); + qhd_xfer_error_isr(p_qhd_int); } break; @@ -757,20 +774,17 @@ void hcd_int_handler(uint8_t rhport) return; } - if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) - { + if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) { ehci_data.uframe_number += (FRAMELIST_SIZE << 3); regs->status = EHCI_INT_MASK_FRAMELIST_ROLLOVER; // Acknowledge } - if (int_status & EHCI_INT_MASK_PORT_CHANGE) - { + if (int_status & EHCI_INT_MASK_PORT_CHANGE) { // Including: Force port resume, over-current change, enable/disable change and connect status change. uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_W1C; print_portsc(regs); - if (regs->portsc_bm.connect_status_change) - { + if (regs->portsc_bm.connect_status_change) { port_connect_status_change_isr(rhport); } @@ -778,15 +792,13 @@ void hcd_int_handler(uint8_t rhport) regs->status = EHCI_INT_MASK_PORT_CHANGE; // Acknowledge } - if (int_status & EHCI_INT_MASK_ERROR) - { + if (int_status & EHCI_INT_MASK_ERROR) { xfer_error_isr(rhport); regs->status = EHCI_INT_MASK_ERROR; // Acknowledge } //------------- some QTD/SITD/ITD with IOC set is completed -------------// - if (int_status & EHCI_INT_MASK_NXP_ASYNC) - { + if (int_status & EHCI_INT_MASK_NXP_ASYNC) { async_list_xfer_complete_isr(qhd_async_head(rhport)); regs->status = EHCI_INT_MASK_NXP_ASYNC; // Acknowledge } -- cgit v1.3.1 From 27acaa013bd8af8ac29e966d7dc145b33dd6bc73 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 May 2023 15:44:08 +0700 Subject: refactor ehci, since usbh only queue 1 TD per queue head --- src/portable/ehci/ehci.c | 113 ++++++++++++++--------------------------------- src/portable/ehci/ehci.h | 16 ++----- 2 files changed, 37 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 0b45d7b93..a08731667 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -156,9 +156,6 @@ static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); static inline ehci_qtd_t* qtd_find_free (void); -static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd); -static inline void qtd_insert_to_qhd (ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new); -static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd); static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes); static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); @@ -473,11 +470,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet hcd_dcache_clean((void *) setup_packet, 8); hcd_dcache_clean_invalidate(td, sizeof(ehci_qtd_t)); - // sw region - qhd->p_qtd_list_head = td; - qhd->p_qtd_list_tail = td; - // attach TD + qhd->p_attached_qtd = td; // software management qhd->qtd_overlay.next.address = (uint32_t) td; hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); @@ -501,7 +495,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * qtd_init(qtd, buffer, buflen); - // first first data toggle is always 1 (data & setup stage) + // first data toggle is always 1 (data & setup stage) qtd->data_toggle = 1; qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT; } else { @@ -521,11 +515,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * } hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t)); - // Software: assign TD to QHD - qhd->p_qtd_list_head = qtd; - qhd->p_qtd_list_tail = qtd; - // attach TD to QHD start transferring + qhd->p_attached_qtd = qtd; // software management qhd->qtd_overlay.next.address = (uint32_t) qtd; hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); @@ -580,27 +571,25 @@ void port_connect_status_change_isr(uint8_t rhport) TU_ATTR_ALWAYS_INLINE static inline void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) { - // free all TDs from the head td to the first active TD - while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) - { - ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; - hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); + // examine TD attached to queue head + ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd; + if (qtd == NULL) return; // no TD attached + hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); - bool const is_ioc = (qtd->int_on_complete != 0); - uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0); + // TD is still active, no need to process + if (qtd->active) { + return; + } - p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes; + uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes; + uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0); - // TD need to be freed and removed from qhd, before invoking callback - qtd->used = 0; // free QTD - qtd_remove_1st_from_qhd(p_qhd); + // remove and free TD before invoking callback + p_qhd->p_attached_qtd = NULL; + qtd->used = 0; // free QTD - if (is_ioc) - { - hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); - p_qhd->total_xferred_bytes = 0; - } - } + // IOC is always set + hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, XFER_RESULT_SUCCESS, true); } TU_ATTR_ALWAYS_INLINE static inline @@ -685,20 +674,17 @@ void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) // while(1){} // } - ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; + ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd; TU_ASSERT(qtd, ); // No TD yet, probably a race condition or cache issue !? hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); - p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes; + uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes; + p_qhd->p_attached_qtd = NULL; qtd->used = 0; // free QTD - qtd_remove_1st_from_qhd(p_qhd); if ( 0 == p_qhd->ep_number ) { - // control cannot be halted --> clear all qtd list - p_qhd->p_qtd_list_head = NULL; - p_qhd->p_qtd_list_tail = NULL; - + // control cannot be halted p_qhd->qtd_overlay.next.terminate = 1; p_qhd->qtd_overlay.alternate.terminate = 1; p_qhd->qtd_overlay.halted = 0; @@ -707,19 +693,17 @@ void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) p_setup->used = 0; } - // call USBH callback + // notify usbh uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0); - hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, xfer_result, true); - - p_qhd->total_xferred_bytes = 0; + hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, xfer_result, true); } } TU_ATTR_ALWAYS_INLINE static inline -void xfer_error_isr(uint8_t hostid) +void xfer_error_isr(uint8_t rhport) { //------------- async list -------------// - ehci_qhd_t * const async_head = qhd_async_head(hostid); + ehci_qhd_t * const async_head = qhd_async_head(rhport); ehci_qhd_t *p_qhd = async_head; do { @@ -729,10 +713,10 @@ void xfer_error_isr(uint8_t hostid) }while(p_qhd != async_head); // async list traversal, stop if loop around //------------- TODO refractor period list -------------// - uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u); + uint32_t const period_1ms_addr = (uint32_t) get_period_head(rhport, 1u); for (uint32_t interval_ms=1; interval_ms <= FRAMELIST_SIZE; interval_ms *= 2) { - ehci_link_t next_item = * get_period_head(hostid, interval_ms); + ehci_link_t next_item = * get_period_head(rhport, interval_ms); // TODO abstract max loop guard for period while( !next_item.terminate && @@ -873,34 +857,6 @@ static inline ehci_qtd_t* qtd_find_free(void) return NULL; } -static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) -{ - return (ehci_qtd_t*) tu_align32(p_qtd->next.address); -} - -static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) -{ - if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL - { - p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL; - }else - { - p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head ); - } -} - -static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) -{ - if (p_qhd->p_qtd_list_head == NULL) // empty list - { - p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new; - }else - { - p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new; - p_qhd->p_qtd_list_tail = p_qtd_new; - } -} - static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { // address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise) @@ -955,15 +911,14 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->int_smask = p_qhd->fl_int_cmask = 0; } - p_qhd->fl_hub_addr = devtree_info.hub_addr; - p_qhd->fl_hub_port = devtree_info.hub_port; - p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet + p_qhd->fl_hub_addr = devtree_info.hub_addr; + p_qhd->fl_hub_port = devtree_info.hub_port; + p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet //------------- HCD Management Data -------------// - p_qhd->used = 1; - p_qhd->removing = 0; - p_qhd->p_qtd_list_head = NULL; - p_qhd->p_qtd_list_tail = NULL; + p_qhd->used = 1; + p_qhd->removing = 0; + p_qhd->p_attached_qtd = NULL; p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint //------------- active, but no TD list -------------// diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index d7d37d627..b525131c6 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -164,12 +164,10 @@ typedef struct TU_ATTR_ALIGNED(32) uint8_t pid; uint8_t interval_ms; // polling interval in frames (or millisecond) - uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set - uint8_t reserved2[2]; + uint8_t TU_RESERVED[8]; - // TODO USBH will only queue 1 TD per QHD, thus we can remove the list - ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list - ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list + // usbh will only queue 1 TD per QHD + ehci_qtd_t * volatile p_attached_qtd; } ehci_qhd_t; TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); @@ -248,14 +246,6 @@ typedef struct TU_ATTR_ALIGNED(32) /// Word 4-5: Buffer Pointer List uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count -// union{ -// uint32_t BufferPointer1; -// struct { -// volatile uint32_t TCount : 3; -// volatile uint32_t TPosition : 2; -// }; -// }; - /*---------- Word 6 ----------*/ ehci_link_t back; -- cgit v1.3.1 From ec4bd39a9209f37b02edac2f6a1ea2ef27f6b785 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 May 2023 16:41:06 +0700 Subject: refactor ehci: add attached_buffer for dcache invalidate for IN transfer --- src/portable/ehci/ehci.c | 116 +++++++++++++++++++++++++++-------------------- src/portable/ehci/ehci.h | 8 ++-- 2 files changed, 72 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index a08731667..cc825d549 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -154,6 +154,7 @@ static inline ehci_qhd_t* qhd_next (ehci_qhd_t const * p_qhd); static inline ehci_qhd_t* qhd_find_free (void); static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd); static inline ehci_qtd_t* qtd_find_free (void); static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes); @@ -468,13 +469,9 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet td->pid = EHCI_PID_SETUP; hcd_dcache_clean((void *) setup_packet, 8); - hcd_dcache_clean_invalidate(td, sizeof(ehci_qtd_t)); - // attach TD - qhd->p_attached_qtd = td; // software management - qhd->qtd_overlay.next.address = (uint32_t) td; - - hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); + // attach TD to QHD -> start transferring + qhd_attach_qtd(qhd, td); return true; } @@ -513,13 +510,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * }else { hcd_dcache_clean(buffer, buflen); } - hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t)); - // attach TD to QHD start transferring - qhd->p_attached_qtd = qtd; // software management - qhd->qtd_overlay.next.address = (uint32_t) qtd; - - hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); + // attach TD to QHD -> start transferring + qhd_attach_qtd(qhd, qtd); return true; } @@ -569,10 +562,9 @@ void port_connect_status_change_isr(uint8_t rhport) } TU_ATTR_ALWAYS_INLINE static inline -void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) -{ +void qhd_xfer_complete_isr(ehci_qhd_t * qhd) { // examine TD attached to queue head - ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd; + ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) qhd->attached_qtd; if (qtd == NULL) return; // no TD attached hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); @@ -581,15 +573,22 @@ void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) return; } + uint8_t dir = (qtd->pid == EHCI_PID_IN) ? 1 : 0; uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes; - uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0); + + // invalidate dcache if IN transfer + if (dir == 1 && qhd->attached_buffer != 0) { + hcd_dcache_invalidate((void*) qhd->attached_buffer, xferred_bytes); + } // remove and free TD before invoking callback - p_qhd->p_attached_qtd = NULL; + qhd->attached_qtd = NULL; + qhd->attached_buffer = 0; qtd->used = 0; // free QTD - // IOC is always set - hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, XFER_RESULT_SUCCESS, true); + // notify usbh + uint8_t const ep_addr = tu_edpt_addr(qhd->ep_number, dir); + hcd_event_xfer_complete(qhd->dev_addr, ep_addr, xferred_bytes, XFER_RESULT_SUCCESS, true); } TU_ATTR_ALWAYS_INLINE static inline @@ -651,10 +650,11 @@ void period_list_xfer_complete_isr(uint8_t rhport, uint32_t interval_ms) } } +// TODO merge with qhd_xfer_complete_isr() TU_ATTR_ALWAYS_INLINE static inline -void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) +void qhd_xfer_error_isr(ehci_qhd_t * qhd) { - volatile ehci_qtd_t *qtd_overlay = &p_qhd->qtd_overlay; + volatile ehci_qtd_t *qtd_overlay = &qhd->qtd_overlay; // TD has error if (qtd_overlay->halted) { @@ -674,28 +674,37 @@ void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) // while(1){} // } - ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd; + ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) qhd->attached_qtd; TU_ASSERT(qtd, ); // No TD yet, probably a race condition or cache issue !? hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); + + uint8_t dir = (qtd->pid == EHCI_PID_IN) ? 1 : 0; uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes; - p_qhd->p_attached_qtd = NULL; + // invalidate dcache if IN transfer + if (dir == 1 && qhd->attached_buffer != 0) { + hcd_dcache_invalidate((void*) qhd->attached_buffer, xferred_bytes); + } + + // remove and free TD before invoking callback + qhd->attached_qtd = NULL; + qhd->attached_buffer = 0; qtd->used = 0; // free QTD - if ( 0 == p_qhd->ep_number ) { + if (0 == qhd->ep_number ) { // control cannot be halted - p_qhd->qtd_overlay.next.terminate = 1; - p_qhd->qtd_overlay.alternate.terminate = 1; - p_qhd->qtd_overlay.halted = 0; + qhd->qtd_overlay.next.terminate = 1; + qhd->qtd_overlay.alternate.terminate = 1; + qhd->qtd_overlay.halted = 0; - ehci_qtd_t *p_setup = qtd_control(p_qhd->dev_addr); + ehci_qtd_t *p_setup = qtd_control(qhd->dev_addr); p_setup->used = 0; } // notify usbh - uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0); - hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, xfer_result, true); + uint8_t const ep_addr = tu_edpt_addr(qhd->ep_number, dir); + hcd_event_xfer_complete(qhd->dev_addr, ep_addr, xferred_bytes, xfer_result, true); } } @@ -846,22 +855,10 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) return NULL; } -//------------- TD helper -------------// -static inline ehci_qtd_t* qtd_find_free(void) -{ - for (uint32_t i=0; i cannot be cleared (ehci halted otherwise) - if (dev_addr != 0) - { + if (dev_addr != 0) { tu_memclr(p_qhd, sizeof(ehci_qhd_t)); } @@ -911,26 +908,47 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->int_smask = p_qhd->fl_int_cmask = 0; } - p_qhd->fl_hub_addr = devtree_info.hub_addr; - p_qhd->fl_hub_port = devtree_info.hub_port; - p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet + p_qhd->fl_hub_addr = devtree_info.hub_addr; + p_qhd->fl_hub_port = devtree_info.hub_port; + p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet //------------- HCD Management Data -------------// - p_qhd->used = 1; - p_qhd->removing = 0; - p_qhd->p_attached_qtd = NULL; + p_qhd->used = 1; + p_qhd->removing = 0; + p_qhd->attached_qtd = NULL; p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint //------------- active, but no TD list -------------// p_qhd->qtd_overlay.halted = 0; p_qhd->qtd_overlay.next.terminate = 1; p_qhd->qtd_overlay.alternate.terminate = 1; + if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) { p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11 } } +static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd) { + qhd->attached_qtd = qtd; + qhd->attached_buffer = qtd->buffer[0]; + + // clean and invalidate cache before physically write + hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t)); + + qhd->qtd_overlay.next.address = (uint32_t) qtd; + hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t)); +} + + +//------------- TD helper -------------// +static inline ehci_qtd_t *qtd_find_free(void) { + for (uint32_t i = 0; i < QTD_MAX; i++) { + if (!ehci_data.qtd_pool[i].used) return &ehci_data.qtd_pool[i]; + } + return NULL; +} + static void qtd_init(ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes) { tu_memclr(qtd, sizeof(ehci_qtd_t)); diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index b525131c6..8338fb419 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -164,10 +164,12 @@ typedef struct TU_ATTR_ALIGNED(32) uint8_t pid; uint8_t interval_ms; // polling interval in frames (or millisecond) - uint8_t TU_RESERVED[8]; + uint8_t TU_RESERVED[4]; - // usbh will only queue 1 TD per QHD - ehci_qtd_t * volatile p_attached_qtd; + // Attached TD management, note usbh will only queue 1 TD per QHD. + // buffer for dcache invalidate since td's buffer is modified by HC and finding initial buffer address is not trivial + uint32_t attached_buffer; + ehci_qtd_t * volatile attached_qtd; } ehci_qhd_t; TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); -- cgit v1.3.1 From f26a93908ef9dcde6818c9b271727ed6c77e87d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 May 2023 10:56:52 +0700 Subject: only clean/invalidate dcache on imxrt if memory is not in DTCM --- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index ecb1a621c..ab6a42e11 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -42,17 +42,28 @@ #if CFG_TUSB_MCU == OPT_MCU_MIMXRT #include "ci_hs_imxrt.h" + // check if memory is cacheable i.e not in DTCM + TU_ATTR_ALWAYS_INLINE static inline bool is_cache_mem(uint32_t addr) { + return !(0x20000000 <= addr && addr < 0x20100000); + } + void hcd_dcache_clean(void* addr, uint32_t data_size) { - SCB_CleanDCache_by_Addr((uint32_t*) addr, (int32_t) data_size); + if (is_cache_mem((uint32_t) addr)) { + SCB_CleanDCache_by_Addr((uint32_t *) addr, (int32_t) data_size); + } } void hcd_dcache_invalidate(void* addr, uint32_t data_size) { - SCB_InvalidateDCache_by_Addr(addr, (int32_t) data_size); + if (is_cache_mem((uint32_t) addr)) { + SCB_InvalidateDCache_by_Addr(addr, (int32_t) data_size); + } } void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { + if (is_cache_mem((uint32_t) addr)) { SCB_CleanInvalidateDCache_by_Addr(addr, (int32_t) data_size); } +} #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) #include "ci_hs_lpc18_43.h" -- cgit v1.3.1 From 5dae5e12928ba789cd7e248edd9fa91376902925 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 May 2023 13:32:49 +0700 Subject: ehci fix dcache clean when control endpoint failed --- hw/bsp/imxrt/family.cmake | 6 +++++- src/host/usbh.c | 3 ++- src/portable/ehci/ehci.c | 10 ++++------ src/tusb.c | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 4628abc34..a475b4721 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -57,12 +57,16 @@ if (NOT TARGET ${BOARD_TARGET}) ) update_board(${BOARD_TARGET}) + if (NOT DEFINED LD_FILE_${TOOLCHAIN}) + set(LD_FILE_gcc ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx_flexspi_nor.ld) + endif () + if (TOOLCHAIN STREQUAL "gcc") target_sources(${BOARD_TARGET} PUBLIC ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S ) target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx_flexspi_nor.ld" + "LINKER:--script=${LD_FILE_gcc}" "LINKER:-Map=$>,$,$>${CMAKE_EXECUTABLE_SUFFIX}.map" # nanolib --specs=nosys.specs diff --git a/src/host/usbh.c b/src/host/usbh.c index c56ff9459..7b265c742 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -440,7 +440,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG_USBH("on EP %02X with %u bytes %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, + TU_LOG_USBH("on EP %02X with %u bytes: %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]); if (event.dev_addr == 0) @@ -1255,6 +1255,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { failed_count++; osal_task_delay(ATTEMPT_DELAY_MS); // delay a bit + TU_LOG1("Enumeration attempt %u\r\n", failed_count); TU_ASSERT(tuh_control_xfer(xfer), ); }else { diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index cc825d549..10e2db7b5 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -577,7 +577,7 @@ void qhd_xfer_complete_isr(ehci_qhd_t * qhd) { uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes; // invalidate dcache if IN transfer - if (dir == 1 && qhd->attached_buffer != 0) { + if (dir == 1 && qhd->attached_buffer != 0 && xferred_bytes > 0) { hcd_dcache_invalidate((void*) qhd->attached_buffer, xferred_bytes); } @@ -660,7 +660,7 @@ void qhd_xfer_error_isr(ehci_qhd_t * qhd) if (qtd_overlay->halted) { xfer_result_t xfer_result; - if (qtd_overlay->err_count == 0 || qtd_overlay->buffer_err || qtd_overlay->babble_err || qtd_overlay->xact_err) { + if (qtd_overlay->xact_err || qtd_overlay->err_count == 0 || qtd_overlay->buffer_err || qtd_overlay->babble_err) { // Error count = 0 often occurs when device disconnected, or other bus-related error xfer_result = XFER_RESULT_FAILED; }else { @@ -671,7 +671,6 @@ void qhd_xfer_error_isr(ehci_qhd_t * qhd) // if (XFER_RESULT_FAILED == xfer_result ) { // TU_LOG1(" QHD xfer err count: %d\n", qtd_overlay->err_count); // TU_BREAKPOINT(); // TODO skip unplugged device -// while(1){} // } ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) qhd->attached_qtd; @@ -683,7 +682,7 @@ void qhd_xfer_error_isr(ehci_qhd_t * qhd) uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes; // invalidate dcache if IN transfer - if (dir == 1 && qhd->attached_buffer != 0) { + if (dir == 1 && qhd->attached_buffer != 0 && xferred_bytes > 0) { hcd_dcache_invalidate((void*) qhd->attached_buffer, xferred_bytes); } @@ -698,8 +697,7 @@ void qhd_xfer_error_isr(ehci_qhd_t * qhd) qhd->qtd_overlay.alternate.terminate = 1; qhd->qtd_overlay.halted = 0; - ehci_qtd_t *p_setup = qtd_control(qhd->dev_addr); - p_setup->used = 0; + hcd_dcache_clean(qhd, sizeof(ehci_qhd_t)); } // notify usbh diff --git a/src/tusb.c b/src/tusb.c index 7327db685..465b608b0 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -440,7 +440,7 @@ char const* const tu_str_std_request[] = }; char const* const tu_str_xfer_result[] = { - "OK", "Failed", "Stalled", "Timeout" + "OK", "FAILED", "STALLED", "TIMEOUT" }; #endif -- cgit v1.3.1 From 7211dd18b46affdf027522e34ff3aa3b5d8d5df5 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 May 2023 13:42:26 +0700 Subject: more dcache fix --- src/portable/ehci/ehci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 10e2db7b5..852e7f4fe 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -273,19 +273,19 @@ static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr) { } // Close all opened endpoint belong to this device -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +void hcd_device_close(uint8_t rhport, uint8_t daddr) { // skip dev0 - if (dev_addr == 0) { + if (daddr == 0) { return; } // Remove from async list - list_remove_qhd_by_daddr((ehci_link_t *) qhd_async_head(rhport), dev_addr); + list_remove_qhd_by_daddr((ehci_link_t *) qhd_async_head(rhport), daddr); // Remove from all interval period list for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) { - list_remove_qhd_by_daddr((ehci_link_t *) &ehci_data.period_head_arr[i], dev_addr); + list_remove_qhd_by_daddr((ehci_link_t *) &ehci_data.period_head_arr[i], daddr); } // Async doorbell (EHCI 4.8.2 for operational details) @@ -453,7 +453,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); hcd_dcache_clean(p_qhd, sizeof(ehci_qhd_t)); - hcd_dcache_clean(list_head, sizeof(ehci_link_t)); + hcd_dcache_clean(list_head, sizeof(ehci_qhd_t)); return true; } -- cgit v1.3.1 From 1ef820ecfe569e181b8f20cb936f632e51d8257e Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Tue, 23 May 2023 21:45:00 +0700 Subject: Enhance chipidea (#2075) * update chipidea dcd, remove manual ep_count and use DCCPARAMS to get number of endpoint instead * add dcd dcache for chipidea * add cmake for lpc18 * add makefile build for mcx * use fork of mcu sdk * fix ci build with nrf * flash rp2040 with openocd --- .github/workflows/build_arm.yml | 3 +- .github/workflows/cmake_arm.yml | 1 + .idea/cmake.xml | 7 +- .idea/runConfigurations/rt1010_jlink.xml | 10 + .idea/runConfigurations/rt1010_nxplink.xml | 10 - .idea/runConfigurations/rt1060_nxplink.xml | 10 - .pre-commit-config.yaml | 16 +- examples/device/CMakeLists.txt | 2 +- hw/bsp/board_mcu.h | 2 +- hw/bsp/family_support.cmake | 7 + hw/bsp/imxrt/family.cmake | 11 +- hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake | 11 + hw/bsp/lpc18/boards/mcb1800/board.cmake | 11 + hw/bsp/lpc18/family.cmake | 155 +++++++++++ hw/bsp/lpc55/family.cmake | 6 +- hw/bsp/mcx/FreeRTOSConfig/FreeRTOSConfig.h | 166 ++++++++++++ hw/bsp/mcx/boards/mcxn947brk/board.cmake | 18 ++ hw/bsp/mcx/boards/mcxn947brk/board.h | 66 +++++ hw/bsp/mcx/boards/mcxn947brk/board.mk | 11 + hw/bsp/mcx/boards/mcxn947brk/clock_config.c | 338 ++++++++++++++++++++++++ hw/bsp/mcx/boards/mcxn947brk/clock_config.h | 177 +++++++++++++ hw/bsp/mcx/boards/mcxn947brk/pin_mux.c | 141 ++++++++++ hw/bsp/mcx/boards/mcxn947brk/pin_mux.h | 51 ++++ hw/bsp/mcx/family.c | 262 ++++++++++++++++++ hw/bsp/mcx/family.cmake | 179 +++++++++++++ hw/bsp/mcx/family.mk | 48 ++++ hw/bsp/nrf/family.cmake | 11 +- src/common/tusb_mcu.h | 26 +- src/device/dcd.h | 16 ++ src/portable/chipidea/ci_hs/ci_hs_imxrt.h | 32 ++- src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h | 6 +- src/portable/chipidea/ci_hs/ci_hs_mcx.h | 52 ++++ src/portable/chipidea/ci_hs/ci_hs_type.h | 14 +- src/portable/chipidea/ci_hs/dcd_ci_hs.c | 96 +++++-- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 21 +- src/portable/ehci/ehci.c | 13 +- src/tusb_option.h | 6 +- tools/cmake/cpu/cortex-m3.cmake | 10 + tools/cmake/cpu/cortex-m33.cmake | 5 +- tools/cmake/toolchain/arm_gcc.cmake | 2 + tools/get_deps.py | 2 +- tools/make/cpu/cortex-m33.mk | 4 +- 42 files changed, 1914 insertions(+), 121 deletions(-) create mode 100644 .idea/runConfigurations/rt1010_jlink.xml delete mode 100644 .idea/runConfigurations/rt1010_nxplink.xml delete mode 100644 .idea/runConfigurations/rt1060_nxplink.xml create mode 100644 hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake create mode 100644 hw/bsp/lpc18/boards/mcb1800/board.cmake create mode 100644 hw/bsp/lpc18/family.cmake create mode 100644 hw/bsp/mcx/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/mcx/boards/mcxn947brk/board.cmake create mode 100644 hw/bsp/mcx/boards/mcxn947brk/board.h create mode 100644 hw/bsp/mcx/boards/mcxn947brk/board.mk create mode 100644 hw/bsp/mcx/boards/mcxn947brk/clock_config.c create mode 100644 hw/bsp/mcx/boards/mcxn947brk/clock_config.h create mode 100644 hw/bsp/mcx/boards/mcxn947brk/pin_mux.c create mode 100644 hw/bsp/mcx/boards/mcxn947brk/pin_mux.h create mode 100644 hw/bsp/mcx/family.c create mode 100644 hw/bsp/mcx/family.cmake create mode 100644 hw/bsp/mcx/family.mk create mode 100644 src/portable/chipidea/ci_hs/ci_hs_mcx.h create mode 100644 tools/cmake/cpu/cortex-m3.cmake (limited to 'src') diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index f0b01b43d..917c83d74 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -142,8 +142,7 @@ jobs: - name: Create flash.sh run: | - #echo > flash.sh 'cmdout=$(openocd -f "interface/picoprobe.cfg" -f "target/rp2040.cfg" -c "program $1 reset exit")' - echo > flash.sh 'pyocd flash -t rp2040 $1' + echo > flash.sh 'cmdout=$(openocd -f "interface/cmsis-dap.cfg" -f "target/rp2040.cfg" -c "adapter speed 5000" -c "program $1 reset exit")' echo >> flash.sh 'if (( $? )) ; then echo $cmdout ; fi' chmod +x flash.sh diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 844a03443..12173fb63 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -32,6 +32,7 @@ jobs: matrix: family: # Alphabetical order + - 'mcx' - 'imxrt' steps: - name: Setup Python diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 7dacd0003..a80ebed3c 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -2,8 +2,9 @@ - - + + + @@ -29,6 +30,8 @@ + + \ No newline at end of file diff --git a/.idea/runConfigurations/rt1010_jlink.xml b/.idea/runConfigurations/rt1010_jlink.xml new file mode 100644 index 000000000..70cfeea53 --- /dev/null +++ b/.idea/runConfigurations/rt1010_jlink.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/rt1010_nxplink.xml b/.idea/runConfigurations/rt1010_nxplink.xml deleted file mode 100644 index cf3bf842f..000000000 --- a/.idea/runConfigurations/rt1010_nxplink.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations/rt1060_nxplink.xml b/.idea/runConfigurations/rt1060_nxplink.xml deleted file mode 100644 index d3303bdb6..000000000 --- a/.idea/runConfigurations/rt1060_nxplink.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6fb98afb8..4071ec326 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,8 +8,16 @@ repos: hooks: - id: check-yaml - id: trailing-whitespace + exclude: | + (?x)^( + hw/bsp/mcx/sdk/ + ) - id: end-of-file-fixer - exclude: ^.idea/ + exclude: | + (?x)^( + .idea/| + hw/bsp/mcx/sdk/ + ) - id: forbid-submodules - repo: https://github.com/codespell-project/codespell @@ -17,7 +25,11 @@ repos: hooks: - id: codespell args: [-w] - exclude: ^lib/ + exclude: | + (?x)^( + lib/| + hw/bsp/mcx/sdk/ + ) - repo: local hooks: diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index 10a1f4c26..89cfceeeb 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -24,7 +24,7 @@ family_add_subdirectory(midi_test) family_add_subdirectory(msc_dual_lun) # FIXME temp skip net_lwip_webserver for imxrt for now -if (NOT ${FAMILY} STREQUAL "imxrt") +if (NOT ${FAMILY} STREQUAL "imxrt" AND NOT ${FAMILY} STREQUAL "mcx") family_add_subdirectory(net_lwip_webserver) endif() diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index cd195a19b..35210dbae 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -44,7 +44,7 @@ TU_CHECK_MCU(OPT_MCU_LPC40XX, OPT_MCU_LPC43XX) #include "chip.h" -#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX, OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX, OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX, OPT_MCU_MCXN9) #include "fsl_device_registers.h" #elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 442aba955..d2d675332 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -135,6 +135,13 @@ function(family_add_default_example_warnings TARGET) endif() endfunction() + +# add_custom_command(TARGET ${TARGET} POST_BUILD +# COMMAND ${CMAKE_OBJCOPY} -O ihex $ ${TARGET}.hex +# COMMAND ${CMAKE_OBJCOPY} -O binary $ ${TARGET}.bin +# COMMENT "Creating ${TARGET}.hex and ${TARGET}.bin" +# ) + # Add flash jlink target function(family_flash_jlink TARGET) if (NOT DEFINED JLINKEXE) diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 5261e5810..ade744aa5 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -1,8 +1,4 @@ -if (TARGET _imxrt_family_inclusion_marker) - return() -endif () - -add_library(_imxrt_family_inclusion_marker INTERFACE) +include_guard() if (NOT BOARD) message(FATAL_ERROR "BOARD not specified") @@ -87,6 +83,11 @@ function(family_configure_target TARGET) # set output name to .elf set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET}.elf) + # run size after build + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND ${TOOLCHAIN_SIZE} $ + ) + # TOP is path to root directory set(TOP "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../..") diff --git a/hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake b/hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake new file mode 100644 index 000000000..b540012a4 --- /dev/null +++ b/hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake @@ -0,0 +1,11 @@ +set(MCU_VARIANT LPC18S37) + +set(JLINK_DEVICE LPC18S37) +set(PYOCD_TARGET LPC18S37) +set(NXPLINK_DEVICE LPC18S37:LPCXPRESSO18S37) + +set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/lpc1837.ld) + +function(update_board TARGET) + # nothing to do +endfunction() diff --git a/hw/bsp/lpc18/boards/mcb1800/board.cmake b/hw/bsp/lpc18/boards/mcb1800/board.cmake new file mode 100644 index 000000000..1efeafd12 --- /dev/null +++ b/hw/bsp/lpc18/boards/mcb1800/board.cmake @@ -0,0 +1,11 @@ +set(MCU_VARIANT LPC1857) + +set(JLINK_DEVICE LPC1857) +set(PYOCD_TARGET LPC1857) +set(NXPLINK_DEVICE LPC1857:MCB1857) + +set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/lpc1857.ld) + +function(update_board TARGET) + # nothing to do +endfunction() diff --git a/hw/bsp/lpc18/family.cmake b/hw/bsp/lpc18/family.cmake new file mode 100644 index 000000000..059408fe9 --- /dev/null +++ b/hw/bsp/lpc18/family.cmake @@ -0,0 +1,155 @@ +include_guard() + +if (NOT BOARD) + message(FATAL_ERROR "BOARD not specified") +endif () + +# TOP is path to root directory +set(TOP "${CMAKE_CURRENT_LIST_DIR}/../../..") +set(SDK_DIR ${TOP}/hw/mcu/nxp/lpcopen/lpc18xx/lpc_chip_18xx) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR cortex-m3 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/tools/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS LPC18XX CACHE INTERNAL "") + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +set(BOARD_TARGET board_${BOARD}) +if (NOT TARGET ${BOARD_TARGET}) + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/../gcc/cr_startup_lpc18xx.c + ${SDK_DIR}/src/chip_18xx_43xx.c + ${SDK_DIR}/src/clock_18xx_43xx.c + ${SDK_DIR}/src/gpio_18xx_43xx.c + ${SDK_DIR}/src/sysinit_18xx_43xx.c + ${SDK_DIR}/src/uart_18xx_43xx.c + ) + target_compile_options(${BOARD_TARGET} PUBLIC + -nostdlib + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + __USE_LPCOPEN + CORE_M3 + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/inc + ${SDK_DIR}/inc/config_18xx + ) + update_board(${BOARD_TARGET}) + + if (NOT DEFINED LD_FILE_${TOOLCHAIN}) + MESSAGE(FATAL_ERROR "LD_FILE_${TOOLCHAIN} not defined") + endif () + + if (TOOLCHAIN STREQUAL "gcc") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_gcc}" + "LINKER:-Map=$>,$,$>${CMAKE_EXECUTABLE_SUFFIX}.map" + # nanolib + --specs=nosys.specs + --specs=nano.specs + ) + else () + # TODO support IAR + endif () +endif () # BOARD_TARGET + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_target TARGET) + # set output name to .elf + set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET}.elf) + + # run size after build + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND ${TOOLCHAIN_SIZE} $ + ) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # TinyUSB Port + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + #---------- TinyUSB ---------- + # tinyusb target is built for each example since it depends on example's tusb_config.h + set(TINYUSB_TARGET_PREFIX ${TARGET}-) + add_library(${TARGET}-tinyusb_config INTERFACE) + + target_include_directories(${TARGET}-tinyusb_config INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE + CFG_TUSB_MCU=OPT_MCU_LPC18XX + ) + + # tinyusb's CMakeList.txt + add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) + + # group target (not yet supported by clion) + set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config + PROPERTIES FOLDER ${TARGET}_sub + ) + + #---------- Flash ---------- + family_flash_jlink(${TARGET}) +endfunction() + + +function(family_add_freertos TARGET) + # freertos_config + add_subdirectory(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FreeRTOSConfig ${CMAKE_CURRENT_BINARY_DIR}/freertos_config) + + ## freertos + if (NOT TARGET freertos_kernel) + add_subdirectory(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../../lib/FreeRTOS-Kernel ${CMAKE_CURRENT_BINARY_DIR}/freertos_kernel) + endif () + + # Add FreeRTOS option to tinyusb_config + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE + CFG_TUSB_OS=OPT_OS_FREERTOS + ) + # link tinyusb with freeRTOS kernel + target_link_libraries(${TARGET}-tinyusb PUBLIC + freertos_kernel + ) + target_link_libraries(${TARGET} PUBLIC + freertos_kernel + ) +endfunction() + +function(family_configure_device_example TARGET) + family_configure_target(${TARGET}) +endfunction() + +function(family_configure_host_example TARGET) + family_configure_target(${TARGET}) +endfunction() + +function(family_configure_dual_usb_example TARGET) + family_configure_target(${TARGET}) +endfunction() diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index 611c88eb5..3aeda5b2d 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -1,8 +1,4 @@ -if (TARGET _lpc55_family_inclusion_marker) - return() -endif () - -add_library(_lpc55_family_inclusion_marker INTERFACE) +include_guard() if (NOT BOARD) message(FATAL_ERROR "BOARD not specified") diff --git a/hw/bsp/mcx/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/mcx/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..4c6058d27 --- /dev/null +++ b/hw/bsp/mcx/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,166 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// IAR assembler have limited preprocessor support and it only need following macros: +#ifndef __IASMARM__ +// FIXME cause redundant-decls warnings +extern uint32_t SystemCoreClock; +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 2 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK; + CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); + CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); + + /*According to reference manual, device mode setting has to be set by access usb host register */ + CLOCK_EnableClock(kCLOCK_Usbhsl0); // enable usb0 host clock + USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; + CLOCK_DisableClock(kCLOCK_Usbhsl0); // disable usb0 host clock + + /* enable USB Device clock */ + CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); +#endif + +#if PORT_SUPPORT_DEVICE(1) + // Port1 is High Speed + + // Power + SPC0->ACTIVE_VDELAY = 0x0500; + /* Change the power DCDC to 1.8v (By default, DCDC is 1.8V), CORELDO to 1.1v (By default, CORELDO is 1.0V) */ + SPC0->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK; + SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_DCDC_VDD_LVL(0x3) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(0x3) | + SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK | SPC_ACTIVE_CFG_DCDC_VDD_DS(0x2u); + /* Wait until it is done */ + while (SPC0->SC & SPC_SC_BUSY_MASK) {} + if (0u == (SCG0->LDOCSR & SCG_LDOCSR_LDOEN_MASK)) { + SCG0->TRIM_LOCK = 0x5a5a0001U; + SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK; + /* wait LDO ready */ + while (0U == (SCG0->LDOCSR & SCG_LDOCSR_VOUT_OK_MASK)); + } + SYSCON->AHBCLKCTRLSET[2] |= SYSCON_AHBCLKCTRL2_USB_HS_MASK | SYSCON_AHBCLKCTRL2_USB_HS_PHY_MASK; + SCG0->SOSCCFG &= ~(SCG_SOSCCFG_RANGE_MASK | SCG_SOSCCFG_EREFS_MASK); + /* xtal = 20 ~ 30MHz */ + SCG0->SOSCCFG = (1U << SCG_SOSCCFG_RANGE_SHIFT) | (1U << SCG_SOSCCFG_EREFS_SHIFT); + SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCEN_MASK; + while (1) { + if (SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) { + break; + } + } + + // Clock + SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK | SYSCON_CLOCK_CTRL_CLKIN_ENA_FM_USBH_LPT_MASK; + CLOCK_EnableClock(kCLOCK_UsbHs); + CLOCK_EnableClock(kCLOCK_UsbHsPhy); + CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, 24000000U); + CLOCK_EnableUsbhsClock(); + + // USB PHY +#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT))) + USBPHY->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */ +#endif + + // Enable PHY support for Low speed device + LS via FS Hub + USBPHY->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK | USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; + + // Enable all power for normal operation + USBPHY->PWD = 0; + + // TX Timing + uint32_t phytx = USBPHY->TX; + phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK); + phytx |= USBPHY_TX_D_CAL(0x04) | USBPHY_TX_TXCAL45DP(0x07) | USBPHY_TX_TXCAL45DM(0x07); + //phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06); + USBPHY->TX = phytx; +#endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + GPIO_PinWrite(LED_GPIO, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); + +#ifdef NEOPIXEL_PIN + if (state) { + sctpix_setPixel(NEOPIXEL_CH, 0, 0x100000); + sctpix_setPixel(NEOPIXEL_CH, 1, 0x101010); + } else { + sctpix_setPixel(NEOPIXEL_CH, 0, 0x001000); + sctpix_setPixel(NEOPIXEL_CH, 1, 0x000010); + } + sctpix_show(); +#endif +} + +uint32_t board_button_read(void) +{ +#ifdef BUTTON_GPIO + return BUTTON_STATE_ACTIVE == GPIO_PinRead(BUTTON_GPIO, BUTTON_PIN); +#endif +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ +#ifdef UART_DEV + LPUART_WriteBlocking(UART_DEV, (uint8_t const *) buf, len); + return len; +#else + (void) buf; (void) len; + return 0; +#endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake new file mode 100644 index 000000000..e4bc11be5 --- /dev/null +++ b/hw/bsp/mcx/family.cmake @@ -0,0 +1,179 @@ +include_guard() + +if (NOT BOARD) + message(FATAL_ERROR "BOARD not specified") +endif () + +# TOP is path to root directory +set(TOP ${CMAKE_CURRENT_LIST_DIR}/../../..) +set(SDK_DIR ${TOP}/hw/mcu/nxp/mcux-sdk) +set(CMSIS_DIR ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/tools/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS LPC55XX CACHE INTERNAL "") + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +set(BOARD_TARGET board_${BOARD}) +if (NOT TARGET ${BOARD_TARGET}) + add_library(${BOARD_TARGET} STATIC + # external driver + #lib/sct_neopixel/sct_neopixel.c + + # driver + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_gpio.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_common_arm.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpuart.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpflexcomm.c + # mcu + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c + ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c + ) +# target_compile_definitions(${BOARD_TARGET} PUBLIC +# ) + target_include_directories(${BOARD_TARGET} PUBLIC + # driver + # mcu + ${CMSIS_DIR}/CMSIS/Core/Include + ${SDK_DIR}/devices/${MCU_VARIANT} + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + ) + update_board(${BOARD_TARGET}) + + if (TOOLCHAIN STREQUAL "gcc") + target_sources(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S + ) + target_link_options(${BOARD_TARGET} PUBLIC + # linker file + "LINKER:--script=${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld" + # link map + "LINKER:-Map=$>,$,$>${CMAKE_EXECUTABLE_SUFFIX}.map" + # nanolib + --specs=nosys.specs + --specs=nano.specs + ) + else () + # TODO support IAR + endif () +endif () # BOARD_TARGET + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_target TARGET) + # set output name to .elf + set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET}.elf) + + # run size after build + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND ${TOOLCHAIN_SIZE} $ + ) + + # TOP is path to root directory + set(TOP "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../..") + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # TinyUSB Port + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + #---------- TinyUSB ---------- + # tinyusb target is built for each example since it depends on example's tusb_config.h + set(TINYUSB_TARGET_PREFIX ${TARGET}-) + add_library(${TARGET}-tinyusb_config INTERFACE) + + target_include_directories(${TARGET}-tinyusb_config INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE + CFG_TUSB_MCU=OPT_MCU_MCXN9 + ) + + # tinyusb's CMakeList.txt + add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) + + # group target (not yet supported by clion) + set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config + PROPERTIES FOLDER ${TARGET}_sub + ) + + #---------- Flash ---------- + # use MCUXpresso GUI Flash Tool to flash the elf + +# set(REDLINK_EXE /usr/local/LinkServer/binaries/crt_emu_cm_redlink) +# add_custom_target(${TARGET}-redlink +# DEPENDS ${TARGET} +# COMMAND ${REDLINK_EXE} --flash-load-exec $ --vendor NXP -p MCXN947 --bootromstall +# 0x50000040 -CoreIndex=0 --flash-driver= -x ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/flash --flash-dir +# ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/flash --flash-hashing +# ) + + #family_flash_jlink(${TARGET}) + #family_flash_nxplink(${TARGET}) + #family_flash_pyocd(${TARGET}) +endfunction() + + +function(family_add_freertos TARGET) + # freertos_config + if (NOT TARGET freertos_config) + add_library(freertos_config INTERFACE) + target_include_directories(freertos_config SYSTEM INTERFACE + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FreeRTOSConfig + ) + endif() + + ## freertos + if (NOT TARGET freertos_kernel) + add_subdirectory(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../../lib/FreeRTOS-Kernel ${CMAKE_CURRENT_BINARY_DIR}/freertos_kernel) + endif () + + # Add FreeRTOS option to tinyusb_config + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE + CFG_TUSB_OS=OPT_OS_FREERTOS + ) + # link tinyusb with freeRTOS kernel + target_link_libraries(${TARGET}-tinyusb PUBLIC + freertos_kernel + ) + target_link_libraries(${TARGET} PUBLIC + freertos_kernel + ) +endfunction() + +function(family_configure_device_example TARGET) + family_configure_target(${TARGET}) +endfunction() + +function(family_configure_host_example TARGET) + family_configure_target(${TARGET}) +endfunction() + +function(family_configure_dual_usb_example TARGET) + family_configure_target(${TARGET}) +endfunction() diff --git a/hw/bsp/mcx/family.mk b/hw/bsp/mcx/family.mk new file mode 100644 index 000000000..2cd4c2448 --- /dev/null +++ b/hw/bsp/mcx/family.mk @@ -0,0 +1,48 @@ +UF2_FAMILY_ID = 0x2abc77ec +SDK_DIR = hw/mcu/nxp/mcux-sdk + +DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5 + +include $(TOP)/$(BOARD_PATH)/board.mk + +CPU_CORE ?= cortex-m33 +include $(TOP)/tools/make/cpu/$(CPU_CORE).mk + +# Default to Highspeed PORT1 +PORT ?= 1 + +CFLAGS += \ + -flto \ + -DCFG_TUSB_MCU=OPT_MCU_MCXN9 \ + -DBOARD_TUD_RHPORT=$(PORT) \ + +ifeq ($(PORT), 1) + $(info "PORT1 High Speed") + CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED +else + $(info "PORT0 Full Speed") +endif + +# mcu driver cause following warnings +CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration + +# All source paths should be relative to the top level. +LD_FILE ?= $(SDK_DIR)/devices/$(MCU_VARIANT)/gcc/$(MCU_CORE)_flash.ld + +SRC_C += \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + $(SDK_DIR)/devices/$(MCU_VARIANT)/system_$(MCU_CORE).c \ + $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_clock.c \ + $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_reset.c \ + $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_gpio.c \ + $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_common_arm.c \ + $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpflexcomm.c \ + $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpuart.c \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(SDK_DIR)/devices/$(MCU_VARIANT) \ + $(TOP)/$(SDK_DIR)/devices/$(MCU_VARIANT)/drivers \ + +SRC_S += $(SDK_DIR)/devices/$(MCU_VARIANT)/gcc/startup_$(MCU_CORE).S diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 9c43478e8..1156a171b 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -1,8 +1,4 @@ -if (TARGET _nrf_family_inclusion_marker) - return() -endif () - -add_library(_nrf_family_inclusion_marker INTERFACE) +include_guard() if (NOT BOARD) message(FATAL_ERROR "BOARD not specified") @@ -89,6 +85,11 @@ function(family_configure_target TARGET) # set output name to .elf set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET}.elf) + # run size after build + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND ${TOOLCHAIN_SIZE} $ + ) + # TOP is path to root directory set(TOP "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../..") diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index ba8976a8c..9c2933983 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -59,14 +59,6 @@ #define TUP_USBIP_OHCI #define TUP_OHCI_RHPORTS 2 -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - // TODO USB0 has 6, USB1 has 4 - #define TUP_USBIP_CHIPIDEA_HS - #define TUP_USBIP_EHCI - - #define TUP_DCD_ENDPOINT_MAX 6 - #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 FS - #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) #define TUP_DCD_ENDPOINT_MAX 5 @@ -78,12 +70,28 @@ // TODO USB0 has 5, USB1 has 6 #define TUP_DCD_ENDPOINT_MAX 6 +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) + // USB0 has 6 with HS PHY, USB1 has 4 only FS + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_MCXN9) + // NOTE: MCXN943 port 1 use chipidea HS, port 0 use chipidea FS + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 + #elif TU_CHECK_MCU(OPT_MCU_MIMXRT) #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 HS + #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32) #define TUP_USBIP_CHIPIDEA_FS diff --git a/src/device/dcd.h b/src/device/dcd.h index 00419ff05..f82b8633d 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -102,6 +102,22 @@ typedef struct TU_ATTR_ALIGNED(4) //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); +//--------------------------------------------------------------------+ +// Memory API +//--------------------------------------------------------------------+ + +// clean/flush data cache: write cache -> memory. +// Required before an DMA TX transfer to make sure data is in memory +void dcd_dcache_clean(void* addr, uint32_t data_size) TU_ATTR_WEAK; + +// invalidate data cache: mark cache as invalid, next read will read from memory +// Required BOTH before and after an DMA RX transfer +void dcd_dcache_invalidate(void* addr, uint32_t data_size) TU_ATTR_WEAK; + +// clean and invalidate data cache +// Required before an DMA transfer where memory is both read/write by DMA +void dcd_dcache_clean_invalidate(void* addr, uint32_t data_size) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ diff --git a/src/portable/chipidea/ci_hs/ci_hs_imxrt.h b/src/portable/chipidea/ci_hs/ci_hs_imxrt.h index 607926a65..ceff893bd 100644 --- a/src/portable/chipidea/ci_hs/ci_hs_imxrt.h +++ b/src/portable/chipidea/ci_hs/ci_hs_imxrt.h @@ -46,18 +46,44 @@ static const ci_hs_controller_t _ci_controller[] = { // RT1010 and RT1020 only has 1 USB controller #if FSL_FEATURE_SOC_USBHS_COUNT == 1 - { .reg_base = USB_BASE , .irqnum = USB_OTG1_IRQn, .ep_count = 8 } + { .reg_base = USB_BASE , .irqnum = USB_OTG1_IRQn } #else - { .reg_base = USB1_BASE, .irqnum = USB_OTG1_IRQn, .ep_count = 8 }, - { .reg_base = USB2_BASE, .irqnum = USB_OTG2_IRQn, .ep_count = 8 } + { .reg_base = USB1_BASE, .irqnum = USB_OTG1_IRQn}, + { .reg_base = USB2_BASE, .irqnum = USB_OTG2_IRQn} #endif }; +#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) + +//------------- DCD -------------// #define CI_DCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum) #define CI_DCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum) +//------------- HCD -------------// #define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum) #define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum) +//------------- DCache -------------// +TU_ATTR_ALWAYS_INLINE static inline bool imxrt_is_cache_mem(uint32_t addr) { + return !(0x20000000 <= addr && addr < 0x20100000); +} + +TU_ATTR_ALWAYS_INLINE static inline void imxrt_dcache_clean(void* addr, uint32_t data_size) { + if (imxrt_is_cache_mem((uint32_t) addr)) { + SCB_CleanDCache_by_Addr((uint32_t *) addr, (int32_t) data_size); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void imxrt_dcache_invalidate(void* addr, uint32_t data_size) { + if (imxrt_is_cache_mem((uint32_t) addr)) { + SCB_InvalidateDCache_by_Addr(addr, (int32_t) data_size); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void imxrt_dcache_clean_invalidate(void* addr, uint32_t data_size) { + if (imxrt_is_cache_mem((uint32_t) addr)) { + SCB_CleanInvalidateDCache_by_Addr(addr, (int32_t) data_size); + } +} #endif diff --git a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h index 8c2e7dfa6..2e84c93e7 100644 --- a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h +++ b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h @@ -32,10 +32,12 @@ static const ci_hs_controller_t _ci_controller[] = { - { .reg_base = LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 }, - { .reg_base = LPC_USB1_BASE, .irqnum = USB1_IRQn, .ep_count = 4 } + { .reg_base = LPC_USB0_BASE, .irqnum = USB0_IRQn }, + { .reg_base = LPC_USB1_BASE, .irqnum = USB1_IRQn } }; +#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) + #define CI_DCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum) #define CI_DCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum) diff --git a/src/portable/chipidea/ci_hs/ci_hs_mcx.h b/src/portable/chipidea/ci_hs/ci_hs_mcx.h new file mode 100644 index 000000000..f940f4a9d --- /dev/null +++ b/src/portable/chipidea/ci_hs/ci_hs_mcx.h @@ -0,0 +1,52 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _CI_HS_MCX_H_ +#define _CI_HS_MCX_H_ + +#include "fsl_device_registers.h" + +// NOTE: MCX N9 has 2 different USB Controller +// - USB0 is KHCI FullSpeed +// - USB1 is ChipIdea HighSpeed, therefore rhport = 1 is actually index 0 + +static const ci_hs_controller_t _ci_controller[] = { + {.reg_base = USBHS1__USBC_BASE, .irqnum = USB1_HS_IRQn} +}; + +TU_ATTR_ALWAYS_INLINE static inline ci_hs_regs_t* CI_HS_REG(uint8_t port) { + (void) port; + return ((ci_hs_regs_t*) _ci_controller[0].reg_base); +} + +#define CI_DCD_INT_ENABLE(_p) do { (void) _p; NVIC_EnableIRQ (_ci_controller[0].irqnum); } while (0) +#define CI_DCD_INT_DISABLE(_p) do { (void) _p; NVIC_DisableIRQ(_ci_controller[0].irqnum); } while (0) + +#define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum) +#define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum) + + +#endif diff --git a/src/portable/chipidea/ci_hs/ci_hs_type.h b/src/portable/chipidea/ci_hs/ci_hs_type.h index 31b5a012d..2f3aa3694 100644 --- a/src/portable/chipidea/ci_hs/ci_hs_type.h +++ b/src/portable/chipidea/ci_hs/ci_hs_type.h @@ -31,13 +31,21 @@ extern "C" { #endif +// DCCPARAMS +enum { + DCCPARAMS_DEN_MASK = 0x1Fu, ///< DEN bit 4:0 +}; + // USBCMD enum { USBCMD_RUN_STOP = TU_BIT(0), USBCMD_RESET = TU_BIT(1), USBCMD_SETUP_TRIPWIRE = TU_BIT(13), - USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD -// Interrupt Threshold bit 23:16 + USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14), // This bit is used as a semaphore to ensure the to proper addition of a + // new dTD to an active (primed) endpoint’s linked list. This bit is set and + // cleared by software during the process of adding a new dTD + + USBCMD_INTR_THRESHOLD_MASK = 0x00FF0000u, // Interrupt Threshold bit 23:16 }; // PORTSC1 @@ -72,6 +80,7 @@ enum { // USBMode enum { + USBMOD_CM_MASK = TU_BIT(0) | TU_BIT(1), USBMODE_CM_DEVICE = 2, USBMODE_CM_HOST = 3, @@ -134,7 +143,6 @@ typedef struct { uint32_t reg_base; uint32_t irqnum; - uint8_t ep_count; // Max bi-directional Endpoints }ci_hs_controller_t; #ifdef __cplusplus diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 9be79a2f1..850c82e43 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -28,34 +28,52 @@ #if CFG_TUD_ENABLED && defined(TUP_USBIP_CHIPIDEA_HS) -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ #include "device/dcd.h" #include "ci_hs_type.h" #if CFG_TUSB_MCU == OPT_MCU_MIMXRT #include "ci_hs_imxrt.h" -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) + + void dcd_dcache_clean(void* addr, uint32_t data_size) { + imxrt_dcache_clean(addr, data_size); + } + + void dcd_dcache_invalidate(void* addr, uint32_t data_size) { + imxrt_dcache_invalidate(addr, data_size); + } + + void dcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { + imxrt_dcache_clean_invalidate(addr, data_size); + } + +#else + +#if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) #include "ci_hs_lpc18_43.h" + +#elif TU_CHECK_MCU(OPT_MCU_MCXN9) + // MCX N9 only port 1 use this controller + #include "ci_hs_mcx.h" #else #error "Unsupported MCUs" #endif -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ + TU_ATTR_WEAK void dcd_dcache_clean(void* addr, uint32_t data_size) { + (void) addr; (void) data_size; + } -#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) + TU_ATTR_WEAK void dcd_dcache_invalidate(void* addr, uint32_t data_size) { + (void) addr; (void) data_size; + } -// Clean means to push any cached changes to RAM and invalidate "removes" the -// entry from the cache. -#if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1 - #define CleanInvalidateDCache_by_Addr SCB_CleanInvalidateDCache_by_Addr -#else - #define CleanInvalidateDCache_by_Addr(_addr, _dsize) + TU_ATTR_WEAK void dcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { + (void) addr; (void) data_size; + } #endif +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ // ENDPTCTRL enum { @@ -160,6 +178,16 @@ typedef struct { CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048) static dcd_data_t _dcd_data; +//--------------------------------------------------------------------+ +// Prototypes and Helper Functions +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE +static inline uint8_t ci_ep_count(ci_hs_regs_t const* dcd_reg) +{ + return dcd_reg->DCCPARAMS & DCCPARAMS_DEN_MASK; +} + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ @@ -174,7 +202,8 @@ static void bus_reset(uint8_t rhport) // endpoint type of the unused direction must be changed from the control type to any other // type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior // for the data PID tracking on the active endpoint. - for( uint8_t i=1; i < _ci_controller[rhport].ep_count; i++) + uint8_t const ep_count = ci_ep_count(dcd_reg); + for( uint8_t i=1; i < ep_count; i++) { dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); } @@ -202,7 +231,7 @@ static void bus_reset(uint8_t rhport) _dcd_data.qhd[0][0].int_on_setup = 1; // OUT only - CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); } void dcd_init(uint8_t rhport) @@ -211,26 +240,34 @@ void dcd_init(uint8_t rhport) ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + TU_ASSERT(ci_ep_count(dcd_reg) <= TUP_DCD_ENDPOINT_MAX, ); + // Reset controller dcd_reg->USBCMD |= USBCMD_RESET; while( dcd_reg->USBCMD & USBCMD_RESET ) {} // Set mode to device, must be set immediately after reset - dcd_reg->USBMODE = USBMODE_CM_DEVICE; + uint32_t usbmode = dcd_reg->USBMODE & ~USBMOD_CM_MASK; + usbmode |= USBMODE_CM_DEVICE; + dcd_reg->USBMODE = usbmode; + dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION; #if !TUD_OPT_HIGH_SPEED dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; #endif - CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment dcd_reg->USBSTS = dcd_reg->USBSTS; dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND; - dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 - dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect + uint32_t usbcmd = dcd_reg->USBCMD; + usbcmd &= ~USBCMD_INTR_THRESHOLD_MASK; // Interrupt Threshold Interval = 0 + usbcmd |= USBCMD_RUN_STOP; // run + + dcd_reg->USBCMD = usbcmd; } void dcd_int_enable(uint8_t rhport) @@ -286,7 +323,7 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) { // Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the // address to 32-byte boundaries. Buffer must be word aligned - CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31); + dcd_dcache_clean_invalidate((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31); tu_memclr(p_qtd, sizeof(dcd_qtd_t)); @@ -343,8 +380,10 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + // Must not exceed max endpoint number - TU_ASSERT( epnum < _ci_controller[rhport].ep_count ); + TU_ASSERT(epnum < ci_ep_count(dcd_reg)); //------------- Prepare Queue Head -------------// dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; @@ -359,11 +398,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) p_qhd->qtd_overlay.next = QTD_NEXT_INVALID; - CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); // Enable EP Control - ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); - uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET; if ( dir == TUSB_DIR_OUT ) @@ -382,7 +419,8 @@ void dcd_edpt_close_all (uint8_t rhport) ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); // Disable all non-control endpoints - for( uint8_t epnum=1; epnum < _ci_controller[rhport].ep_count; epnum++) + uint8_t const ep_count = ci_ep_count(dcd_reg); + for (uint8_t epnum = 1; epnum < ep_count; epnum++) { _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1; _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1; @@ -420,7 +458,7 @@ static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir) p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd // flush cache - CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); if ( epnum == 0 ) { @@ -498,7 +536,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } } - CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31); + dcd_dcache_clean_invalidate((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31); } else { @@ -611,7 +649,7 @@ void dcd_int_handler(uint8_t rhport) if (int_status & INTR_USB) { // Make sure we read the latest version of _dcd_data. - CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE; dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index ab6a42e11..8c27abbf6 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -42,28 +42,17 @@ #if CFG_TUSB_MCU == OPT_MCU_MIMXRT #include "ci_hs_imxrt.h" - // check if memory is cacheable i.e not in DTCM - TU_ATTR_ALWAYS_INLINE static inline bool is_cache_mem(uint32_t addr) { - return !(0x20000000 <= addr && addr < 0x20100000); - } - void hcd_dcache_clean(void* addr, uint32_t data_size) { - if (is_cache_mem((uint32_t) addr)) { - SCB_CleanDCache_by_Addr((uint32_t *) addr, (int32_t) data_size); - } + imxrt_dcache_clean(addr, data_size); } void hcd_dcache_invalidate(void* addr, uint32_t data_size) { - if (is_cache_mem((uint32_t) addr)) { - SCB_InvalidateDCache_by_Addr(addr, (int32_t) data_size); - } + imxrt_dcache_invalidate(addr, data_size); } -void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { - if (is_cache_mem((uint32_t) addr)) { - SCB_CleanInvalidateDCache_by_Addr(addr, (int32_t) data_size); + void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { + imxrt_dcache_clean_invalidate(addr, data_size); } -} #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) #include "ci_hs_lpc18_43.h" @@ -75,8 +64,6 @@ void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) - //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 852e7f4fe..2b25eee9d 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -163,22 +163,15 @@ static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t static inline ehci_link_t* list_next (ehci_link_t const *p_link); TU_ATTR_WEAK void hcd_dcache_clean(void* addr, uint32_t data_size) { - (void) addr; - (void) data_size; + (void) addr; (void) data_size; } -// invalidate data cache: mark cache as invalid, next read will read from memory -// Required BOTH before and after an DMA RX transfer TU_ATTR_WEAK void hcd_dcache_invalidate(void* addr, uint32_t data_size) { - (void) addr; - (void) data_size; + (void) addr; (void) data_size; } -// clean and invalidate data cache -// Required before an DMA transfer where memory is both read/write by DMA TU_ATTR_WEAK void hcd_dcache_clean_invalidate(void* addr, uint32_t data_size) { - (void) addr; - (void) data_size; + (void) addr; (void) data_size; } //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index 4f3f3a985..948c9edf3 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -166,6 +166,10 @@ // WCH #define OPT_MCU_CH32V307 2200 ///< WCH CH32V307 + +// NXP LPC MCX +#define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series + // Helper to check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input #define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) @@ -274,7 +278,7 @@ // In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler // to generate unaligned access code. // LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM -#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) +#if TUD_OPT_HIGH_SPEED && TU_CHECK_MCU(OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX) #define TUP_MCU_STRICT_ALIGN 1 #else #define TUP_MCU_STRICT_ALIGN 0 diff --git a/tools/cmake/cpu/cortex-m3.cmake b/tools/cmake/cpu/cortex-m3.cmake new file mode 100644 index 000000000..b740ee44c --- /dev/null +++ b/tools/cmake/cpu/cortex-m3.cmake @@ -0,0 +1,10 @@ +if (TOOLCHAIN STREQUAL "gcc") + list(APPEND TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m3 + ) + + set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "") +else () + # TODO support IAR +endif () diff --git a/tools/cmake/cpu/cortex-m33.cmake b/tools/cmake/cpu/cortex-m33.cmake index fbd5027b1..26c91a64f 100644 --- a/tools/cmake/cpu/cortex-m33.cmake +++ b/tools/cmake/cpu/cortex-m33.cmake @@ -3,10 +3,11 @@ if (TOOLCHAIN STREQUAL "gcc") -mthumb -mcpu=cortex-m33 -mfloat-abi=hard - -mfpu=fpv5-d16 + #-mfpu=fpv5-d16 + -mfpu=fpv5-sp-d16 ) - set(FREERTOS_PORT GCC_ARM_CM33_NONSECURE CACHE INTERNAL "") + set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") else () # TODO support IAR endif () diff --git a/tools/cmake/toolchain/arm_gcc.cmake b/tools/cmake/toolchain/arm_gcc.cmake index c7b6cff98..5f25d637b 100644 --- a/tools/cmake/toolchain/arm_gcc.cmake +++ b/tools/cmake/toolchain/arm_gcc.cmake @@ -3,6 +3,8 @@ set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") set(CMAKE_C_COMPILER "arm-none-eabi-gcc") set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") + +set(TOOLCHAIN_SIZE "arm-none-eabi-size" CACHE INTERNAL "") set(GCC_ELF2BIN "arm-none-eabi-objcopy") set_property(GLOBAL PROPERTY ELF2BIN ${GCC_ELF2BIN}) diff --git a/tools/get_deps.py b/tools/get_deps.py index be5738dc1..f499562cb 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -24,7 +24,7 @@ deps_optional = { 'hw/mcu/nordic/nrfx' : ['2527e3c8449cfd38aee41598e8af8492f410ed15', 'https://github.com/NordicSemiconductor/nrfx.git' ], 'hw/mcu/nuvoton' : ['2204191ec76283371419fbcec207da02e1bc22fa', 'https://github.com/majbthrd/nuc_driver.git' ], 'hw/mcu/nxp/lpcopen' : ['43c45c85405a5dd114fff0ea95cca62837740c13', 'https://github.com/hathach/nxp_lpcopen.git' ], - 'hw/mcu/nxp/mcux-sdk' : ['f357a1150f6cf6c6b844f53f2d426bfb3e649850', 'https://github.com/NXPmicro/mcux-sdk.git' ], + 'hw/mcu/nxp/mcux-sdk' : ['950819b7de9b32f92c3edf396bc5ffb8d66e7009', 'https://github.com/hathach/mcux-sdk.git' ], 'hw/mcu/nxp/nxp_sdk' : ['845c8fc49b6fb660f06a5c45225494eacb06f00c', 'https://github.com/hathach/nxp_sdk.git' ], 'hw/mcu/raspberry_pi/Pico-PIO-USB' : ['c3715ce94b6f6391856de56081d4d9b3e98fa93d', 'https://github.com/sekigon-gonnoc/Pico-PIO-USB.git' ], 'hw/mcu/renesas/fsp' : ['8dc14709f2a6518b43f71efad70d900b7718d9f1', 'https://github.com/renesas/fsp.git' ], diff --git a/tools/make/cpu/cortex-m33.mk b/tools/make/cpu/cortex-m33.mk index 2ea3a0753..3d12b01fd 100644 --- a/tools/make/cpu/cortex-m33.mk +++ b/tools/make/cpu/cortex-m33.mk @@ -3,7 +3,9 @@ ifeq ($(TOOLCHAIN),gcc) -mthumb \ -mcpu=cortex-m33 \ -mfloat-abi=hard \ - -mfpu=fpv5-d16 \ + -mfpu=fpv5-sp-d16 \ + + #-mfpu=fpv5-d16 \ #set(FREERTOS_PORT GCC_ARM_CM33_NONSECURE CACHE INTERNAL "") FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure -- cgit v1.3.1 From 57d2eb603b412a6bfbfdad7fb0bac854302b4351 Mon Sep 17 00:00:00 2001 From: Aladdin Bakosh Date: Mon, 15 May 2023 18:27:45 +0200 Subject: fix(RA Host Portable): implement missing function __builtin_ctz(x) for IAR --- src/portable/renesas/rusb2/hcd_rusb2.c | 2 +- src/portable/renesas/rusb2/rusb2_ra.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index e4743223e..0e6fa1618 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -407,7 +407,7 @@ static void process_pipe0_bemp(uint8_t rhport) static void process_pipe_nrdy(uint8_t rhport, unsigned num) { (void)rhport; - unsigned result; + xfer_result_t result; uint16_t volatile *ctr = get_pipectr(num); // TU_LOG1("NRDY %d %x\n", num, *ctr); switch (*ctr & RUSB2_PIPE_CTR_PID_Msk) { diff --git a/src/portable/renesas/rusb2/rusb2_ra.h b/src/portable/renesas/rusb2/rusb2_ra.h index 5785850cc..5be9f11ce 100644 --- a/src/portable/renesas/rusb2/rusb2_ra.h +++ b/src/portable/renesas/rusb2/rusb2_ra.h @@ -36,6 +36,10 @@ extern "C" { #define RUSB2_REG_BASE (0x40090000) +#if defined(__ICCARM__) + #define __builtin_ctz(x) __iar_builtin_CLZ(__iar_builtin_RBIT(x)) +#endif + TU_ATTR_ALWAYS_INLINE static inline void rusb2_int_enable(uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From 26d05d7fc922f3715799f6049556232d5ed5c8e3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 25 May 2023 16:53:32 +0700 Subject: fix issue with ftdi host driver with status bytes add workflow_dispatch to all ci workflow --- .github/workflows/build_aarch64.yml | 1 + .github/workflows/build_arm.yml | 1 + .github/workflows/build_esp.yml | 1 + .github/workflows/build_iar.yml | 1 + .github/workflows/build_msp430.yml | 1 + .github/workflows/build_renesas.yml | 1 + .github/workflows/build_riscv.yml | 1 + .github/workflows/build_win_mac.yml | 1 + .github/workflows/cifuzz.yml | 1 + src/class/cdc/cdc_host.c | 36 +++++++++++++++++------------------- src/common/tusb_private.h | 17 +++++++++++------ 11 files changed, 37 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/.github/workflows/build_aarch64.yml b/.github/workflows/build_aarch64.yml index cc8ddb070..77d3778d7 100644 --- a/.github/workflows/build_aarch64.yml +++ b/.github/workflows/build_aarch64.yml @@ -1,6 +1,7 @@ name: Build AArch64 on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 917c83d74..1db9586af 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -1,6 +1,7 @@ name: Build ARM on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index 0a6815ea2..29585cb36 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -1,6 +1,7 @@ name: Build ESP on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/build_iar.yml b/.github/workflows/build_iar.yml index a5d24892f..8c3b57e10 100644 --- a/.github/workflows/build_iar.yml +++ b/.github/workflows/build_iar.yml @@ -1,6 +1,7 @@ name: Build IAR on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/build_msp430.yml b/.github/workflows/build_msp430.yml index 7cb60dceb..5424a88d6 100644 --- a/.github/workflows/build_msp430.yml +++ b/.github/workflows/build_msp430.yml @@ -1,6 +1,7 @@ name: Build MSP430 on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index ffdeedb71..3f0a4b694 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -1,6 +1,7 @@ name: Build Renesas on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml index 87c7b522e..8682d655a 100644 --- a/.github/workflows/build_riscv.yml +++ b/.github/workflows/build_riscv.yml @@ -1,6 +1,7 @@ name: Build RISC-V on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/build_win_mac.yml b/.github/workflows/build_win_mac.yml index 4b743a686..45fc62f78 100644 --- a/.github/workflows/build_win_mac.yml +++ b/.github/workflows/build_win_mac.yml @@ -1,6 +1,7 @@ name: Build Windows/MacOS on: + workflow_dispatch: push: paths: - 'src/**' diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 7314fd9e6..4c4b12a6b 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -1,5 +1,6 @@ name: CIFuzz on: + workflow_dispatch: pull_request: branches: - master diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 9ff666ed4..ce9f27c33 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -550,8 +550,7 @@ void cdch_close(uint8_t daddr) } } -bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ +bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { // TODO handle stall response, retry failed transfer ... TU_ASSERT(event == XFER_RESULT_SUCCESS); @@ -559,41 +558,40 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc); - if ( ep_addr == p_cdc->stream.tx.ep_addr ) - { + if ( ep_addr == p_cdc->stream.tx.ep_addr ) { // invoke tx complete callback to possibly refill tx fifo if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx); - if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) - { + if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); } } - else if ( ep_addr == p_cdc->stream.rx.ep_addr ) - { - tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - + else if ( ep_addr == p_cdc->stream.rx.ep_addr ) { #if CFG_TUH_CDC_FTDI - // FTDI reserve 2 bytes for status if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { - uint8_t status[2]; - tu_edpt_stream_read(&p_cdc->stream.rx, status, 2); - (void) status; // TODO handle status - } + // FTDI reserve 2 bytes for status + // FTDI status +// uint8_t status[2] = { +// p_cdc->stream.rx.ep_buf[0], +// p_cdc->stream.rx.ep_buf[1] +// }; + tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2); + }else #endif + { + tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); + } // invoke receive callback if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx); // prepare for next transfer if needed tu_edpt_stream_read_xfer(&p_cdc->stream.rx); - }else if ( ep_addr == p_cdc->ep_notif ) - { + }else if ( ep_addr == p_cdc->ep_notif ) { // TODO handle notification endpoint - }else - { + }else { TU_ASSERT(false); } diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index d5541856c..db1ba974d 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -148,21 +148,26 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s); // Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) -{ +void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); } +// Same as tu_edpt_stream_read_xfer_complete but skip the first n bytes +TU_ATTR_ALWAYS_INLINE static inline +void tu_edpt_stream_read_xfer_complete_offset(tu_edpt_stream_t* s, uint32_t xferred_bytes, uint32_t skip_offset) { + if (skip_offset < xferred_bytes) { + tu_fifo_write_n(&s->ff, s->ep_buf + skip_offset, (uint16_t) (xferred_bytes - skip_offset)); + } +} + // Get the number of bytes available for reading TU_ATTR_ALWAYS_INLINE static inline -uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) -{ +uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) { return (uint32_t) tu_fifo_count(&s->ff); } TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) -{ +bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) { return tu_fifo_peek(&s->ff, ch); } -- cgit v1.3.1 From b262164a35e9e305b67cb8d0c2188353db405200 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 May 2023 15:16:18 +0700 Subject: fix build with net_lwip_webserver example --- examples/device/CMakeLists.txt | 7 +- examples/device/net_lwip_webserver/CMakeLists.txt | 148 +++++++++++----------- src/CMakeLists.txt | 2 + 3 files changed, 80 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index 89cfceeeb..5b077a5e1 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -22,12 +22,7 @@ family_add_subdirectory(hid_generic_inout) family_add_subdirectory(hid_multiple_interface) family_add_subdirectory(midi_test) family_add_subdirectory(msc_dual_lun) - -# FIXME temp skip net_lwip_webserver for imxrt for now -if (NOT ${FAMILY} STREQUAL "imxrt" AND NOT ${FAMILY} STREQUAL "mcx") - family_add_subdirectory(net_lwip_webserver) -endif() - +family_add_subdirectory(net_lwip_webserver) family_add_subdirectory(uac2_headset) family_add_subdirectory(usbtmc) family_add_subdirectory(video_capture) diff --git a/examples/device/net_lwip_webserver/CMakeLists.txt b/examples/device/net_lwip_webserver/CMakeLists.txt index e7338c809..5225f7c42 100644 --- a/examples/device/net_lwip_webserver/CMakeLists.txt +++ b/examples/device/net_lwip_webserver/CMakeLists.txt @@ -1,83 +1,89 @@ cmake_minimum_required(VERSION 3.17) -set(TOP "../../..") -get_filename_component(TOP "${TOP}" REALPATH) +include(${CMAKE_CURRENT_LIST_DIR}/../../../hw/bsp/family_support.cmake) -if (EXISTS ${TOP}/lib/lwip/src) - include(${TOP}/hw/bsp/family_support.cmake) +set(LWIP ${TOP}/lib/lwip) +if (NOT EXISTS ${LWIP}/src) + MESSAGE(WARNING "lib/lwip submodule not found, please run 'python tools/get_deps.py lib/lwip' to fetch it") + return() +endif() - # gets PROJECT name for the example (e.g. -) - family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) - project(${PROJECT} C CXX ASM) +project(${PROJECT} C CXX ASM) - # Checks this example is valid for the family and initializes the project - family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) - add_executable(${PROJECT}) +add_executable(${PROJECT}) - # Example source - target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ) +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/src/main.c + ${CMAKE_CURRENT_LIST_DIR}/src/usb_descriptors.c + ) - # Example include - target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${TOP}/lib/lwip/src/include - ${TOP}/lib/lwip/src/include/ipv4 - ${TOP}/lib/lwip/src/include/lwip/apps - ${TOP}/lib/networking - ) +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/src + ${LWIP}/src/include + ${LWIP}/src/include/ipv4 + ${LWIP}/src/include/lwip/apps + ${TOP}/lib/networking + ) - target_sources(${PROJECT} PUBLIC - ${TOP}/lib/lwip/src/core/altcp.c - ${TOP}/lib/lwip/src/core/altcp_alloc.c - ${TOP}/lib/lwip/src/core/altcp_tcp.c - ${TOP}/lib/lwip/src/core/def.c - ${TOP}/lib/lwip/src/core/dns.c - ${TOP}/lib/lwip/src/core/inet_chksum.c - ${TOP}/lib/lwip/src/core/init.c - ${TOP}/lib/lwip/src/core/ip.c - ${TOP}/lib/lwip/src/core/mem.c - ${TOP}/lib/lwip/src/core/memp.c - ${TOP}/lib/lwip/src/core/netif.c - ${TOP}/lib/lwip/src/core/pbuf.c - ${TOP}/lib/lwip/src/core/raw.c - ${TOP}/lib/lwip/src/core/stats.c - ${TOP}/lib/lwip/src/core/sys.c - ${TOP}/lib/lwip/src/core/tcp.c - ${TOP}/lib/lwip/src/core/tcp_in.c - ${TOP}/lib/lwip/src/core/tcp_out.c - ${TOP}/lib/lwip/src/core/timeouts.c - ${TOP}/lib/lwip/src/core/udp.c - ${TOP}/lib/lwip/src/core/ipv4/autoip.c - ${TOP}/lib/lwip/src/core/ipv4/dhcp.c - ${TOP}/lib/lwip/src/core/ipv4/etharp.c - ${TOP}/lib/lwip/src/core/ipv4/icmp.c - ${TOP}/lib/lwip/src/core/ipv4/igmp.c - ${TOP}/lib/lwip/src/core/ipv4/ip4.c - ${TOP}/lib/lwip/src/core/ipv4/ip4_addr.c - ${TOP}/lib/lwip/src/core/ipv4/ip4_frag.c - ${TOP}/lib/lwip/src/netif/ethernet.c - ${TOP}/lib/lwip/src/netif/slipif.c - ${TOP}/lib/lwip/src/apps/http/httpd.c - ${TOP}/lib/lwip/src/apps/http/fs.c - ${TOP}/lib/networking/dhserver.c - ${TOP}/lib/networking/dnserver.c - ${TOP}/lib/networking/rndis_reports.c - ) +# lib/networking sources +target_sources(${PROJECT} PUBLIC + ${TOP}/lib/networking/dhserver.c + ${TOP}/lib/networking/dnserver.c + ${TOP}/lib/networking/rndis_reports.c + ) - # due to warnings from other net source, we need to prevent error from some of the warnings options - target_compile_options(${PROJECT} PUBLIC - -Wno-error=null-dereference - -Wno-error=conversion - -Wno-error=sign-conversion - -Wno-error=sign-compare - ) +# lwip sources +target_sources(${PROJECT} PUBLIC + ${LWIP}/src/core/altcp.c + ${LWIP}/src/core/altcp_alloc.c + ${LWIP}/src/core/altcp_tcp.c + ${LWIP}/src/core/def.c + ${LWIP}/src/core/dns.c + ${LWIP}/src/core/inet_chksum.c + ${LWIP}/src/core/init.c + ${LWIP}/src/core/ip.c + ${LWIP}/src/core/mem.c + ${LWIP}/src/core/memp.c + ${LWIP}/src/core/netif.c + ${LWIP}/src/core/pbuf.c + ${LWIP}/src/core/raw.c + ${LWIP}/src/core/stats.c + ${LWIP}/src/core/sys.c + ${LWIP}/src/core/tcp.c + ${LWIP}/src/core/tcp_in.c + ${LWIP}/src/core/tcp_out.c + ${LWIP}/src/core/timeouts.c + ${LWIP}/src/core/udp.c + ${LWIP}/src/core/ipv4/autoip.c + ${LWIP}/src/core/ipv4/dhcp.c + ${LWIP}/src/core/ipv4/etharp.c + ${LWIP}/src/core/ipv4/icmp.c + ${LWIP}/src/core/ipv4/igmp.c + ${LWIP}/src/core/ipv4/ip4.c + ${LWIP}/src/core/ipv4/ip4_addr.c + ${LWIP}/src/core/ipv4/ip4_frag.c + ${LWIP}/src/netif/ethernet.c + ${LWIP}/src/netif/slipif.c + ${LWIP}/src/apps/http/httpd.c + ${LWIP}/src/apps/http/fs.c + ) - # Configure compilation flags and libraries for the example... see the corresponding function - # in hw/bsp/FAMILY/family.cmake for details. - family_configure_device_example(${PROJECT}) -endif() +# due to warnings from other net source, we need to prevent error from some of the warnings options +target_compile_options(${PROJECT} PUBLIC + -Wno-error=null-dereference + -Wno-error=conversion + -Wno-error=sign-conversion + -Wno-error=sign-compare + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0b99d8919..0d2f0975b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,8 @@ function(add_tinyusb TARGET) ) target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + # TODO for net driver, should be removed/changed + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../lib/networking ) # enable all possible warnings target_compile_options(${TARGET} PUBLIC -- cgit v1.3.1 From 7ac85d08c7aa59f35cbbf2657dd9be68d46e1fdc Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 May 2023 16:37:47 +0700 Subject: move lpc18 and rp2040 to cmake workflow since rp2040 often failed randomly with make --- .github/workflows/build_arm.yml | 3 +- .github/workflows/cmake_arm.yml | 19 ++- hw/bsp/imxrt/FreeRTOSConfig/FreeRTOSConfig.h | 8 +- hw/bsp/lpc18/FreeRTOSConfig/FreeRTOSConfig.h | 166 +++++++++++++++++++++ hw/bsp/lpc55/FreeRTOSConfig/FreeRTOSConfig.h | 8 +- hw/bsp/lpc55/boards/double_m33_express/board.cmake | 16 ++ hw/bsp/lpc55/family.cmake | 14 +- hw/bsp/mcx/FreeRTOSConfig/FreeRTOSConfig.h | 8 +- hw/bsp/nrf/FreeRTOSConfig/FreeRTOSConfig.h | 166 +++++++++++++++++++++ hw/bsp/saml2x/family.mk | 4 +- src/CMakeLists.txt | 47 ++++-- tools/get_deps.py | 4 +- 12 files changed, 429 insertions(+), 34 deletions(-) create mode 100644 hw/bsp/lpc18/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/lpc55/boards/double_m33_express/board.cmake create mode 100644 hw/bsp/nrf/FreeRTOSConfig/FreeRTOSConfig.h (limited to 'src') diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 8fbaba4c6..42c8eb7ce 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -35,12 +35,11 @@ jobs: # Alphabetical order - 'broadcom_32bit' - 'kinetis_k32l kinetis_kl' - - 'lpc11 lpc13 lpc15 lpc17 lpc18' + - 'lpc11 lpc13 lpc15 lpc17' - 'lpc51 lpc54 lpc55' - 'mm32 msp432e4' - 'nrf' - 'ra' - - 'rp2040' - 'samd11 samd21' - 'samd51 same5x' - 'saml2x' diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index e7991252d..f3989f239 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -32,9 +32,11 @@ jobs: fail-fast: false matrix: family: - # Alphabetical order - - 'mcx' - - 'imxrt' + # Alphabetical order + - 'lpc18' + - 'mcx' + - 'imxrt' + - 'rp2040' steps: - name: Setup Python uses: actions/setup-python@v4 @@ -52,8 +54,19 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v3 + - name: Checkout pico-sdk for rp2040 + if: matrix.family == 'rp2040' + uses: actions/checkout@v3 + with: + repository: raspberrypi/pico-sdk + ref: develop + path: pico-sdk + - name: Get Dependencies run: python3 tools/get_deps.py ${{ matrix.family }} - name: Build run: python tools/build_cmake.py ${{ matrix.family }} + env: + # for rp2040, there is no harm if defined for other families + PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk diff --git a/hw/bsp/imxrt/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/imxrt/FreeRTOSConfig/FreeRTOSConfig.h index c8d94f9ed..c1928fbcd 100644 --- a/hw/bsp/imxrt/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/imxrt/FreeRTOSConfig/FreeRTOSConfig.h @@ -49,10 +49,10 @@ extern uint32_t SystemCoreClock; #endif /* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) #define configUSE_PREEMPTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 diff --git a/hw/bsp/lpc18/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/lpc18/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..323c1a0a4 --- /dev/null +++ b/hw/bsp/lpc18/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,166 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// IAR assembler have limited preprocessor support and it only need following macros: +#ifndef __IASMARM__ +// FIXME cause redundant-decls warnings +extern uint32_t SystemCoreClock; +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 2 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Sun, 9 Apr 2023 19:10:01 -0400 Subject: Even when we get an empty "status change" interrupt from the hub, schedule another interrupt poll. During enumeration, when there are multiple devices attached to the hub as it's plugged into the Pi Pico, enumeration hangs, because we get a "status change" callback with value zero. With this patch, we retry several times on "zero" status change callbacks, until eventually we succeed. This is the cheapo hub that exhibits this behavior, but I assume it's not the only one: https://www.amazon.com/gp/product/B083RQMC7S. While debugging this, I consulted the implementation in the Linux kernel. There, hub setup explicitly checks each port individually, before starting to depend on "status change" interrupts: https://elixir.bootlin.com/linux/latest/source/drivers/usb/core/hub.c#L1133. We probably should do something like that here, but it's a much bigger change. --- src/host/hub.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/host/hub.c b/src/host/hub.c index 85bf22b3e..5b2db547d 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -361,6 +361,13 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 break; } } + + // The status change event was neither for the hub, nor for any of + // its ports. (For example `p_hub->status_change == 0`.) This + // shouldn't happen, but it does with some devices. Initiate the + // next interrupt poll here, because we've scheduled no other work + // whose completion can initiate it. + hub_edpt_status_xfer(dev_addr); } // NOTE: next status transfer is queued by usbh.c after handling this request -- cgit v1.3.1 From 5c428d35a61f7d877cba19d9e094bd519ae91997 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 29 May 2023 13:27:20 +0700 Subject: check status_change is not zero first --- src/host/hub.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/host/hub.c b/src/host/hub.c index 5b2db547d..0807c2023 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -327,51 +327,45 @@ static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); static void connection_port_reset_complete (tuh_xfer_t* xfer); // callback as response of interrupt endpoint polling -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; TU_ASSERT(result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); - TU_LOG2(" Hub Status Change = 0x%02X\r\n", p_hub->status_change); + uint8_t const status_change = p_hub->status_change; + TU_LOG2(" Hub Status Change = 0x%02X\r\n", status_change); - // Hub bit 0 is for the hub device events - if (tu_bit_test(p_hub->status_change, 0)) - { - if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) - { + if ( status_change == 0 ) { + // The status change event was neither for the hub, nor for any of its ports. + // This shouldn't happen, but it does with some devices. + // Initiate the next interrupt poll here. + hub_edpt_status_xfer(dev_addr); + return true; + } + + if (tu_bit_test(status_change, 0)) { + // Hub bit 0 is for the hub device events + if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) { //Hub status control transfer failed, retry hub_edpt_status_xfer(dev_addr); } } - else - { + else { // Hub bits 1 to n are hub port events - for (uint8_t port=1; port <= p_hub->port_count; port++) - { - if ( tu_bit_test(p_hub->status_change, port) ) - { - if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) - { + for (uint8_t port=1; port <= p_hub->port_count; port++) { + if ( tu_bit_test(status_change, port) ) { + if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) { //Hub status control transfer failed, retry hub_edpt_status_xfer(dev_addr); } break; } } - - // The status change event was neither for the hub, nor for any of - // its ports. (For example `p_hub->status_change == 0`.) This - // shouldn't happen, but it does with some devices. Initiate the - // next interrupt poll here, because we've scheduled no other work - // whose completion can initiate it. - hub_edpt_status_xfer(dev_addr); } // NOTE: next status transfer is queued by usbh.c after handling this request - return true; } -- cgit v1.3.1 From 20ef6c4ef7f7fa7130352ae0c0984692a9719b35 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 29 May 2023 13:29:11 +0700 Subject: slightly clean up --- src/host/hub.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/host/hub.c b/src/host/hub.c index 0807c2023..182bd6ce8 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -341,8 +341,7 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 // The status change event was neither for the hub, nor for any of its ports. // This shouldn't happen, but it does with some devices. // Initiate the next interrupt poll here. - hub_edpt_status_xfer(dev_addr); - return true; + return hub_edpt_status_xfer(dev_addr); } if (tu_bit_test(status_change, 0)) { -- cgit v1.3.1 From 70a92291fe84eb57844a331749ceecb6d2f1f544 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Thu, 1 Jun 2023 10:58:03 -0400 Subject: Fix diagnostic format string (missing %u) --- src/host/usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 7b265c742..6159044ab 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1179,7 +1179,7 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); if (is_hub_addr(daddr)) { - TU_LOG(USBH_DEBUG, " is a HUB device\r\n", daddr); + TU_LOG(USBH_DEBUG, " is a HUB device %u\r\n", daddr); // Submit removed event If the device itself is a hub (un-rolled recursive) // TODO a better to unroll recursrive is using array of removing_hubs and mark it here -- cgit v1.3.1 From e7090c75148820ff3a4ad60c718684c46c954c18 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Jun 2023 11:42:17 +0700 Subject: cmake refactor --- .github/workflows/build_arm.yml | 2 +- .github/workflows/cmake_arm.yml | 9 ++-- hw/bsp/family_support.cmake | 116 +++++++++++++++++++++++++--------------- hw/bsp/imxrt/family.cmake | 26 ++------- hw/bsp/lpc18/family.cmake | 23 ++------ hw/bsp/lpc55/family.cmake | 25 ++------- hw/bsp/mcx/family.cmake | 23 ++------ hw/bsp/nrf/family.cmake | 23 ++------ hw/bsp/stm32g0/family.cmake | 23 ++------ hw/bsp/stm32g4/family.cmake | 25 ++------- src/CMakeLists.txt | 4 ++ tools/build_cmake.py | 10 ++-- 12 files changed, 112 insertions(+), 197 deletions(-) (limited to 'src') diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 3a2daab08..a7c7fd1e1 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -46,7 +46,7 @@ jobs: - 'stm32f0 stm32f1 stm32f2 stm32f3' - 'stm32f4' - 'stm32f7' - - 'stm32g4 stm32h7' + - 'stm32h7' - 'stm32l0 stm32l4 stm32u5 stm32wb' - 'tm4c123 xmc4000' steps: diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 2e74c304c..2ca8e32f5 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -38,6 +38,7 @@ jobs: - 'imxrt' - 'rp2040' - 'stm32g0' + - 'stm32g4' steps: - name: Setup Python uses: actions/setup-python@v4 @@ -75,11 +76,11 @@ jobs: # Upload binaries for hardware test with self-hosted - name: Prepare rp2040 Artifacts if: contains(matrix.family, 'rp2040') && github.repository_owner == 'hathach' - working-directory: ${{github.workspace}}/cmake-build-ci-raspberry_pi_pico + working-directory: ${{github.workspace}}/cmake-build/cmake-build-raspberry_pi_pico run: | - find device/ -name "*.elf" -exec mv {} ../ \; - # find host/ -name "*.elf" -exec mv {} ../ \; - # find dual/ -name "*.elf" -exec mv {} ../ \; + find device/ -name "*.elf" -exec mv {} ../../ \; + # find host/ -name "*.elf" -exec mv {} ../../ \; + # find dual/ -name "*.elf" -exec mv {} ../../ \; - name: Upload Artifacts for rp2040 if: contains(matrix.family,'rp2040') && github.repository_owner == 'hathach' diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index d9b8bbbe9..fdc9580ae 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -84,8 +84,8 @@ endfunction() function(family_initialize_project PROJECT DIR) - # set output suffix to .elf (skip espressif) - if(NOT FAMILY STREQUAL "espressif") + # set output suffix to .elf (skip espressif and rp2040) + if(NOT FAMILY STREQUAL "espressif" AND NOT FAMILY STREQUAL "rp2040") set(CMAKE_EXECUTABLE_SUFFIX .elf PARENT_SCOPE) endif() @@ -144,6 +144,11 @@ function(family_add_default_example_warnings TARGET) endfunction() +#------------------------------------ +# Main target configure +#------------------------------------ + +# Add common configuration to example function(family_configure_common TARGET) # run size after build add_custom_command(TARGET ${TARGET} POST_BUILD @@ -158,6 +163,66 @@ function(family_configure_common TARGET) endfunction() +# configure an executable target to link to tinyusb in device mode, and add the board implementation +function(family_configure_device_example TARGET) + # default implementation is empty, the function should be redefined in the FAMILY/family.cmake +endfunction() + + +# configure an executable target to link to tinyusb in host mode, and add the board implementation +function(family_configure_host_example TARGET) + # default implementation is empty, the function should be redefined in the FAMILY/family.cmake +endfunction() + + +# Add tinyusb to example +function(family_add_tinyusb TARGET OPT_MCU) + # tinyusb target is built for each example since it depends on example's tusb_config.h + set(TINYUSB_TARGET_PREFIX ${TARGET}-) + add_library(${TARGET}-tinyusb_config INTERFACE) + + target_include_directories(${TARGET}-tinyusb_config INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE + CFG_TUSB_MCU=${OPT_MCU} + ) + + # tinyusb's CMakeList.txt + add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) +endfunction() + + +# Add freeRTOS support to example +function(family_add_freertos TARGET) + # freeros config + if (NOT TARGET freertos_config) + add_library(freertos_config INTERFACE) + target_include_directories(freertos_config SYSTEM INTERFACE + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${FAMILY}/FreeRTOSConfig + ) + endif() + + # freertos kernel should be generic as freertos_config however, CMAKE complains with missing variable + # such as CMAKE_C_COMPILE_OBJECT + if (NOT TARGET freertos_kernel) + add_subdirectory(${TOP}/lib/FreeRTOS-Kernel ${CMAKE_BINARY_DIR}/lib/freertos_kernel) + endif () + + # Add FreeRTOS option to tinyusb_config + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE + CFG_TUSB_OS=OPT_OS_FREERTOS + ) + # link tinyusb with freeRTOS kernel + target_link_libraries(${TARGET}-tinyusb PUBLIC + freertos_kernel + ) + target_link_libraries(${TARGET} PUBLIC + freertos_kernel + ) +endfunction() + + # Add bin/hex output function(family_add_bin_hex TARGET) add_custom_command(TARGET ${TARGET} POST_BUILD @@ -167,6 +232,10 @@ function(family_add_bin_hex TARGET) endfunction() +#---------------------------------- +# Flashing target +#---------------------------------- + # Add flash jlink target function(family_flash_jlink TARGET) if (NOT DEFINED JLINKEXE) @@ -233,48 +302,7 @@ function(family_flash_nxplink TARGET) endfunction() -# configure an executable target to link to tinyusb in device mode, and add the board implementation -function(family_configure_device_example TARGET) - # default implementation is empty, the function should be redefined in the FAMILY/family.cmake -endfunction() - - -# configure an executable target to link to tinyusb in host mode, and add the board implementation -function(family_configure_host_example TARGET) - # default implementation is empty, the function should be redefined in the FAMILY/family.cmake -endfunction() - - -# Add freeRTOS support to example, can be overridden by FAMILY/family.cmake -function(family_add_freertos TARGET) - # freeros config - if (NOT TARGET freertos_config) - add_library(freertos_config INTERFACE) - target_include_directories(freertos_config SYSTEM INTERFACE - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${FAMILY}/FreeRTOSConfig - ) - endif() - - # freertos kernel should be generic as freertos_config however, CMAKE complains with missing variable - # such as CMAKE_C_COMPILE_OBJECT - if (NOT TARGET freertos_kernel) - add_subdirectory(${TOP}/lib/FreeRTOS-Kernel ${CMAKE_BINARY_DIR}/lib/freertos_kernel) - endif () - - # Add FreeRTOS option to tinyusb_config - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_OS=OPT_OS_FREERTOS - ) - # link tinyusb with freeRTOS kernel - target_link_libraries(${TARGET}-tinyusb PUBLIC - freertos_kernel - ) - target_link_libraries(${TARGET} PUBLIC - freertos_kernel - ) -endfunction() - - +# family specific: can override above functions include(${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake) if (NOT FAMILY_MCUS) diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 49a4a9281..3c156285c 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -36,7 +36,6 @@ if (NOT TARGET ${BOARD_TARGET}) ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c ) target_compile_definitions(${BOARD_TARGET} PUBLIC - CFG_TUSB_MCU=OPT_MCU_MIMXRT __ARMVFP__=0 __ARMFPV5__=0 XIP_EXTERNAL_FLASH=1 @@ -100,33 +99,16 @@ function(family_configure_example TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - #---------- TinyUSB ---------- - # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}-) - add_library(${TARGET}-tinyusb_config INTERFACE) - - target_include_directories(${TARGET}-tinyusb_config INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_MCU=OPT_MCU_MIMXRT - ) - - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # Add TinyUSB + family_add_tinyusb(${TARGET} OPT_MCU_MIMXRT) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # group target (not yet supported by clion) - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub - ) - - #---------- Flash ---------- + # Flashing family_flash_jlink(${TARGET}) family_flash_nxplink(${TARGET}) - family_flash_pyocd(${TARGET}) + #family_flash_pyocd(${TARGET}) endfunction() diff --git a/hw/bsp/lpc18/family.cmake b/hw/bsp/lpc18/family.cmake index 515348e10..a133e7217 100644 --- a/hw/bsp/lpc18/family.cmake +++ b/hw/bsp/lpc18/family.cmake @@ -83,30 +83,13 @@ function(family_configure_example TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - #---------- TinyUSB ---------- - # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}-) - add_library(${TARGET}-tinyusb_config INTERFACE) - - target_include_directories(${TARGET}-tinyusb_config INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_MCU=OPT_MCU_LPC18XX - ) - - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # Add TinyUSB + family_add_tinyusb(${TARGET} OPT_MCU_LPC18XX) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # group target (not yet supported by clion) - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub - ) - - #---------- Flash ---------- + # Flashing family_flash_jlink(${TARGET}) endfunction() diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index eb163bde7..25eed48de 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -109,33 +109,16 @@ function(family_configure_example TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - #---------- TinyUSB ---------- - # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}-) - add_library(${TARGET}-tinyusb_config INTERFACE) - - target_include_directories(${TARGET}-tinyusb_config INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_MCU=OPT_MCU_LPC55XX - ) - - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # Add TinyUSB + family_add_tinyusb(${TARGET} OPT_MCU_LPC55XX) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # group target (not yet supported by clion) - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub - ) - - #---------- Flash ---------- + # Flashing family_flash_jlink(${TARGET}) family_flash_nxplink(${TARGET}) - family_flash_pyocd(${TARGET}) + #family_flash_pyocd(${TARGET}) endfunction() diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index d5a17f584..17f54a53b 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -91,30 +91,13 @@ function(family_configure_example TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - #---------- TinyUSB ---------- - # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}-) - add_library(${TARGET}-tinyusb_config INTERFACE) - - target_include_directories(${TARGET}-tinyusb_config INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_MCU=OPT_MCU_MCXN9 - ) - - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # Add TinyUSB + family_add_tinyusb(${TARGET} OPT_MCU_MCXN9) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # group target (not yet supported by clion) - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub - ) - - #---------- Flash ---------- + # Flashing family_flash_jlink(${TARGET}) #family_flash_nxplink(${TARGET}) #family_flash_pyocd(${TARGET}) diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 71067c8ae..2c5d7a431 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -98,30 +98,13 @@ function(family_configure_example TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - #---------- TinyUSB ---------- - # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}-) - add_library(${TARGET}-tinyusb_config INTERFACE) - - target_include_directories(${TARGET}-tinyusb_config INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_MCU=OPT_MCU_NRF5X - ) - - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # Add TinyUSB + family_add_tinyusb(${TARGET} OPT_MCU_NRF5X) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # group target (not yet supported by clion) - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub - ) - - #---------- Flash ---------- + # Flashing family_flash_jlink(${TARGET}) endfunction() diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index 9674bc759..184dc6062 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -96,30 +96,13 @@ function(family_configure_example TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - #---------- TinyUSB ---------- - # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}-) - add_library(${TARGET}-tinyusb_config INTERFACE) - - target_include_directories(${TARGET}-tinyusb_config INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_MCU=OPT_MCU_STM32G0 - ) - - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # Add TinyUSB + family_add_tinyusb(${TARGET} OPT_MCU_STM32G0) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # group target (not yet supported by clion) - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub - ) - - #---------- Flash ---------- + # Flashing family_flash_stlink(${TARGET}) #family_flash_jlink(${TARGET}) endfunction() diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 1de6fd674..5578a9b6c 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -12,7 +12,7 @@ set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) set(CMSIS_5 ${TOP}/lib/CMSIS_5) # enable LTO -#set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) # toolchain set up set(CMAKE_SYSTEM_PROCESSOR cortex-m4 CACHE INTERNAL "System Processor") @@ -96,30 +96,13 @@ function(family_configure_example TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - #---------- TinyUSB ---------- - # tinyusb target is built for each example since it depends on example's tusb_config.h - set(TINYUSB_TARGET_PREFIX ${TARGET}-) - add_library(${TARGET}-tinyusb_config INTERFACE) - - target_include_directories(${TARGET}-tinyusb_config INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - target_compile_definitions(${TARGET}-tinyusb_config INTERFACE - CFG_TUSB_MCU=OPT_MCU_STM32G4 - ) - - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # Add TinyUSB + family_add_tinyusb(${TARGET} OPT_MCU_STM32G4) # Link dependencies target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) - # group target (not yet supported by clion) - set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config - PROPERTIES FOLDER ${TARGET}_sub - ) - - #---------- Flash ---------- + # Flashing family_flash_stlink(${TARGET}) #family_flash_jlink(${TARGET}) endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 396737ed5..ad9fbc7c0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -96,3 +96,7 @@ endif() target_link_libraries(${TINYUSB_TARGET} PUBLIC ${TINYUSB_CONFIG_TARGET} ) + +# export target name +# set(TINYUSB_TARGET ${TINYUSB_TARGET} PARENT_SCOPE) +# set(TINYUSB_CONFIG_TARGET ${TINYUSB_CONFIG_TARGET} PARENT_SCOPE) diff --git a/tools/build_cmake.py b/tools/build_cmake.py index 88d27dfb8..d85726213 100644 --- a/tools/build_cmake.py +++ b/tools/build_cmake.py @@ -34,13 +34,15 @@ def build_family(family, make_option): for board in all_boards: start_time = time.monotonic() + build_dir = f"cmake-build/cmake-build-{board}" + # Generate build - r = subprocess.run(f"cmake examples -B cmake-build-ci-{board} -G \"Ninja\" -DFAMILY={family} -DBOARD" + r = subprocess.run(f"cmake examples -B {build_dir} -G \"Ninja\" -DFAMILY={family} -DBOARD" f"={board}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # Build if r.returncode == 0: - r = subprocess.run(f"cmake --build cmake-build-ci-{board}", shell=True, stdout=subprocess.PIPE, + r = subprocess.run(f"cmake --build {build_dir}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) duration = time.monotonic() - start_time @@ -71,10 +73,10 @@ if __name__ == '__main__': if make_iar_option not in sys.argv: make_iar_option = '' - # If family are not specified in arguments, build all + # If family are not specified in arguments, build all supported all_families = [] for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name != 'espressif': + if entry.is_dir() and entry.name != 'espressif' and os.path.isfile(entry.path + "/family.cmake"): all_families.append(entry.name) filter_with_input(all_families) all_families.sort() -- cgit v1.3.1 From fcf77914546496d88d5915223095d93bb63c67fe Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Jun 2023 13:27:18 +0700 Subject: add IAR support for G0 with cmake --- examples/device/net_lwip_webserver/CMakeLists.txt | 16 +-- hw/bsp/family_support.cmake | 108 +++++++++++---------- hw/bsp/imxrt/family.cmake | 4 +- hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake | 2 +- hw/bsp/lpc18/boards/mcb1800/board.cmake | 2 +- hw/bsp/lpc18/family.cmake | 2 +- hw/bsp/lpc55/boards/double_m33_express/board.cmake | 2 +- hw/bsp/lpc55/family.cmake | 4 +- hw/bsp/nrf/boards/pca10056/board.cmake | 2 +- hw/bsp/nrf/boards/pca10095/board.cmake | 2 +- hw/bsp/nrf/family.cmake | 4 +- hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.cmake | 8 +- hw/bsp/stm32g0/family.cmake | 86 ++++++++-------- hw/bsp/stm32g4/boards/b_g474e_dpow1/board.cmake | 8 +- hw/bsp/stm32g4/boards/stm32g474nucleo/board.cmake | 8 +- hw/bsp/stm32g4/family.cmake | 4 +- src/CMakeLists.txt | 2 + tools/cmake/cpu/cortex-m0plus.cmake | 12 ++- tools/cmake/toolchain/arm_gcc.cmake | 14 ++- tools/cmake/toolchain/arm_iar.cmake | 34 +++++++ tools/cmake/toolchain/set_flags.cmake | 17 +--- 21 files changed, 196 insertions(+), 145 deletions(-) create mode 100644 tools/cmake/toolchain/arm_iar.cmake (limited to 'src') diff --git a/examples/device/net_lwip_webserver/CMakeLists.txt b/examples/device/net_lwip_webserver/CMakeLists.txt index 5225f7c42..2c21aa52b 100644 --- a/examples/device/net_lwip_webserver/CMakeLists.txt +++ b/examples/device/net_lwip_webserver/CMakeLists.txt @@ -77,12 +77,16 @@ target_sources(${PROJECT} PUBLIC ) # due to warnings from other net source, we need to prevent error from some of the warnings options -target_compile_options(${PROJECT} PUBLIC - -Wno-error=null-dereference - -Wno-error=conversion - -Wno-error=sign-conversion - -Wno-error=sign-compare - ) +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${PROJECT} PUBLIC + -Wno-error=null-dereference + -Wno-error=conversion + -Wno-error=sign-conversion + -Wno-error=sign-compare + ) +elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + +endif () # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index fdc9580ae..e801f0116 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -97,53 +97,6 @@ function(family_initialize_project PROJECT DIR) endfunction() -function(family_add_default_example_warnings TARGET) - target_compile_options(${TARGET} PUBLIC - -Wall - -Wextra - -Werror - -Wfatal-errors - -Wdouble-promotion - -Wfloat-equal - -Wshadow - -Wwrite-strings - -Wsign-compare - -Wmissing-format-attribute - -Wunreachable-code - -Wcast-align - -Wcast-qual - -Wnull-dereference - -Wuninitialized - -Wunused - -Wredundant-decls - #-Wstrict-prototypes - #-Werror-implicit-function-declaration - #-Wundef - ) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0) - target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments") - endif() - - # GCC 10 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0) - target_compile_options(${TARGET} PUBLIC -Wconversion) - endif() - - # GCC 8 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) - target_compile_options(${TARGET} PUBLIC -Wcast-function-type -Wstrict-overflow) - endif() - - # GCC 6 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) - target_compile_options(${TARGET} PUBLIC -Wno-strict-aliasing) - endif() - endif() -endfunction() - - #------------------------------------ # Main target configure #------------------------------------ @@ -155,11 +108,13 @@ function(family_configure_common TARGET) COMMAND ${CMAKE_SIZE} $ ) - # Generate map file - target_link_options(${TARGET} PUBLIC - # link map - "LINKER:-Map=$.map" - ) + if (CMAKE_C_COMPILER_ID STREQUAL "GCC") + # Generate map file + target_link_options(${TARGET} PUBLIC + # link map + "LINKER:-Map=$.map" + ) + endif() endfunction() @@ -198,7 +153,7 @@ function(family_add_freertos TARGET) # freeros config if (NOT TARGET freertos_config) add_library(freertos_config INTERFACE) - target_include_directories(freertos_config SYSTEM INTERFACE + target_include_directories(freertos_config INTERFACE ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${FAMILY}/FreeRTOSConfig ) endif() @@ -223,6 +178,53 @@ function(family_add_freertos TARGET) endfunction() +function(family_add_default_example_warnings TARGET) + target_compile_options(${TARGET} PUBLIC + -Wall + -Wextra + -Werror + -Wfatal-errors + -Wdouble-promotion + -Wfloat-equal + -Wshadow + -Wwrite-strings + -Wsign-compare + -Wmissing-format-attribute + -Wunreachable-code + -Wcast-align + -Wcast-qual + -Wnull-dereference + -Wuninitialized + -Wunused + -Wredundant-decls + #-Wstrict-prototypes + #-Werror-implicit-function-declaration + #-Wundef + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0) + target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments") + endif() + + # GCC 10 + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0) + target_compile_options(${TARGET} PUBLIC -Wconversion) + endif() + + # GCC 8 + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) + target_compile_options(${TARGET} PUBLIC -Wcast-function-type -Wstrict-overflow) + endif() + + # GCC 6 + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + target_compile_options(${TARGET} PUBLIC -Wno-strict-aliasing) + endif() + endif() +endfunction() + + # Add bin/hex output function(family_add_bin_hex TARGET) add_custom_command(TARGET ${TARGET} POST_BUILD diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 3c156285c..b5d47614e 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -53,7 +53,7 @@ if (NOT TARGET ${BOARD_TARGET}) update_board(${BOARD_TARGET}) if (NOT DEFINED LD_FILE_${TOOLCHAIN}) - set(LD_FILE_gcc ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx_flexspi_nor.ld) + set(LD_FILE_GCC ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx_flexspi_nor.ld) endif () if (TOOLCHAIN STREQUAL "gcc") @@ -61,7 +61,7 @@ if (NOT TARGET ${BOARD_TARGET}) ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S ) target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_gcc}" + "LINKER:--script=${LD_FILE_GCC}" # nanolib --specs=nosys.specs --specs=nano.specs diff --git a/hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake b/hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake index b540012a4..00686ca01 100644 --- a/hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake +++ b/hw/bsp/lpc18/boards/lpcxpresso18s37/board.cmake @@ -4,7 +4,7 @@ set(JLINK_DEVICE LPC18S37) set(PYOCD_TARGET LPC18S37) set(NXPLINK_DEVICE LPC18S37:LPCXPRESSO18S37) -set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/lpc1837.ld) +set(LD_FILE_GCC ${CMAKE_CURRENT_LIST_DIR}/lpc1837.ld) function(update_board TARGET) # nothing to do diff --git a/hw/bsp/lpc18/boards/mcb1800/board.cmake b/hw/bsp/lpc18/boards/mcb1800/board.cmake index 1efeafd12..cfc2739e3 100644 --- a/hw/bsp/lpc18/boards/mcb1800/board.cmake +++ b/hw/bsp/lpc18/boards/mcb1800/board.cmake @@ -4,7 +4,7 @@ set(JLINK_DEVICE LPC1857) set(PYOCD_TARGET LPC1857) set(NXPLINK_DEVICE LPC1857:MCB1857) -set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/lpc1857.ld) +set(LD_FILE_GCC ${CMAKE_CURRENT_LIST_DIR}/lpc1857.ld) function(update_board TARGET) # nothing to do diff --git a/hw/bsp/lpc18/family.cmake b/hw/bsp/lpc18/family.cmake index a133e7217..38b0f61fc 100644 --- a/hw/bsp/lpc18/family.cmake +++ b/hw/bsp/lpc18/family.cmake @@ -48,7 +48,7 @@ if (NOT TARGET ${BOARD_TARGET}) if (TOOLCHAIN STREQUAL "gcc") target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_gcc}" + "LINKER:--script=${LD_FILE_GCC}" # nanolib --specs=nosys.specs --specs=nano.specs diff --git a/hw/bsp/lpc55/boards/double_m33_express/board.cmake b/hw/bsp/lpc55/boards/double_m33_express/board.cmake index 7c46c075e..62b0993dc 100644 --- a/hw/bsp/lpc55/boards/double_m33_express/board.cmake +++ b/hw/bsp/lpc55/boards/double_m33_express/board.cmake @@ -5,7 +5,7 @@ set(JLINK_DEVICE LPC55S69) set(PYOCD_TARGET LPC55S69) set(NXPLINK_DEVICE LPC55S69:LPCXpresso55S69) -set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/LPC55S69_cm33_core0_uf2.ld) +set(LD_FILE_GCC ${CMAKE_CURRENT_LIST_DIR}/LPC55S69_cm33_core0_uf2.ld) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index 25eed48de..967ed3fa6 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -65,7 +65,7 @@ if (NOT TARGET ${BOARD_TARGET}) update_board(${BOARD_TARGET}) if (NOT DEFINED LD_FILE_${TOOLCHAIN}) - set(LD_FILE_gcc ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) + set(LD_FILE_GCC ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) endif () if (TOOLCHAIN STREQUAL "gcc") @@ -74,7 +74,7 @@ if (NOT TARGET ${BOARD_TARGET}) ) target_link_options(${BOARD_TARGET} PUBLIC # linker file - "LINKER:--script=${LD_FILE_gcc}" + "LINKER:--script=${LD_FILE_GCC}" # nanolib --specs=nosys.specs --specs=nano.specs diff --git a/hw/bsp/nrf/boards/pca10056/board.cmake b/hw/bsp/nrf/boards/pca10056/board.cmake index cc8ef2fcb..3137c4fcd 100644 --- a/hw/bsp/nrf/boards/pca10056/board.cmake +++ b/hw/bsp/nrf/boards/pca10056/board.cmake @@ -1,5 +1,5 @@ set(MCU_VARIANT nrf52840) -set(LD_FILE_gcc ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) +set(LD_FILE_GCC ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake index e90d76e91..a0562c738 100644 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ b/hw/bsp/nrf/boards/pca10095/board.cmake @@ -1,5 +1,5 @@ set(MCU_VARIANT nrf5340_application) -set(LD_FILE_gcc ${NRFX_DIR}/mdk/nrf5340_xxaa_application.ld) +set(LD_FILE_GCC ${NRFX_DIR}/mdk/nrf5340_xxaa_application.ld) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 2c5d7a431..e94aeb9bd 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -55,7 +55,7 @@ if (NOT TARGET ${BOARD_TARGET}) update_board(${BOARD_TARGET}) if (NOT DEFINED LD_FILE_${TOOLCHAIN}) - set(LD_FILE_gcc ${NRFX_DIR}/mdk/${MCU_VARIANT}_xxaa.ld) + set(LD_FILE_GCC ${NRFX_DIR}/mdk/${MCU_VARIANT}_xxaa.ld) endif () if (TOOLCHAIN STREQUAL "gcc") @@ -64,7 +64,7 @@ if (NOT TARGET ${BOARD_TARGET}) ) target_link_options(${BOARD_TARGET} PUBLIC # linker file - "LINKER:--script=${LD_FILE_gcc}" + "LINKER:--script=${LD_FILE_GCC}" -L${NRFX_DIR}/mdk # nanolib --specs=nosys.specs diff --git a/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.cmake b/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.cmake index c9f2a9c8e..145490921 100644 --- a/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.cmake +++ b/hw/bsp/stm32g0/boards/stm32g0b1nucleo/board.cmake @@ -1,11 +1,11 @@ #set(MCU_VARIANT MIMXRT1011) set(JLINK_DEVICE STM32G0B1RE) -set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/STM32G0B1RETx_FLASH.ld) -set(LD_FILE_iar ${ST_CMSIS}/Source/Templates/iar/linker/stm32g0b1xx_flash.icf) +set(LD_FILE_GCC ${CMAKE_CURRENT_LIST_DIR}/STM32G0B1RETx_FLASH.ld) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/stm32g0b1xx_flash.icf) -set(STARTUP_FILE_gcc ${ST_CMSIS}/Source/Templates/gcc/startup_stm32g0b1xx.s) -set(STARTUP_FILE_iar ${ST_CMSIS}/Source/Templates/iar/startup_stm32g0b1xx.s) +set(STARTUP_FILE_GCC ${ST_CMSIS}/Source/Templates/gcc/startup_stm32g0b1xx.s) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_stm32g0b1xx.s) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index 184dc6062..d77b3c102 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -28,50 +28,49 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -set(BOARD_TARGET board_${BOARD}) -if (NOT TARGET ${BOARD_TARGET}) - add_library(${BOARD_TARGET} STATIC - ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMAKE_CURRENT_LIST_DIR} - ${CMSIS_5}/CMSIS/Core/Include - ${ST_CMSIS}/Include - ${ST_HAL_DRIVER}/Inc - ) - target_compile_options(${BOARD_TARGET} PUBLIC - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - ) - update_board(${BOARD_TARGET}) - - target_sources(${BOARD_TARGET} PUBLIC - ${STARTUP_FILE_${TOOLCHAIN}} - ) - - if (TOOLCHAIN STREQUAL "gcc") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_gcc}" - -nostartfiles - # nanolib - --specs=nosys.specs - --specs=nano.specs +function(add_board_target TARGET) + if (NOT TARGET ${TARGET}) + add_library(${TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + target_compile_options(${TARGET} PUBLIC ) - else () - # TODO support IAR - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_iar}" + target_compile_definitions(${TARGET} PUBLIC ) + + update_board(${TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GCC") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GCC}" + -nostartfiles + # nanolib + --specs=nosys.specs + --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + # TODO support IAR + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () endif () -endif () # BOARD_TARGET +endfunction() #------------------------------------ @@ -80,6 +79,9 @@ endif () # BOARD_TARGET function(family_configure_example TARGET) family_configure_common(${TARGET}) + # Board target + add_board_target(board_${BOARD}) + #---------- Port Specific ---------- # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC @@ -100,7 +102,7 @@ function(family_configure_example TARGET) family_add_tinyusb(${TARGET} OPT_MCU_STM32G0) # Link dependencies - target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb) + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) # Flashing family_flash_stlink(${TARGET}) diff --git a/hw/bsp/stm32g4/boards/b_g474e_dpow1/board.cmake b/hw/bsp/stm32g4/boards/b_g474e_dpow1/board.cmake index 4e8f3f059..3a4849ef6 100644 --- a/hw/bsp/stm32g4/boards/b_g474e_dpow1/board.cmake +++ b/hw/bsp/stm32g4/boards/b_g474e_dpow1/board.cmake @@ -1,11 +1,11 @@ set(MCU_VARIANT stm32g474xx) set(JLINK_DEVICE stm32g474re) -set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/STM32G474RETx_FLASH.ld) -set(LD_FILE_iar ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(LD_FILE_GCC ${CMAKE_CURRENT_LIST_DIR}/STM32G474RETx_FLASH.ld) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) -set(STARTUP_FILE_gcc ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) -set(STARTUP_FILE_iar ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_GCC ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/stm32g4/boards/stm32g474nucleo/board.cmake b/hw/bsp/stm32g4/boards/stm32g474nucleo/board.cmake index 8cc633449..f13f1fc28 100644 --- a/hw/bsp/stm32g4/boards/stm32g474nucleo/board.cmake +++ b/hw/bsp/stm32g4/boards/stm32g474nucleo/board.cmake @@ -1,11 +1,11 @@ set(MCU_VARIANT stm32g474xx) set(JLINK_DEVICE stm32g474re) -set(LD_FILE_gcc ${CMAKE_CURRENT_LIST_DIR}/STM32G474RETx_FLASH.ld) -set(LD_FILE_iar ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(LD_FILE_GCC ${CMAKE_CURRENT_LIST_DIR}/STM32G474RETx_FLASH.ld) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) -set(STARTUP_FILE_gcc ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) -set(STARTUP_FILE_iar ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_GCC ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 5578a9b6c..c87486677 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -59,7 +59,7 @@ if (NOT TARGET ${BOARD_TARGET}) if (TOOLCHAIN STREQUAL "gcc") target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_gcc}" + "LINKER:--script=${LD_FILE_GCC}" -nostartfiles # nanolib --specs=nosys.specs @@ -68,7 +68,7 @@ if (NOT TARGET ${BOARD_TARGET}) else () # TODO support IAR target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_iar}" + "LINKER:--config=${LD_FILE_IAR}" ) endif () endif () # BOARD_TARGET diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ad9fbc7c0..09f41c9ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,6 +65,8 @@ function(add_tinyusb TARGET) -Wreturn-type -Wredundant-decls ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + endif () endfunction() diff --git a/tools/cmake/cpu/cortex-m0plus.cmake b/tools/cmake/cpu/cortex-m0plus.cmake index 1e316ccfc..bc2257048 100644 --- a/tools/cmake/cpu/cortex-m0plus.cmake +++ b/tools/cmake/cpu/cortex-m0plus.cmake @@ -1,11 +1,17 @@ if (TOOLCHAIN STREQUAL "gcc") - list(APPEND TOOLCHAIN_COMMON_FLAGS + set(TOOLCHAIN_COMMON_FLAGS -mthumb -mcpu=cortex-m0plus -mfloat-abi=soft ) set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") -else () - # TODO support IAR + +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m0 + ) + + set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "") + endif () diff --git a/tools/cmake/toolchain/arm_gcc.cmake b/tools/cmake/toolchain/arm_gcc.cmake index c7f12f43a..6dd1e7002 100644 --- a/tools/cmake/toolchain/arm_gcc.cmake +++ b/tools/cmake/toolchain/arm_gcc.cmake @@ -1,8 +1,8 @@ set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") set(CMAKE_C_COMPILER "arm-none-eabi-gcc") set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") +set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "") set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "") @@ -29,13 +29,13 @@ list(APPEND TOOLCHAIN_COMMON_FLAGS -fno-strict-aliasing ) -list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS +set(TOOLCHAIN_EXE_LINKER_FLAGS -Wl,--print-memory-usage -Wl,--gc-sections -Wl,--cref ) -list(APPEND TOOLCHAIN_WARNING_FLAGS +set(TOOLCHAIN_WARNING_FLAGS -Wall -Wextra -Werror @@ -62,3 +62,11 @@ list(APPEND TOOLCHAIN_WARNING_FLAGS ) include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) + +# try_compile is cmake test compiling its own example, +# pass -nostdlib to skip stdlib linking +get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) +if (IS_IN_TRY_COMPILE) + set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") +endif () diff --git a/tools/cmake/toolchain/arm_iar.cmake b/tools/cmake/toolchain/arm_iar.cmake new file mode 100644 index 000000000..dfbe55e0d --- /dev/null +++ b/tools/cmake/toolchain/arm_iar.cmake @@ -0,0 +1,34 @@ +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER "iccarm") +set(CMAKE_CXX_COMPILER "iccarm") +set(CMAKE_ASM_COMPILER "iasmarm") + +set(CMAKE_SIZE "size" CACHE FILEPATH "") +set(CMAKE_OBJCOPY "ielftool" CACHE FILEPATH "") +set(CMAKE_OBJDUMP "iefdumparm" CACHE FILEPATH "") + +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) + +# Look for includes and libraries only in the target system prefix. +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# pass TOOLCHAIN_CPU to +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) + +include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) + +# enable all possible warnings for building examples +list(APPEND TOOLCHAIN_COMMON_FLAGS + ) + +list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS + ) + +list(APPEND TOOLCHAIN_WARNING_FLAGS + ) + +include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) diff --git a/tools/cmake/toolchain/set_flags.cmake b/tools/cmake/toolchain/set_flags.cmake index 6f74fe673..44930ef4d 100644 --- a/tools/cmake/toolchain/set_flags.cmake +++ b/tools/cmake/toolchain/set_flags.cmake @@ -1,9 +1,10 @@ include(CMakePrintHelpers) + +# join the toolchain flags into a single string +list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS) + foreach (LANG IN ITEMS C CXX ASM) - # join the toolchain flags into a single string - list(APPEND TOOLCHAIN_${LANG}_FLAGS ${TOOLCHAIN_COMMON_FLAGS}) - list(JOIN TOOLCHAIN_${LANG}_FLAGS " " TOOLCHAIN_${LANG}_FLAGS) - set(CMAKE_${LANG}_FLAGS_INIT "${TOOLCHAIN_${LANG}_FLAGS}") + set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS}) #cmake_print_variables(CMAKE_${LANG}_FLAGS_INIT) @@ -14,11 +15,3 @@ endforeach () # Linker list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) - -# try_compile is cmake test compiling its own example, -# pass -nostdlib to skip stdlib linking -get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) -if (IS_IN_TRY_COMPILE) - set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") - set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") -endif () -- cgit v1.3.1