From fb631c9a402478702fcce7168a5f1cc3b231e959 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 24 Nov 2025 00:26:05 +0100 Subject: hcd: add fsdev driver Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 20 +- src/portable/st/stm32_fsdev/fsdev_at32.h | 16 +- src/portable/st/stm32_fsdev/fsdev_ch32.h | 9 +- src/portable/st/stm32_fsdev/fsdev_stm32.h | 15 +- src/portable/st/stm32_fsdev/fsdev_type.h | 41 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 833 ++++++++++++++++++++++++++ 6 files changed, 911 insertions(+), 23 deletions(-) create mode 100644 src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c (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 381aa0b40..db1a5784a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -123,8 +123,6 @@ #error "Unknown USB IP" #endif -#include "fsdev_type.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -848,6 +846,24 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_write(ep_idx, ep_reg, true); } +void dcd_int_enable(uint8_t rhport) { + fsdev_int_enable(rhport); +} + +void dcd_int_disable(uint8_t rhport) { + fsdev_int_disable(rhport); +} + +#if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) +void dcd_connect(uint8_t rhport) { + fsdev_connect(rhport); +} + +void dcd_disconnect(uint8_t rhport) { + fsdev_disconnect(rhport); +} +#endif + //--------------------------------------------------------------------+ // PMA read/write //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index deb1de2a8..03490ee24 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -168,7 +168,7 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void dcd_int_enable(uint8_t rhport) { +void fsdev_int_enable(uint8_t rhport) { (void)rhport; #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) // AT32F403A/407 devices allow to remap the USB interrupt vectors from @@ -187,7 +187,7 @@ void dcd_int_enable(uint8_t rhport) { } } -void dcd_int_disable(uint8_t rhport) { +void fsdev_int_disable(uint8_t rhport) { (void)rhport; #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) // AT32F403A/407 devices allow to remap the USB interrupt vectors from @@ -206,20 +206,20 @@ void dcd_int_disable(uint8_t rhport) { } } -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void) rhport; /* disable usb phy */ - FSDEV_REG->CNTR |= USB_CNTR_PDWN; + *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN; /* D+ 1.5k pull-up disable, USB->cfg_bit.puo = TRUE; */ - *(uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); + *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void) rhport; /* enable usb phy */ - FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN; /* Dp 1.5k pull-up enable, USB->cfg_bit.puo = 0; */ - *(uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1); + *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1); } #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index ceebb6dab..547f3bd1b 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -168,6 +168,7 @@ #define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ #define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) +#include "fsdev_type.h" //--------------------------------------------------------------------+ // @@ -184,26 +185,26 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void dcd_int_enable(uint8_t rhport) { +void fsdev_int_enable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_EnableIRQ(fsdev_irq[i]); } } -void dcd_int_disable(uint8_t rhport) { +void fsdev_int_disable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_DisableIRQ(fsdev_irq[i]); } } -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN; } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; } diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 30ffadc35..d47d23f14 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -321,6 +321,8 @@ #define FSDEV_USE_SBUF_ISO 0 #endif +#include "fsdev_type.h" + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -372,7 +374,7 @@ static const IRQn_Type fsdev_irq[] = { }; enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; -void dcd_int_enable(uint8_t rhport) { +void fsdev_int_enable(uint8_t rhport) { (void)rhport; // forces write to RAM before allowing ISR to execute @@ -395,7 +397,7 @@ void dcd_int_enable(uint8_t rhport) { } } -void dcd_int_disable(uint8_t rhport) { +void fsdev_int_disable(uint8_t rhport) { (void)rhport; #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP) @@ -420,28 +422,27 @@ void dcd_int_disable(uint8_t rhport) { // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. #if defined(USB_BCDR_DPPU) -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void)rhport; USB->BCDR &= ~(USB_BCDR_DPPU); } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void)rhport; USB->BCDR |= USB_BCDR_DPPU; } #elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 -void dcd_disconnect(uint8_t rhport) { +void fsdev_disconnect(uint8_t rhport) { (void)rhport; SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); } -void dcd_connect(uint8_t rhport) { +void fsdev_connect(uint8_t rhport) { (void)rhport; SYSCFG->PMC |= SYSCFG_PMC_USB_PU; } #endif - #endif /* TUSB_FSDEV_STM32_H */ diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index cf36576bb..2b340d64a 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -174,6 +174,14 @@ typedef enum { #define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) #define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) + +void fsdev_int_enable(uint8_t rhport); +void fsdev_int_disable(uint8_t rhport); +void fsdev_connect(uint8_t rhport); +void fsdev_disconnect(uint8_t rhport); + //--------------------------------------------------------------------+ // Endpoint Helper // - CTR is write 0 to clear @@ -186,13 +194,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { if (need_exclusive) { - dcd_int_disable(0); + fsdev_int_disable(0); } FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; if (need_exclusive) { - dcd_int_enable(0); + fsdev_int_enable(0); } } @@ -216,6 +224,35 @@ TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; } +//--------------------------------------------------------------------+ +// Channel Helper +// - Direction is opposite to endpoint direction +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ch_read(uint32_t ch_id) { + return ep_read(ch_id); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value, bool need_exclusive) { + ep_write(ch_id, value, need_exclusive); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ch_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + ep_write(ch_id, reg, false); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + //--------------------------------------------------------------------+ // BTable Helper //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c new file mode 100644 index 000000000..1c08f64d6 --- /dev/null +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -0,0 +1,833 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 HiFiPhile (Zixun LI) + * + * 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. + */ + +/********************************************** + * This driver provides USB Host controller support for STM32 MCUs with "USB A"/"PCD"/"HCD" peripheral. + * This covers these MCU families: + * + * C0 2048 byte buffer; 32-bit bus; host mode + * G0 2048 byte buffer; 32-bit bus; host mode + * H5 2048 byte buffer; 32-bit bus; host mode + * U535, U545 2048 byte buffer; 32-bit bus; host mode + * + */ + +#include "tusb_option.h" + +#if CFG_TUH_ENABLED && defined(TUP_USBIP_FSDEV) && \ + TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32G0, OPT_MCU_STM32H5, OPT_MCU_STM32U5) + +#include "host/hcd.h" +#include "host/usbh.h" + +#if defined(TUP_USBIP_FSDEV_STM32) + #include "fsdev_stm32.h" +#else + #error "Unknown USB IP" +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +// Debug level for FSDEV +#define FSDEV_DEBUG 1 + +// Max number of endpoints application can open, can be larger than FSDEV_EP_COUNT +#ifndef CFG_TUH_FSDEV_ENDPOINT_MAX + #define CFG_TUH_FSDEV_ENDPOINT_MAX 16u +#endif + +TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); + +enum { + HCD_XFER_ERROR_MAX = 3 +}; + +// Host driver struct for each opened endpoint +typedef struct { + uint8_t *buffer; + uint16_t buflen; + uint16_t max_packet_size; + uint8_t dev_addr; + uint8_t ep_addr; + uint8_t ep_type; + uint8_t interval; + bool low_speed; + bool allocated; + bool next_setup; +} hcd_endpoint_t; + +// Additional info for each channel when it is active +typedef struct { + hcd_endpoint_t* edpt[2]; // OUT/IN + uint16_t queued_len[2]; + uint8_t dev_addr; + uint8_t ep_num; + uint8_t ep_type; + bool allocated[2]; + uint8_t retry[2]; + uint8_t result; +} hcd_xfer_t; + +// Root hub port state +static struct { + bool connected; +} _hcd_port; + +typedef struct { + hcd_xfer_t xfer[FSDEV_EP_COUNT]; + hcd_endpoint_t edpt[CFG_TUH_FSDEV_ENDPOINT_MAX]; +} hcd_data_t; + +hcd_data_t _hcd_data; + +//--------------------------------------------------------------------+ +// Prototypes +//--------------------------------------------------------------------+ + +static uint8_t endpoint_alloc(void); +static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr); +static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len); +static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type); +static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); +static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); +static bool edpt_xfer_kickoff(uint8_t ep_id); +static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); +static void edpoint_close(uint8_t ep_id); +static void port_status_handler(uint8_t rhport, bool in_isr); +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { + edpt->allocated = false; +} + +static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) { + xfer->allocated[dir] = false; +} + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// Optional HCD configuration, called by tuh_configure() +bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { + (void) rhport; + (void) cfg_id; + (void) cfg_param; + return false; +} + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { + (void) rh_init; + + // Follow the RM mentions to use a special ordering of PDWN and FRES + for (volatile uint32_t i = 0; i < 200; i++) { + asm("NOP"); + } + + // Perform USB peripheral reset + FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + for (volatile uint32_t i = 0; i < 200; i++) { + asm("NOP"); + } + + FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + + // Wait startup time + for (volatile uint32_t i = 0; i < 200; i++) { + asm("NOP"); + } + + FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode + +#if !defined(FSDEV_BUS_32BIT) + // BTABLE register does not exist on 32-bit bus devices + FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; +#endif + + FSDEV_REG->ISTR = 0; // Clear pending interrupts + + // Reset channels to disabled + for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { + ch_write(i, 0u, false); + } + + tu_memclr(&_hcd_data, sizeof(_hcd_data)); + + // Enable interrupts for host mode + FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | + USB_CNTR_WKUPM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM; + + // Initialize port state + _hcd_port.connected = false; + + fsdev_connect(rhport); + + return true; +} + +static void port_status_handler(uint8_t rhport, bool in_isr) { + uint32_t const fnr_reg = FSDEV_REG->FNR; + uint32_t const istr_reg = FSDEV_REG->ISTR; + // SE0 detected USB Disconnected state + if ((fnr_reg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U) { + _hcd_port.connected = false; + hcd_event_device_remove(rhport, in_isr); + return; + } + + if (!_hcd_port.connected) { + // J-state or K-state detected & LastState=Disconnected + if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { + _hcd_port.connected = true; + hcd_event_device_attach(rhport, in_isr); + } + } else { + // J-state or K-state detected & lastState=Connected: a Missed disconnection is detected + if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { + _hcd_port.connected = false; + hcd_event_device_remove(rhport, in_isr); + } + } +} + +// Handle CTR interrupt for the TX/OUT direction +static void handle_ctr_tx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + uint8_t ep_id = endpoint_find(daddr, ep_num); + TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_OUT],); + + // Manage Correct Transaction + if ((ch_reg & USB_CH_ERRTX) == 0U) { + // Acked + if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { + if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { + uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); + hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + btable_set_count(ch_id, BTABLE_BUF_TX, len); + xfer->queued_len[TUSB_DIR_OUT] += len; + + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits + ch_write(ch_id, ch_reg, false); + } else { + channel_dealloc(xfer, TUSB_DIR_OUT); + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); + } + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) { + // NAKed + if (edpt->ep_type != TUSB_XFER_INTERRUPT) { + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ch_write(ch_id, ch_reg, false); + } + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) { + // STALLed + channel_dealloc(xfer, TUSB_DIR_OUT); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + ch_write(ch_id, ch_reg, false); + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_STALLED, true); + } + } else { + // Error + TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", + ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_OUT], edpt->buflen); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits + ch_reg &=~USB_CH_ERRTX; + if (xfer->retry[TUSB_DIR_OUT] < HCD_XFER_ERROR_MAX) { + // Retry + xfer->retry[TUSB_DIR_OUT]++; + } else { + // Failed after retries + channel_dealloc(xfer, TUSB_DIR_OUT); + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_FAILED, true); + } + ch_write(ch_id, ch_reg, false); + } +} + +// Handle CTR interrupt for the RX/IN direction +static void handle_ctr_rx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + uint8_t ep_id = endpoint_find(daddr, ep_num | TUSB_DIR_IN_MASK); + TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_IN],); + + // Manage Correct Transaction + if ((ch_reg & USB_CH_ERRRX) == 0U) { + // Acked + if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) { + uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); + + hcd_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); + xfer->queued_len[TUSB_DIR_IN] += rx_count; + + if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + // all bytes received or short packet + channel_dealloc(xfer, TUSB_DIR_IN); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); + } else { + // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always + uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); + ch_write(ch_id, ch_reg, false); + } + } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) { + // NAKed + if (edpt->ep_type != TUSB_XFER_INTERRUPT) { + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); + ch_write(ch_id, ch_reg, false); + } + } else { + // STALLed + channel_dealloc(xfer, TUSB_DIR_IN); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ch_write(ch_id, ch_reg, false); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_STALLED, true); + } + } else { + // Error + TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", + ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_IN], edpt->buflen); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits + ch_reg &=~USB_CH_ERRRX; + if (xfer->retry[TUSB_DIR_IN] < HCD_XFER_ERROR_MAX) { + // Retry + xfer->retry[TUSB_DIR_IN]++; + } else { + // Failed after retries + channel_dealloc(xfer, TUSB_DIR_IN); + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_FAILED, true); + } + ch_write(ch_id, ch_reg, false); + } +} + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport, bool in_isr) { + uint32_t int_status = FSDEV_REG->ISTR; + + /* Port Change Detected (Connection/Disconnection) */ + if (int_status & USB_ISTR_DCON) { + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_DCON; + port_status_handler(rhport, in_isr); + } + + // Handle transfer complete (CTR) + while (FSDEV_REG->ISTR & USB_ISTR_CTR) { + uint32_t const ch_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + uint32_t const ch_reg = ch_read(ch_id); + + if (ch_reg & USB_EP_CTR_RX) { + #ifdef FSDEV_BUS_32BIT + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf + * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code + * also takes time, so we'll wait 60 cycles (count = 20). + * - Since Low Speed mode is not supported/popular, we will ignore it for now. + * + * Note: this errata may also apply to G0, U5, H5 etc. + */ + volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + #endif + + ch_write_clear_ctr(ch_id, TUSB_DIR_IN); + handle_ctr_rx(ch_id); + } + + if (ch_reg & USB_EP_CTR_TX) { + ch_write_clear_ctr(ch_id, TUSB_DIR_OUT); + handle_ctr_tx(ch_id); + } + } + + if (int_status & USB_ISTR_ERR) { + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ERR; + // TODO: Handle error + } + + if (int_status & USB_ISTR_PMAOVR) { + TU_BREAKPOINT(); + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; + } +} + +// Enable USB interrupt +void hcd_int_enable(uint8_t rhport) { + fsdev_int_enable(rhport); +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) { + fsdev_int_disable(rhport); +} + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + return FSDEV_REG->FNR & USB_FNR_FN; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; + return _hcd_port.connected; +} + +// Reset USB bus on the port +void hcd_port_reset(uint8_t rhport) { + (void) rhport; + FSDEV_REG->CNTR |= USB_CNTR_FRES; +} + +// Complete bus reset sequence +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; + FSDEV_REG->CNTR &= ~USB_CNTR_FRES; +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + if ((FSDEV_REG->ISTR & USB_ISTR_LS_DCONN) != 0U) { + return TUSB_SPEED_LOW; + } else { + return TUSB_SPEED_FULL; + } +} + +// HCD closes all opened endpoints belonging to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + + // Close all endpoints for this device + for(uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + if (edpt->allocated && edpt->dev_addr == dev_addr) { + edpoint_close(i); + } + } + +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc) { + (void) rhport; + + uint8_t const ep_addr = ep_desc->bEndpointAddress; + uint16_t const packet_size = tu_edpt_packet_size(ep_desc); + uint8_t const ep_type = ep_desc->bmAttributes.xfer; + + uint8_t const ep_id = endpoint_alloc(); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + edpt->dev_addr = dev_addr; + edpt->ep_addr = ep_addr; + edpt->ep_type = ep_type; + edpt->max_packet_size = packet_size; + edpt->interval = ep_desc->bInterval; + edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW); + + // EP0 is bi-directional, so we need to open both OUT and IN channels + if (ep_addr == 0) { + uint8_t const ep_id_in = endpoint_alloc(); + TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + + _hcd_data.edpt[ep_id_in] = *edpt; // copy from OUT endpoint + _hcd_data.edpt[ep_id_in].ep_addr = 0 | TUSB_DIR_IN_MASK; + } + + return true; +} + +bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + + uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + edpoint_close(ep_id); + + if (ep_addr == 0) { + uint8_t const ep_id_in = endpoint_find(dev_addr, 0 | TUSB_DIR_IN_MASK); + TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + + edpoint_close(ep_id_in); + } + + return false; +} + +// Submit a transfer +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { + (void) rhport; + + TU_LOG(FSDEV_DEBUG, "hcd_edpt_xfer addr=%u ep=0x%02X len=%u\r\n", dev_addr, ep_addr, buflen); + + uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + + edpt->buffer = buffer; + edpt->buflen = buflen; + + return edpt_xfer_kickoff(ep_id); +} + +// Abort a queued transfer +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + + uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + + if (xfer->allocated[dir] && + xfer->dev_addr == dev_addr && + xfer->ep_num == tu_edpt_number(ep_addr)) { + + channel_dealloc(xfer, dir); + + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); // will change Status, reserved other toggle bits + ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); + ch_write(i, ch_reg, true); + + } + } + + return true; +} + +// Submit a special transfer to send 8-byte Setup Packet +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; + + uint8_t const ep_id = endpoint_find(dev_addr, 0); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + edpt->next_setup = true; + + return hcd_edpt_xfer(rhport, dev_addr, 0, (uint8_t*)(uintptr_t) setup_packet, 8); +} + +// Clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return true; +} + +//--------------------------------------------------------------------+ +// Helper Functions +//--------------------------------------------------------------------+ + +static uint8_t endpoint_alloc(void) { + for (uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + if (!edpt->allocated) { + edpt->allocated = true; + return i; + } + } + return TUSB_INDEX_INVALID_8; +} + +static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) { + for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + if (edpt->allocated && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { + return i; + } + } + return TUSB_INDEX_INVALID_8; +} + +// close an opened endpoint +static void edpoint_close(uint8_t ep_id) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + endpoint_dealloc(edpt); + + // disable active channel belong to this endpoint + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + + if (xfer->allocated[TUSB_DIR_OUT] && xfer->edpt[TUSB_DIR_OUT] == edpt) { + channel_dealloc(xfer, TUSB_DIR_OUT); + + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + ch_write(i, ch_reg, true); + + } + if (xfer->allocated[TUSB_DIR_IN] && xfer->edpt[TUSB_DIR_IN] == edpt) { + channel_dealloc(xfer, TUSB_DIR_IN); + + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ch_write(i, ch_reg, true); + + } + } +} + +// Allocate PMA buffer +static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) { + (void) len; + // Simple static allocation as we are unlikely to handle ISO endpoints in host mode + // We just give each channel a buffer of max packet size (64 bytes) + + uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; + addr += channel * 64 * 2 + (dir == TUSB_DIR_IN ? 64 : 0); + + TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF); + + return addr; +} + +// Allocate hardware channel +static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + + // Find channel allocate for same ep_num but other direction + tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + if (!_hcd_data.xfer[i].allocated[dir] && + _hcd_data.xfer[i].allocated[other_dir] && + _hcd_data.xfer[i].dev_addr == dev_addr && + _hcd_data.xfer[i].ep_num == ep_num && + _hcd_data.xfer[i].ep_type == ep_type) { + _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].queued_len[dir] = 0; + _hcd_data.xfer[i].retry[dir] = 0; + return i; + } + } + + // Find free channel + for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { + if (!_hcd_data.xfer[i].allocated[0] && !_hcd_data.xfer[i].allocated[1]) { + _hcd_data.xfer[i].dev_addr = dev_addr; + _hcd_data.xfer[i].ep_num = ep_num; + _hcd_data.xfer[i].ep_type = ep_type; + _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].queued_len[dir] = 0; + _hcd_data.xfer[i].retry[dir] = 0; + return i; + } + } + + // Allocation failed + return TUSB_INDEX_INVALID_8; +} + +// kick-off transfer with an endpoint +static bool edpt_xfer_kickoff(uint8_t ep_id) { + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + uint8_t ch_id = channel_alloc(edpt->dev_addr, edpt->ep_addr, edpt->ep_type); + TU_ASSERT(ch_id != TUSB_INDEX_INVALID_8); // all channel are in used + + tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); + + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + xfer->edpt[dir] = edpt; + + return channel_xfer_start(ch_id, dir); +} + +static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + hcd_endpoint_t* edpt = xfer->edpt[dir]; + + uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK; + ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos | + USB_EP_CTR_TX | USB_EP_CTR_RX; + + // Set type + switch (edpt->ep_type) { + case TUSB_XFER_BULK: + ch_reg |= USB_EP_BULK; + break; + case TUSB_XFER_INTERRUPT: + ch_reg |= USB_EP_INTERRUPT; + break; + + case TUSB_XFER_CONTROL: + ch_reg |= USB_EP_CONTROL; + break; + + default: + // Note: ISO endpoint is unsupported + TU_ASSERT(false); + } + + /* Create a packet memory buffer area. */ + uint16_t pma_addr = hcd_pma_alloc(ch_id, dir, edpt->max_packet_size); + btable_set_addr(ch_id, dir == TUSB_DIR_OUT ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); + + if (dir == TUSB_DIR_OUT) { + uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + + hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + btable_set_count(ch_id, BTABLE_BUF_TX, len); + + xfer->queued_len[TUSB_DIR_OUT] += len; + if (edpt->next_setup) { + // Setup packet uses IN token + edpt->next_setup = false; + ch_reg |= USB_EP_SETUP; + } + + ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits + + } else { + btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); + ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits + } + + ch_write(ch_id, ch_reg, true); + + return true; +} + +//--------------------------------------------------------------------+ +// PMA read/write +//--------------------------------------------------------------------+ + +// Write to packet memory area (PMA) from user memory +static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_write = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(dst); + const uint8_t *src8 = src; + + while (n_write--) { + pma_buf->value = fsdevbus_unaligned_read(src8); + src8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // Handle odd bytes + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = 0; + for (uint16_t i = 0; i < odd; i++) { + temp |= *src8++ << (i * 8); + } + pma_buf->value = temp; + } + + return true; +} + +// Read from packet memory area (PMA) to user memory +static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_read = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(src); + uint8_t *dst8 = (uint8_t *)dst; + + while (n_read--) { + fsdevbus_unaligned_write(dst8, (fsdev_bus_t) pma_buf->value); + dst8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // Handle odd bytes + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = pma_buf->value; + while (odd--) { + *dst8++ = (uint8_t)(temp & 0xfful); + temp >>= 8; + } + } + + return true; +} + +#endif -- cgit v1.3.1 From 03bd8c26d6b72b5e53c0d4b9787a6396ee295927 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 24 Nov 2025 21:03:04 +0100 Subject: fsdev: reorganize functions Signed-off-by: HiFiPhile --- examples/host/bare_api/only.txt | 1 + examples/host/cdc_msc_hid/only.txt | 1 + examples/host/cdc_msc_hid_freertos/only.txt | 1 + hw/bsp/at32f403a_407/family.cmake | 1 + hw/bsp/at32f403a_407/family.mk | 1 + hw/bsp/at32f413/family.cmake | 1 + hw/bsp/at32f413/family.mk | 1 + hw/bsp/ch32v20x/family.cmake | 1 + hw/bsp/ch32v20x/family.mk | 1 + hw/bsp/stm32c0/family.cmake | 1 + hw/bsp/stm32c0/family.mk | 1 + hw/bsp/stm32f0/family.cmake | 1 + hw/bsp/stm32f0/family.mk | 1 + hw/bsp/stm32f1/family.cmake | 1 + hw/bsp/stm32f1/family.mk | 1 + hw/bsp/stm32f3/family.cmake | 1 + hw/bsp/stm32f3/family.mk | 1 + hw/bsp/stm32g0/family.cmake | 1 + hw/bsp/stm32g0/family.mk | 2 + hw/bsp/stm32g4/family.cmake | 1 + hw/bsp/stm32g4/family.mk | 1 + hw/bsp/stm32h5/family.cmake | 1 + hw/bsp/stm32h5/family.mk | 2 + hw/bsp/stm32l0/family.cmake | 1 + hw/bsp/stm32l0/family.mk | 1 + hw/bsp/stm32l4/family.cmake | 1 + hw/bsp/stm32l4/family.mk | 1 + hw/bsp/stm32u0/family.cmake | 1 + hw/bsp/stm32u0/family.mk | 1 + hw/bsp/stm32u5/family.cmake | 2 + hw/bsp/stm32u5/family.mk | 6 +- hw/bsp/stm32wb/family.cmake | 1 + hw/bsp/stm32wb/family.mk | 1 + lib/rt-thread/SConscript | 3 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 190 +----------- src/portable/st/stm32_fsdev/fsdev_at32.h | 10 +- src/portable/st/stm32_fsdev/fsdev_ch32.h | 10 +- src/portable/st/stm32_fsdev/fsdev_common.c | 241 +++++++++++++++ src/portable/st/stm32_fsdev/fsdev_common.h | 343 +++++++++++++++++++++ src/portable/st/stm32_fsdev/fsdev_stm32.h | 14 +- src/portable/st/stm32_fsdev/fsdev_type.h | 344 --------------------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 412 ++++++++++++-------------- tools/iar_template.ipcf | 4 +- 43 files changed, 838 insertions(+), 774 deletions(-) create mode 100644 src/portable/st/stm32_fsdev/fsdev_common.c create mode 100644 src/portable/st/stm32_fsdev/fsdev_common.h delete mode 100644 src/portable/st/stm32_fsdev/fsdev_type.h (limited to 'src') diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index cba58f8e8..a7bebf1d9 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -13,6 +13,7 @@ mcu:MSP432E4 mcu:RX65X mcu:RAXXX mcu:MAX3421 +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index cba58f8e8..a7bebf1d9 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -13,6 +13,7 @@ mcu:MSP432E4 mcu:RX65X mcu:RAXXX mcu:MAX3421 +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index ef0a1ac96..8da7a47d6 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -9,6 +9,7 @@ mcu:MIMXRT11XX mcu:MSP432E4 mcu:RX65X mcu:MAX3421 +mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 diff --git a/hw/bsp/at32f403a_407/family.cmake b/hw/bsp/at32f403a_407/family.cmake index 498b89c1a..7aaa9ede8 100644 --- a/hw/bsp/at32f403a_407/family.cmake +++ b/hw/bsp/at32f403a_407/family.cmake @@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/at32f403a_407/family.mk b/hw/bsp/at32f403a_407/family.mk index c82d402ca..f458881a3 100644 --- a/hw/bsp/at32f403a_407/family.mk +++ b/hw/bsp/at32f403a_407/family.mk @@ -16,6 +16,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ diff --git a/hw/bsp/at32f413/family.cmake b/hw/bsp/at32f413/family.cmake index 02692daf5..33718bd1c 100644 --- a/hw/bsp/at32f413/family.cmake +++ b/hw/bsp/at32f413/family.cmake @@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/at32f413/family.mk b/hw/bsp/at32f413/family.mk index 9c5d867de..abcd15d11 100644 --- a/hw/bsp/at32f413/family.mk +++ b/hw/bsp/at32f413/family.mk @@ -16,6 +16,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index d8c7c5327..59a96f70d 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -93,6 +93,7 @@ function(family_configure_example TARGET RTOS) ${TOP}/src/portable/wch/dcd_ch32_usbfs.c ${TOP}/src/portable/wch/hcd_ch32_usbfs.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 16fc537ac..7042ecbb7 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -47,6 +47,7 @@ SRC_C += \ src/portable/wch/dcd_ch32_usbfs.c \ src/portable/wch/hcd_ch32_usbfs.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(SDK_SRC_DIR)/Core/core_riscv.c \ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \ diff --git a/hw/bsp/stm32c0/family.cmake b/hw/bsp/stm32c0/family.cmake index 6e04b20f4..dc1a2bb13 100644 --- a/hw/bsp/stm32c0/family.cmake +++ b/hw/bsp/stm32c0/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32c0/family.mk b/hw/bsp/stm32c0/family.mk index fd03ad537..71209bf2e 100644 --- a/hw/bsp/stm32c0/family.mk +++ b/hw/bsp/stm32c0/family.mk @@ -30,6 +30,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f0/family.cmake b/hw/bsp/stm32f0/family.cmake index ee73ae872..a926a9739 100644 --- a/hw/bsp/stm32f0/family.cmake +++ b/hw/bsp/stm32f0/family.cmake @@ -65,6 +65,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32f0/family.mk b/hw/bsp/stm32f0/family.mk index 9b8305874..b5efdcb8d 100644 --- a/hw/bsp/stm32f0/family.mk +++ b/hw/bsp/stm32f0/family.mk @@ -30,6 +30,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f1/family.cmake b/hw/bsp/stm32f1/family.cmake index 064f32096..9e94d86c6 100644 --- a/hw/bsp/stm32f1/family.cmake +++ b/hw/bsp/stm32f1/family.cmake @@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32f1/family.mk b/hw/bsp/stm32f1/family.mk index ca95f2315..d4b6dfa6c 100644 --- a/hw/bsp/stm32f1/family.mk +++ b/hw/bsp/stm32f1/family.mk @@ -27,6 +27,7 @@ LDFLAGS_GCC += \ # ------------------------ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ ${ST_CMSIS}/Source/Templates/system_stm32${ST_FAMILY}xx.c \ ${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal.c \ ${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal_cortex.c \ diff --git a/hw/bsp/stm32f3/family.cmake b/hw/bsp/stm32f3/family.cmake index 7c9e97e62..3cbb4e1cd 100644 --- a/hw/bsp/stm32f3/family.cmake +++ b/hw/bsp/stm32f3/family.cmake @@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32f3/family.mk b/hw/bsp/stm32f3/family.mk index 13734583a..eb4a4e186 100644 --- a/hw/bsp/stm32f3/family.mk +++ b/hw/bsp/stm32f3/family.mk @@ -19,6 +19,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index 572f0e644..0ce85168e 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -64,6 +64,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32g0/family.mk b/hw/bsp/stm32g0/family.mk index d735ca92d..e376f7f06 100644 --- a/hw/bsp/stm32g0/family.mk +++ b/hw/bsp/stm32g0/family.mk @@ -29,6 +29,8 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 7e8b319b8..85201ce61 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32g4/family.mk b/hw/bsp/stm32g4/family.mk index 0abd73532..a153194ce 100644 --- a/hw/bsp/stm32g4/family.mk +++ b/hw/bsp/stm32g4/family.mk @@ -29,6 +29,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ src/portable/st/typec/typec_stm32.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ diff --git a/hw/bsp/stm32h5/family.cmake b/hw/bsp/stm32h5/family.cmake index 6e63c4072..d6f356ddf 100644 --- a/hw/bsp/stm32h5/family.cmake +++ b/hw/bsp/stm32h5/family.cmake @@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/st/typec/typec_stm32.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) diff --git a/hw/bsp/stm32h5/family.mk b/hw/bsp/stm32h5/family.mk index 792edb2bb..ec5f82d61 100644 --- a/hw/bsp/stm32h5/family.mk +++ b/hw/bsp/stm32h5/family.mk @@ -36,6 +36,8 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32l0/family.cmake b/hw/bsp/stm32l0/family.cmake index b6b0139a0..3f6622f71 100644 --- a/hw/bsp/stm32l0/family.cmake +++ b/hw/bsp/stm32l0/family.cmake @@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32l0/family.mk b/hw/bsp/stm32l0/family.mk index 921b1b413..0ae881fdf 100644 --- a/hw/bsp/stm32l0/family.mk +++ b/hw/bsp/stm32l0/family.mk @@ -27,6 +27,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32l4/family.cmake b/hw/bsp/stm32l4/family.cmake index 5bc28dd5d..b1659d47a 100644 --- a/hw/bsp/stm32l4/family.cmake +++ b/hw/bsp/stm32l4/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32l4/family.mk b/hw/bsp/stm32l4/family.mk index 01d059236..fd11fd226 100644 --- a/hw/bsp/stm32l4/family.mk +++ b/hw/bsp/stm32l4/family.mk @@ -34,6 +34,7 @@ SRC_C += \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32u0/family.cmake b/hw/bsp/stm32u0/family.cmake index 4f9b03109..2d3819cba 100644 --- a/hw/bsp/stm32u0/family.cmake +++ b/hw/bsp/stm32u0/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32u0/family.mk b/hw/bsp/stm32u0/family.mk index d5a850050..5f25906d3 100644 --- a/hw/bsp/stm32u0/family.mk +++ b/hw/bsp/stm32u0/family.mk @@ -27,6 +27,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake index 70e0c313c..58dc63ae3 100644 --- a/hw/bsp/stm32u5/family.cmake +++ b/hw/bsp/stm32u5/family.cmake @@ -66,6 +66,8 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 3694b1ca0..79f181a68 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -39,10 +39,12 @@ SRC_C += \ ifeq ($(MCU_VARIANT),stm32u545xx) SRC_C += \ - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c else ifeq ($(MCU_VARIANT),stm32u535xx) SRC_C += \ - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c else SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ diff --git a/hw/bsp/stm32wb/family.cmake b/hw/bsp/stm32wb/family.cmake index 1a96e3d7e..6703a9b19 100644 --- a/hw/bsp/stm32wb/family.cmake +++ b/hw/bsp/stm32wb/family.cmake @@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC diff --git a/hw/bsp/stm32wb/family.mk b/hw/bsp/stm32wb/family.mk index a80ff6f5b..0b1a51cec 100644 --- a/hw/bsp/stm32wb/family.mk +++ b/hw/bsp/stm32wb/family.mk @@ -20,6 +20,7 @@ LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + src/portable/st/stm32_fsdev/fsdev_common.c \ $(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 \ diff --git a/lib/rt-thread/SConscript b/lib/rt-thread/SConscript index 99517a090..e7b6f2dc4 100644 --- a/lib/rt-thread/SConscript +++ b/lib/rt-thread/SConscript @@ -18,7 +18,8 @@ if GetDepend(["PKG_TINYUSB_DEVICE_ENABLE"]): # BSP if GetDepend(["SOC_FAMILY_STM32"]): src += ["../../src/portable/synopsys/dwc2/dcd_dwc2.c", - "../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c"] + "../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c", + "../../src/portable/st/stm32_fsdev/fsdev_common.c"] if GetDepend(["SOC_NRF52840"]): src += ["../../src/portable/nordic/nrf5x/dcd_nrf5x.c"] diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index db1a5784a..3762b33f9 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -112,16 +112,7 @@ !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0) #include "device/dcd.h" - -#if defined(TUP_USBIP_FSDEV_STM32) - #include "fsdev_stm32.h" -#elif defined(TUP_USBIP_FSDEV_CH32) - #include "fsdev_ch32.h" -#elif defined(TUP_USBIP_FSDEV_AT32) - #include "fsdev_at32.h" -#else - #error "Unknown USB IP" -#endif +#include "fsdev_common.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -162,11 +153,6 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir); static uint16_t ep_buf_ptr; ///< Points to first free memory location static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf); 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, uint16_t nbytes); -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); - -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); static void edpt0_open(uint8_t rhport); @@ -307,7 +293,7 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - dcd_read_packet_memory(setup_packet, rx_addr, rx_count); + fsdev_read_packet_memory(setup_packet, rx_addr, rx_count); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); @@ -345,9 +331,9 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); if (xfer->ff) { - dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); + fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); } else { - dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); + fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } xfer->queued_len += rx_count; @@ -742,9 +728,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); if (xfer->ff) { - dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); + fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); } else { - dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } xfer->queued_len += len; @@ -864,168 +850,4 @@ void dcd_disconnect(uint8_t rhport) { } #endif -//--------------------------------------------------------------------+ -// PMA read/write -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_write = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); - const uint8_t *src8 = src; - - while (n_write--) { - pma_buf->value = fsdevbus_unaligned_read(src8); - src8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = 0; - for(uint16_t i = 0; i < odd; i++) { - temp |= *src8++ << (i * 8); - } - pma_buf->value = temp; - } - - return true; -} - -// Read from packet memory area (PMA) to user memory. -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_read = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); - uint8_t *dst8 = (uint8_t *)dst; - - while (n_read--) { - fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); - dst8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = pma_buf->value; - while (odd--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - return true; -} - -// Write to PMA from FIFO -static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { - if (wNBytes == 0) return true; - - // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - tu_fifo_buffer_info_t info; - tu_fifo_get_read_info(ff, &info); - - uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); - uint16_t const cnt_total = cnt_lin + cnt_wrap; - - // 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 aligned - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t const *src8 = (uint8_t const*) info.ptr_lin; - - // write even linear part - dcd_write_packet_memory(dst, src8, lin_even); - dst += lin_even; - src8 += lin_even; - - if (lin_odd == 0) { - src8 = (uint8_t const*) info.ptr_wrap; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp = 0; - uint16_t i; - for(i = 0; i < lin_odd; i++) { - temp |= *src8++ << (i * 8); - } - - src8 = (uint8_t const*) info.ptr_wrap; - for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - temp |= *src8++ << (i * 8); - } - - dcd_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); - dst += FSDEV_BUS_SIZE; - } - - // write the rest of the wrapped part - dcd_write_packet_memory(dst, src8, cnt_wrap); - - tu_fifo_advance_read_pointer(ff, cnt_total); - return true; -} - -// Read from PMA to FIFO -static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { - if (wNBytes == 0) return true; - - // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - // Check for first linear part - tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - - uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); - uint16_t cnt_total = cnt_lin + cnt_wrap; - - // 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 aligned - - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t *dst8 = (uint8_t *) info.ptr_lin; - - // read even linear part - dcd_read_packet_memory(dst8, src, lin_even); - dst8 += lin_even; - src += lin_even; - - if (lin_odd == 0) { - dst8 = (uint8_t *) info.ptr_wrap; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp; - dcd_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); - src += FSDEV_BUS_SIZE; - - uint16_t i; - for (i = 0; i < lin_odd; i++) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - - dst8 = (uint8_t *) info.ptr_wrap; - for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - // read the rest of the wrapped part - dcd_read_packet_memory(dst8, src, cnt_wrap); - - tu_fifo_advance_write_pointer(ff, cnt_total); - return true; -} - #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index 03490ee24..6877dc131 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -150,8 +150,6 @@ #define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ #define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) -#include "fsdev_type.h" - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -168,7 +166,7 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void fsdev_int_enable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) { (void)rhport; #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) // AT32F403A/407 devices allow to remap the USB interrupt vectors from @@ -187,7 +185,7 @@ void fsdev_int_enable(uint8_t rhport) { } } -void fsdev_int_disable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { (void)rhport; #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) // AT32F403A/407 devices allow to remap the USB interrupt vectors from @@ -206,7 +204,7 @@ void fsdev_int_disable(uint8_t rhport) { } } -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void) rhport; /* disable usb phy */ *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN; @@ -214,7 +212,7 @@ void fsdev_disconnect(uint8_t rhport) { *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void) rhport; /* enable usb phy */ *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN; diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 547f3bd1b..ee0057cb4 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -168,8 +168,6 @@ #define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ #define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) -#include "fsdev_type.h" - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -185,26 +183,26 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; #error "Unsupported MCU" #endif -void fsdev_int_enable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_EnableIRQ(fsdev_irq[i]); } } -void fsdev_int_disable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { (void)rhport; for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { NVIC_DisableIRQ(fsdev_irq[i]); } } -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN; } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void) rhport; EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; } diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c new file mode 100644 index 000000000..d021a6abf --- /dev/null +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -0,0 +1,241 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 Ha Thach (tinyusb.org) + * Copyright (c) 2025, HiFiPhile (Zixun LI) + * + * 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. + */ + +#include "tusb_option.h" + +#if defined(TUP_USBIP_FSDEV) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) + +#include "fsdev_common.h" + +//--------------------------------------------------------------------+ +// PMA read/write +//--------------------------------------------------------------------+ + +// Write to packet memory area (PMA) from user memory +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_write = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); + const uint8_t *src8 = src; + + while (n_write--) { + pma_buf->value = fsdevbus_unaligned_read(src8); + src8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = 0; + for(uint16_t i = 0; i < odd; i++) { + temp |= *src8++ << (i * 8); + } + pma_buf->value = temp; + } + + return true; +} + +// Read from packet memory area (PMA) to user memory. +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { + if (nbytes == 0) return true; + uint32_t n_read = nbytes / FSDEV_BUS_SIZE; + + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); + uint8_t *dst8 = (uint8_t *)dst; + + while (n_read--) { + fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); + dst8 += FSDEV_BUS_SIZE; + pma_buf++; + } + + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = pma_buf->value; + while (odd--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } + } + + return true; +} + +// Write to PMA from FIFO +bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { + if (wNBytes == 0) return true; + + // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + tu_fifo_buffer_info_t info; + tu_fifo_get_read_info(ff, &info); + + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t const cnt_total = cnt_lin + cnt_wrap; + + // 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 aligned + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t const *src8 = (uint8_t const*) info.ptr_lin; + + // write even linear part + fsdev_write_packet_memory(dst, src8, lin_even); + dst += lin_even; + src8 += lin_even; + + if (lin_odd == 0) { + src8 = (uint8_t const*) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp = 0; + uint16_t i; + for(i = 0; i < lin_odd; i++) { + temp |= *src8++ << (i * 8); + } + + src8 = (uint8_t const*) info.ptr_wrap; + for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + temp |= *src8++ << (i * 8); + } + + fsdev_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); + dst += FSDEV_BUS_SIZE; + } + + // write the rest of the wrapped part + fsdev_write_packet_memory(dst, src8, cnt_wrap); + + tu_fifo_advance_read_pointer(ff, cnt_total); + return true; +} + +// Read from PMA to FIFO +bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { + if (wNBytes == 0) return true; + + // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + tu_fifo_buffer_info_t info; + tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO + + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_total = cnt_lin + cnt_wrap; + + // 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 aligned + + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t *dst8 = (uint8_t *) info.ptr_lin; + + // read even linear part + fsdev_read_packet_memory(dst8, src, lin_even); + dst8 += lin_even; + src += lin_even; + + if (lin_odd == 0) { + dst8 = (uint8_t *) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp; + fsdev_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); + src += FSDEV_BUS_SIZE; + + uint16_t i; + for (i = 0; i < lin_odd; i++) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } + + dst8 = (uint8_t *) info.ptr_wrap; + for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } + } + + // read the rest of the wrapped part + fsdev_read_packet_memory(dst8, src, cnt_wrap); + + tu_fifo_advance_write_pointer(ff, cnt_total); + return true; +} + +//--------------------------------------------------------------------+ +// BTable Helper +//--------------------------------------------------------------------+ + +/* Aligned buffer size according to hardware */ +uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { + /* The STM32 full speed USB peripheral supports only a limited set of + * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ + uint16_t block_in_bytes; + if (size > 62) { + block_in_bytes = 32; + *blsize = 1; + *num_block = tu_div_ceil(size, 32); + } else { + block_in_bytes = 2; + *blsize = 0; + *num_block = tu_div_ceil(size, 2); + } + + return (*num_block) * block_in_bytes; +} + +void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { + uint8_t blsize, num_block; + (void) pma_align_buffer_size(wCount, &blsize, &num_block); + + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ + uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); + if (bl_nb == 0) { + // zlp but 0 is invalid value, set blsize to 1 (32 bytes) + // Note: lower value can cause PMAOVR on setup with ch32v203 + bl_nb = 1 << 15; + } + +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; +#endif +} + +#endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h new file mode 100644 index 000000000..e363245ec --- /dev/null +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -0,0 +1,343 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) N Conrad + * Copyright (c) 2024, hathach (tinyusb.org) + * Copyright (c) 2025, HiFiPhile (Zixun LI) + * + * 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 TUSB_FSDEV_COMMON_H +#define TUSB_FSDEV_COMMON_H + +#include "common/tusb_common.h" + +#if CFG_TUD_ENABLED +#include "device/dcd.h" +#endif + +#if CFG_TUH_ENABLED +#include "host/hcd.h" +#endif + +#if defined(TUP_USBIP_FSDEV_STM32) + #include "fsdev_stm32.h" +#elif defined(TUP_USBIP_FSDEV_CH32) + #include "fsdev_ch32.h" +#elif defined(TUP_USBIP_FSDEV_AT32) + #include "fsdev_at32.h" +#else + #error "Unknown USB IP" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it +// Both of these MUST be a multiple of 2, and are in byte units. +#ifndef FSDEV_BTABLE_BASE +#define FSDEV_BTABLE_BASE 0U +#endif + +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); + +// FSDEV_PMA_SIZE is PMA buffer size in bytes. +// - 512-byte devices, access with a stride of two words (use every other 16-bit address) +// - 1024-byte devices, access with a stride of one word (use every 16-bit address) +// - 2048-byte devices, access with 32-bit address + +// For purposes of accessing the packet +#if FSDEV_PMA_SIZE == 512 + // 1x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 2 + #define pma_access_scheme TU_ATTR_ALIGNED(4) +#elif FSDEV_PMA_SIZE == 1024 + // 2x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme +#elif FSDEV_PMA_SIZE == 2048 + // 32 bit access scheme + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme +#endif + +// The fsdev_bus_t type can be used for both register and PMA access necessities +#ifdef FSDEV_BUS_32BIT + typedef uint32_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) +#else + typedef uint16_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) +#endif + +enum { + FSDEV_BUS_SIZE = sizeof(fsdev_bus_t), +}; + +//--------------------------------------------------------------------+ +// BTable Typedef +//--------------------------------------------------------------------+ +enum { + BTABLE_BUF_TX = 0, + BTABLE_BUF_RX = 1 +}; + +// hardware limit endpoint +#define FSDEV_EP_COUNT 8 + +// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either +// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. +// 0: TX (IN), 1: RX (OUT) +typedef union { + // data is strictly 16-bit access (address could be 32-bit aligned) + struct { + volatile pma_access_scheme uint16_t addr; + volatile pma_access_scheme uint16_t count; + } ep16[FSDEV_EP_COUNT][2]; + + // strictly 32-bit access + struct { + volatile uint32_t count_addr; + } ep32[FSDEV_EP_COUNT][2]; +} fsdev_btable_t; + +TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); + +#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) + +typedef struct { + volatile pma_access_scheme fsdev_bus_t value; +} fsdev_pma_buf_t; + +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) + +//--------------------------------------------------------------------+ +// Registers Typedef +//--------------------------------------------------------------------+ + +// volatile 32-bit aligned +#define _va32 volatile TU_ATTR_ALIGNED(4) + +typedef struct { + struct { + _va32 fsdev_bus_t reg; + }ep[FSDEV_EP_COUNT]; + + _va32 uint32_t RESERVED7[8]; // Reserved + _va32 fsdev_bus_t CNTR; // 40: Control register + _va32 fsdev_bus_t ISTR; // 44: Interrupt status register + _va32 fsdev_bus_t FNR; // 48: Frame number register + _va32 fsdev_bus_t DADDR; // 4C: Device address register + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) +} fsdev_regs_t; + +TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); +TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); + +#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) + + +#ifndef USB_EPTX_STAT +#define USB_EPTX_STAT 0x0030U +#endif + +#ifndef USB_EPRX_STAT +#define USB_EPRX_STAT 0x3000U +#endif + +#ifndef USB_EPTX_STAT_Pos +#define USB_EPTX_STAT_Pos 4u +#endif + +#ifndef USB_EP_DTOG_TX_Pos +#define USB_EP_DTOG_TX_Pos 6u +#endif + +#ifndef USB_EP_CTR_TX_Pos +#define USB_EP_CTR_TX_Pos 7u +#endif + +typedef enum { + EP_STAT_DISABLED = 0, + EP_STAT_STALL = 1, + EP_STAT_NAK = 2, + EP_STAT_VALID = 3 +}ep_stat_t; + +#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) + +#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) + +//--------------------------------------------------------------------+ +// Endpoint Helper +// - CTR is write 0 to clear +// - DTOG and STAT are write 1 to toggle +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { + return FSDEV_REG->ep[ep_id].reg; +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { + if (need_exclusive) { + fsdev_int_disable(0); + } + + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; + + if (need_exclusive) { + fsdev_int_enable(0); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ep_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + ep_write(ep_id, reg, false); +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { + return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; +} + +//--------------------------------------------------------------------+ +// Channel Helper +// - Direction is opposite to endpoint direction +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ch_read(uint32_t ch_id) { + return ep_read(ch_id); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value, bool need_exclusive) { + ep_write(ch_id, value, need_exclusive); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ch_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + ep_write(ch_id, reg, false); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + +TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); +} + +//--------------------------------------------------------------------+ +// BTable Helper +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { +#ifdef FSDEV_BUS_32BIT + return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; +#else + return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { + uint16_t count; +#ifdef FSDEV_BUS_32BIT + count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); +#else + count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; +#endif + return count & 0x3FFU; +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; +#endif +} + +/* Aligned buffer size according to hardware */ +uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); + +void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); + +//--------------------------------------------------------------------+ +// PMA (Packet Memory Area) Access +//--------------------------------------------------------------------+ + +// Write to packet memory area (PMA) from user memory +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); + +// Read from packet memory area (PMA) to user memory. +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); + +// Write to PMA from FIFO +bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); + +// Read from PMA to FIFO +bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); + +#ifdef __cplusplus +} +#endif + +#endif /* TUSB_FSDEV_COMMON_H */ diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index d47d23f14..71370b189 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -321,8 +321,6 @@ #define FSDEV_USE_SBUF_ISO 0 #endif -#include "fsdev_type.h" - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -374,7 +372,7 @@ static const IRQn_Type fsdev_irq[] = { }; enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; -void fsdev_int_enable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) { (void)rhport; // forces write to RAM before allowing ISR to execute @@ -397,7 +395,7 @@ void fsdev_int_enable(uint8_t rhport) { } } -void fsdev_int_disable(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) { (void)rhport; #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP) @@ -422,24 +420,24 @@ void fsdev_int_disable(uint8_t rhport) { // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. #if defined(USB_BCDR_DPPU) -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void)rhport; USB->BCDR &= ~(USB_BCDR_DPPU); } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void)rhport; USB->BCDR |= USB_BCDR_DPPU; } #elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 -void fsdev_disconnect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) { (void)rhport; SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); } -void fsdev_connect(uint8_t rhport) { +TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) { (void)rhport; SYSCFG->PMC |= SYSCFG_PMC_USB_PU; } diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h deleted file mode 100644 index 2b340d64a..000000000 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright(c) N Conrad - * Copyright(c) 2024, hathach (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 TUSB_FSDEV_TYPE_H -#define TUSB_FSDEV_TYPE_H - -#ifdef __cplusplus - extern "C" { -#endif - -#include "stdint.h" - -// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it -// Both of these MUST be a multiple of 2, and are in byte units. -#ifndef FSDEV_BTABLE_BASE -#define FSDEV_BTABLE_BASE 0U -#endif - -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); - -// FSDEV_PMA_SIZE is PMA buffer size in bytes. -// - 512-byte devices, access with a stride of two words (use every other 16-bit address) -// - 1024-byte devices, access with a stride of one word (use every 16-bit address) -// - 2048-byte devices, access with 32-bit address - -// For purposes of accessing the packet -#if FSDEV_PMA_SIZE == 512 - // 1x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 2 - #define pma_access_scheme TU_ATTR_ALIGNED(4) -#elif FSDEV_PMA_SIZE == 1024 - // 2x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 1 - #define pma_access_scheme -#elif FSDEV_PMA_SIZE == 2048 - // 32 bit access scheme - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_STRIDE 1 - #define pma_access_scheme -#endif - -// The fsdev_bus_t type can be used for both register and PMA access necessities -#ifdef FSDEV_BUS_32BIT - typedef uint32_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) -#else - typedef uint16_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) -#endif - -enum { - FSDEV_BUS_SIZE = sizeof(fsdev_bus_t), -}; - -//--------------------------------------------------------------------+ -// BTable Typedef -//--------------------------------------------------------------------+ -enum { - BTABLE_BUF_TX = 0, - BTABLE_BUF_RX = 1 -}; - -// hardware limit endpoint -#define FSDEV_EP_COUNT 8 - -// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either -// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. -// 0: TX (IN), 1: RX (OUT) -typedef union { - // data is strictly 16-bit access (address could be 32-bit aligned) - struct { - volatile pma_access_scheme uint16_t addr; - volatile pma_access_scheme uint16_t count; - } ep16[FSDEV_EP_COUNT][2]; - - // strictly 32-bit access - struct { - volatile uint32_t count_addr; - } ep32[FSDEV_EP_COUNT][2]; -} fsdev_btable_t; - -TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); - -#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) - -typedef struct { - volatile pma_access_scheme fsdev_bus_t value; -} fsdev_pma_buf_t; - -#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) - -//--------------------------------------------------------------------+ -// Registers Typedef -//--------------------------------------------------------------------+ - -// volatile 32-bit aligned -#define _va32 volatile TU_ATTR_ALIGNED(4) - -typedef struct { - struct { - _va32 fsdev_bus_t reg; - }ep[FSDEV_EP_COUNT]; - - _va32 uint32_t RESERVED7[8]; // Reserved - _va32 fsdev_bus_t CNTR; // 40: Control register - _va32 fsdev_bus_t ISTR; // 44: Interrupt status register - _va32 fsdev_bus_t FNR; // 48: Frame number register - _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) -} fsdev_regs_t; - -TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); -TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); - -#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) - - -#ifndef USB_EPTX_STAT -#define USB_EPTX_STAT 0x0030U -#endif - -#ifndef USB_EPRX_STAT -#define USB_EPRX_STAT 0x3000U -#endif - -#ifndef USB_EPTX_STAT_Pos -#define USB_EPTX_STAT_Pos 4u -#endif - -#ifndef USB_EP_DTOG_TX_Pos -#define USB_EP_DTOG_TX_Pos 6u -#endif - -#ifndef USB_EP_CTR_TX_Pos -#define USB_EP_CTR_TX_Pos 7u -#endif - -typedef enum { - EP_STAT_DISABLED = 0, - EP_STAT_STALL = 1, - EP_STAT_NAK = 2, - EP_STAT_VALID = 3 -}ep_stat_t; - -#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) - -#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) -#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) - -void fsdev_int_enable(uint8_t rhport); -void fsdev_int_disable(uint8_t rhport); -void fsdev_connect(uint8_t rhport); -void fsdev_disconnect(uint8_t rhport); - -//--------------------------------------------------------------------+ -// Endpoint Helper -// - CTR is write 0 to clear -// - DTOG and STAT are write 1 to toggle -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { - return FSDEV_REG->ep[ep_id].reg; -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { - if (need_exclusive) { - fsdev_int_disable(0); - } - - FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; - - if (need_exclusive) { - fsdev_int_enable(0); - } -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { - uint32_t reg = FSDEV_REG->ep[ep_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); - ep_write(ep_id, reg, false); -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { - return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; -} - -//--------------------------------------------------------------------+ -// Channel Helper -// - Direction is opposite to endpoint direction -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ch_read(uint32_t ch_id) { - return ep_read(ch_id); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value, bool need_exclusive) { - ep_write(ch_id, value, need_exclusive); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { - uint32_t reg = FSDEV_REG->ep[ch_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); - ep_write(ch_id, reg, false); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); -} - -TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); -} - -//--------------------------------------------------------------------+ -// BTable Helper -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { -#ifdef FSDEV_BUS_32BIT - return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; -#else - return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { - uint16_t count; -#ifdef FSDEV_BUS_32BIT - count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); -#else - count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; -#endif - return count & 0x3FFU; -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; - cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); - FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; -#endif -} - -/* Aligned buffer size according to hardware */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { - /* The STM32 full speed USB peripheral supports only a limited set of - * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ - uint16_t block_in_bytes; - if (size > 62) { - block_in_bytes = 32; - *blsize = 1; - *num_block = tu_div_ceil(size, 32); - } else { - block_in_bytes = 2; - *blsize = 0; - *num_block = tu_div_ceil(size, 2); - } - - return (*num_block) * block_in_bytes; -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { - uint8_t blsize, num_block; - (void) pma_align_buffer_size(wCount, &blsize, &num_block); - - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); - if (bl_nb == 0) { - // zlp but 0 is invalid value, set blsize to 1 (32 bytes) - // Note: lower value can cause PMAOVR on setup with ch32v203 - bl_nb = 1 << 15; - } - -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; -#endif - -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 1c08f64d6..b3c08ba23 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -30,6 +30,7 @@ * * C0 2048 byte buffer; 32-bit bus; host mode * G0 2048 byte buffer; 32-bit bus; host mode + * U3 2048 byte buffer; 32-bit bus; host mode * H5 2048 byte buffer; 32-bit bus; host mode * U535, U545 2048 byte buffer; 32-bit bus; host mode * @@ -42,19 +43,14 @@ #include "host/hcd.h" #include "host/usbh.h" - -#if defined(TUP_USBIP_FSDEV_STM32) - #include "fsdev_stm32.h" -#else - #error "Unknown USB IP" -#endif +#include "fsdev_common.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ // Debug level for FSDEV -#define FSDEV_DEBUG 1 +#define FSDEV_DEBUG 3 // Max number of endpoints application can open, can be larger than FSDEV_EP_COUNT #ifndef CFG_TUH_FSDEV_ENDPOINT_MAX @@ -76,9 +72,12 @@ typedef struct { uint8_t ep_addr; uint8_t ep_type; uint8_t interval; - bool low_speed; - bool allocated; - bool next_setup; + struct TU_ATTR_PACKED { + uint8_t low_speed : 1; + uint8_t allocated : 1; + uint8_t next_setup : 1; + uint8_t pid : 1; + }; } hcd_endpoint_t; // Additional info for each channel when it is active @@ -88,7 +87,7 @@ typedef struct { uint8_t dev_addr; uint8_t ep_num; uint8_t ep_type; - bool allocated[2]; + uint8_t allocated[2]; uint8_t retry[2]; uint8_t result; } hcd_xfer_t; @@ -113,24 +112,35 @@ static uint8_t endpoint_alloc(void); static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr); static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len); static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type); -static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); -static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); static bool edpt_xfer_kickoff(uint8_t ep_id); static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); static void edpoint_close(uint8_t ep_id); static void port_status_handler(uint8_t rhport, bool in_isr); +static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); +static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); +static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); +static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { - edpt->allocated = false; + edpt->allocated = 0; } static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) { - xfer->allocated[dir] = false; + xfer->allocated[dir] = 0; } +// Write channel state in specified direction +static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir, ep_stat_t state, bool need_exclusive) { + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); + ch_change_status(&ch_reg, dir, state); + ch_write(ch_id, ch_reg, need_exclusive); +} + + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ @@ -218,139 +228,153 @@ static void port_status_handler(uint8_t rhport, bool in_isr) { } } -// Handle CTR interrupt for the TX/OUT direction -static void handle_ctr_tx(uint32_t ch_id) { - uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; +//--------------------------------------------------------------------+ +// Interrupt Helper Functions +//--------------------------------------------------------------------+ +// Handle ACK response +static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; - uint8_t ep_id = endpoint_find(daddr, ep_num); - TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_OUT],); - // Manage Correct Transaction - if ((ch_reg & USB_CH_ERRTX) == 0U) { - // Acked - if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { - if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { - uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); - uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); - btable_set_count(ch_id, BTABLE_BUF_TX, len); - xfer->queued_len[TUSB_DIR_OUT] += len; - - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits - ch_write(ch_id, ch_reg, false); - } else { - channel_dealloc(xfer, TUSB_DIR_OUT); - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); - } - } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) { - // NAKed - if (edpt->ep_type != TUSB_XFER_INTERRUPT) { - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); - ch_write(ch_id, ch_reg, false); - } - } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) { - // STALLed + if (dir == TUSB_DIR_OUT) { + // OUT/TX direction + if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { + // More data to send + uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + btable_set_count(ch_id, BTABLE_BUF_TX, len); + xfer->queued_len[TUSB_DIR_OUT] += len; + channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); + } else { + // Transfer complete channel_dealloc(xfer, TUSB_DIR_OUT); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - ch_write(ch_id, ch_reg, false); - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_STALLED, true); + edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0; + hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); } } else { - // Error - TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", - ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_OUT], edpt->buflen); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change TX Status, reserved other toggle bits - ch_reg &=~USB_CH_ERRTX; - if (xfer->retry[TUSB_DIR_OUT] < HCD_XFER_ERROR_MAX) { - // Retry - xfer->retry[TUSB_DIR_OUT]++; + // IN/RX direction + uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); + uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); + + fsdev_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); + xfer->queued_len[TUSB_DIR_IN] += rx_count; + + if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + // Transfer complete (short packet or all bytes received) + channel_dealloc(xfer, TUSB_DIR_IN); + edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0; + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); } else { - // Failed after retries - channel_dealloc(xfer, TUSB_DIR_OUT); - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_FAILED, true); + // More data expected + uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); + channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false); } - ch_write(ch_id, ch_reg, false); } } -// Handle CTR interrupt for the RX/IN direction -static void handle_ctr_rx(uint32_t ch_id) { - uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; +// Handle NAK response +static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; - uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; - uint8_t ep_id = endpoint_find(daddr, ep_num | TUSB_DIR_IN_MASK); - TU_VERIFY(ep_id != TUSB_INDEX_INVALID_8, ); + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_IN],); + // Retry non-periodic transfer immediately, + // Periodic transfer will be retried by next frame automatically + if (edpt->ep_type == TUSB_XFER_CONTROL || edpt->ep_type == TUSB_XFER_BULK) { + channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false); + } +} + +// Handle STALL response +static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + channel_dealloc(xfer, dir); + + channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false); + + hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), + xfer->queued_len[dir], XFER_RESULT_STALLED, true); +} + +// Handle error response +static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { + uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; + uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; + + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); + ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX); + + if (xfer->retry[dir] < HCD_XFER_ERROR_MAX) { + // Retry + xfer->retry[dir]++; + ch_change_status(&ch_reg, dir, EP_STAT_VALID); + } else { + // Failed after retries + channel_dealloc(xfer, dir); + ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); + hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), + xfer->queued_len[dir], XFER_RESULT_FAILED, true); + } + ch_write(ch_id, ch_reg, false); +} + +// Handle CTR interrupt for the TX/OUT direction +static void handle_ctr_tx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_OUT] == 1,); + + if ((ch_reg & USB_CH_ERRTX) == 0U) { + // No error + if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) { + ch_handle_ack(ch_id, ch_reg, TUSB_DIR_OUT); + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) { + ch_handle_nak(ch_id, ch_reg, TUSB_DIR_OUT); + } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) { + ch_handle_stall(ch_id, ch_reg, TUSB_DIR_OUT); + } + } else { + ch_handle_error(ch_id, ch_reg, TUSB_DIR_OUT); + } +} + +// Handle CTR interrupt for the RX/IN direction +static void handle_ctr_rx(uint32_t ch_id) { + uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + TU_VERIFY(xfer->allocated[TUSB_DIR_IN] == 1,); - // Manage Correct Transaction if ((ch_reg & USB_CH_ERRRX) == 0U) { - // Acked + // No error if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) { - uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); - uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - - hcd_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); - xfer->queued_len[TUSB_DIR_IN] += rx_count; - - if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { - // all bytes received or short packet - channel_dealloc(xfer, TUSB_DIR_IN); - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); - } else { - // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always - uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); - btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); - ch_write(ch_id, ch_reg, false); - } + ch_handle_ack(ch_id, ch_reg, TUSB_DIR_IN); } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) { - // NAKed - if (edpt->ep_type != TUSB_XFER_INTERRUPT) { - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); - ch_write(ch_id, ch_reg, false); - } - } else { - // STALLed - channel_dealloc(xfer, TUSB_DIR_IN); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - ch_write(ch_id, ch_reg, false); - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_STALLED, true); + ch_handle_nak(ch_id, ch_reg, TUSB_DIR_IN); + } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL){ + ch_handle_stall(ch_id, ch_reg, TUSB_DIR_IN); } } else { - // Error - TU_LOG(FSDEV_DEBUG, "handle_ctr_tx error epreg=0x%08X ch=%u ep=0x%02X daddr=%u queued=%u/%u\r\n", - ch_reg, ch_id, ep_num, daddr, xfer->queued_len[TUSB_DIR_IN], edpt->buflen); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits - ch_reg &=~USB_CH_ERRRX; - if (xfer->retry[TUSB_DIR_IN] < HCD_XFER_ERROR_MAX) { - // Retry - xfer->retry[TUSB_DIR_IN]++; - } else { - // Failed after retries - channel_dealloc(xfer, TUSB_DIR_IN); - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_FAILED, true); - } - ch_write(ch_id, ch_reg, false); + ch_handle_error(ch_id, ch_reg, TUSB_DIR_IN); } } @@ -468,7 +492,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // Close all endpoints for this device for(uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (edpt->allocated && edpt->dev_addr == dev_addr) { + if (edpt->allocated == 1 && edpt->dev_addr == dev_addr) { edpoint_close(i); } } @@ -496,7 +520,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const edpt->ep_type = ep_type; edpt->max_packet_size = packet_size; edpt->interval = ep_desc->bInterval; - edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW); + edpt->pid = 0; + edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; // EP0 is bi-directional, so we need to open both OUT and IN channels if (ep_addr == 0) { @@ -525,7 +550,7 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { edpoint_close(ep_id_in); } - return false; + return true; } // Submit a transfer @@ -556,17 +581,12 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_xfer_t* xfer = &_hcd_data.xfer[i]; - if (xfer->allocated[dir] && + if (xfer->allocated[dir] == 1 && xfer->dev_addr == dev_addr && xfer->ep_num == tu_edpt_number(ep_addr)) { - channel_dealloc(xfer, dir); - - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); // will change Status, reserved other toggle bits - ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); - ch_write(i, ch_reg, true); - + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; + channel_write_status(i, ch_reg, dir, EP_STAT_DISABLED, true); } } @@ -582,6 +602,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; edpt->next_setup = true; + edpt->pid = 0; return hcd_edpt_xfer(rhport, dev_addr, 0, (uint8_t*)(uintptr_t) setup_packet, 8); } @@ -592,6 +613,12 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) dev_addr; (void) ep_addr; + uint8_t const ep_id = endpoint_find(dev_addr, 0); + TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + edpt->pid = 0; + return true; } @@ -602,8 +629,8 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { static uint8_t endpoint_alloc(void) { for (uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (!edpt->allocated) { - edpt->allocated = true; + if (edpt->allocated == 0) { + edpt->allocated = 1; return i; } } @@ -613,7 +640,7 @@ static uint8_t endpoint_alloc(void) { static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) { for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (edpt->allocated && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { + if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { return i; } } @@ -628,24 +655,14 @@ static void edpoint_close(uint8_t ep_id) { // disable active channel belong to this endpoint for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_xfer_t* xfer = &_hcd_data.xfer[i]; - - if (xfer->allocated[TUSB_DIR_OUT] && xfer->edpt[TUSB_DIR_OUT] == edpt) { + uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; + if (xfer->allocated[TUSB_DIR_OUT] == 1 && xfer->edpt[TUSB_DIR_OUT] == edpt) { channel_dealloc(xfer, TUSB_DIR_OUT); - - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - ch_write(i, ch_reg, true); - + channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true); } - if (xfer->allocated[TUSB_DIR_IN] && xfer->edpt[TUSB_DIR_IN] == edpt) { + if (xfer->allocated[TUSB_DIR_IN] == 1 && xfer->edpt[TUSB_DIR_IN] == edpt) { channel_dealloc(xfer, TUSB_DIR_IN); - - uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change TX Status, reserved other toggle bits - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - ch_write(i, ch_reg, true); - + channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true); } } } @@ -654,10 +671,10 @@ static void edpoint_close(uint8_t ep_id) { static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) { (void) len; // Simple static allocation as we are unlikely to handle ISO endpoints in host mode - // We just give each channel a buffer of max packet size (64 bytes) + // We just give each channel two buffers of max packet size (64 bytes) for IN and OUT uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; - addr += channel * 64 * 2 + (dir == TUSB_DIR_IN ? 64 : 0); + addr += channel * TUSB_EPSIZE_BULK_FS * 2 + (dir == TUSB_DIR_IN ? TUSB_EPSIZE_BULK_FS : 0); TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF); @@ -672,12 +689,12 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find channel allocate for same ep_num but other direction tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (!_hcd_data.xfer[i].allocated[dir] && - _hcd_data.xfer[i].allocated[other_dir] && + if (_hcd_data.xfer[i].allocated[dir] == 0 && + _hcd_data.xfer[i].allocated[other_dir] == 1 && _hcd_data.xfer[i].dev_addr == dev_addr && _hcd_data.xfer[i].ep_num == ep_num && _hcd_data.xfer[i].ep_type == ep_type) { - _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].allocated[dir] = 1; _hcd_data.xfer[i].queued_len[dir] = 0; _hcd_data.xfer[i].retry[dir] = 0; return i; @@ -686,11 +703,11 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find free channel for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (!_hcd_data.xfer[i].allocated[0] && !_hcd_data.xfer[i].allocated[1]) { + if (_hcd_data.xfer[i].allocated[0] == 0 && _hcd_data.xfer[i].allocated[1] == 0) { _hcd_data.xfer[i].dev_addr = dev_addr; _hcd_data.xfer[i].ep_num = ep_num; _hcd_data.xfer[i].ep_type = ep_type; - _hcd_data.xfer[i].allocated[dir] = true; + _hcd_data.xfer[i].allocated[dir] = 1; _hcd_data.xfer[i].queued_len[dir] = 0; _hcd_data.xfer[i].retry[dir] = 0; return i; @@ -748,84 +765,35 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); - hcd_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); xfer->queued_len[TUSB_DIR_OUT] += len; - if (edpt->next_setup) { - // Setup packet uses IN token - edpt->next_setup = false; - ch_reg |= USB_EP_SETUP; - } - - ch_change_status(&ch_reg, TUSB_DIR_OUT, EP_STAT_VALID); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_OUT); // only change TX Status, reserve other toggle bits - } else { btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); - ch_change_status(&ch_reg, TUSB_DIR_IN, EP_STAT_VALID); - ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(TUSB_DIR_IN); // will change RX Status, reserved other toggle bits } - ch_write(ch_id, ch_reg, true); - - return true; -} - -//--------------------------------------------------------------------+ -// PMA read/write -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -static bool hcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_write = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(dst); - const uint8_t *src8 = src; - - while (n_write--) { - pma_buf->value = fsdevbus_unaligned_read(src8); - src8 += FSDEV_BUS_SIZE; - pma_buf++; + if (edpt->low_speed == 1) { + ch_reg |= USB_CHEP_LSEP; + } else { + ch_reg &= ~USB_CHEP_LSEP; } - // Handle odd bytes - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = 0; - for (uint16_t i = 0; i < odd; i++) { - temp |= *src8++ << (i * 8); - } - pma_buf->value = temp; + if (tu_edpt_number(edpt->ep_addr) == 0) { + edpt->pid = 1; } - return true; -} - -// Read from packet memory area (PMA) to user memory -static bool hcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) return true; - uint32_t n_read = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(src); - uint8_t *dst8 = (uint8_t *)dst; - - while (n_read--) { - fsdevbus_unaligned_write(dst8, (fsdev_bus_t) pma_buf->value); - dst8 += FSDEV_BUS_SIZE; - pma_buf++; + if (edpt->next_setup) { + // Setup packet uses IN token + edpt->next_setup = false; + ch_reg |= USB_EP_SETUP; + edpt->pid = 0; } - // Handle odd bytes - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = pma_buf->value; - while (odd--) { - *dst8++ = (uint8_t)(temp & 0xfful); - temp >>= 8; - } - } + ch_change_status(&ch_reg, dir, EP_STAT_VALID); + ch_change_dtog(&ch_reg, dir, edpt->pid); + ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir) | CH_DTOG_MASK(dir); + ch_write(ch_id, ch_reg, true); return true; } diff --git a/tools/iar_template.ipcf b/tools/iar_template.ipcf index 2581a4702..caddda826 100644 --- a/tools/iar_template.ipcf +++ b/tools/iar_template.ipcf @@ -217,7 +217,9 @@ $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h + $TUSB_DIR$/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c + $TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.c + $TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.h $TUSB_DIR$/src/portable/st/typec/typec_stm32.c -- cgit v1.3.1 From a445e8c3b31629f2d14b3380c15bceb667d546b6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 25 Nov 2025 23:02:17 +0100 Subject: hcd/fsdev: more refactor Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 123 +++++++++++++------------- 1 file changed, 61 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index b3c08ba23..2d05b2633 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -89,8 +89,7 @@ typedef struct { uint8_t ep_type; uint8_t allocated[2]; uint8_t retry[2]; - uint8_t result; -} hcd_xfer_t; +} hcd_channel_t; // Root hub port state static struct { @@ -98,7 +97,7 @@ static struct { } _hcd_port; typedef struct { - hcd_xfer_t xfer[FSDEV_EP_COUNT]; + hcd_channel_t channel[FSDEV_EP_COUNT]; hcd_endpoint_t edpt[CFG_TUH_FSDEV_ENDPOINT_MAX]; } hcd_data_t; @@ -129,8 +128,8 @@ static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { edpt->allocated = 0; } -static inline void channel_dealloc(hcd_xfer_t* xfer, tusb_dir_t dir) { - xfer->allocated[dir] = 0; +static inline void channel_dealloc(hcd_channel_t* ch, tusb_dir_t dir) { + ch->allocated[dir] = 0; } // Write channel state in specified direction @@ -241,40 +240,40 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; if (dir == TUSB_DIR_OUT) { // OUT/TX direction - if (edpt->buflen != xfer->queued_len[TUSB_DIR_OUT]) { + if (edpt->buflen != channel->queued_len[TUSB_DIR_OUT]) { // More data to send - uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - xfer->queued_len[TUSB_DIR_OUT] += len; + channel->queued_len[TUSB_DIR_OUT] += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); } else { // Transfer complete - channel_dealloc(xfer, TUSB_DIR_OUT); + channel_dealloc(channel, TUSB_DIR_OUT); edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num, xfer->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num, channel->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); } } else { // IN/RX direction uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - fsdev_read_packet_memory(edpt->buffer + xfer->queued_len[TUSB_DIR_IN], pma_addr, rx_count); - xfer->queued_len[TUSB_DIR_IN] += rx_count; + fsdev_read_packet_memory(edpt->buffer + channel->queued_len[TUSB_DIR_IN], pma_addr, rx_count); + channel->queued_len[TUSB_DIR_IN] += rx_count; - if ((rx_count < edpt->max_packet_size) || (xfer->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + if ((rx_count < edpt->max_packet_size) || (channel->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { // Transfer complete (short packet or all bytes received) - channel_dealloc(xfer, TUSB_DIR_IN); + channel_dealloc(channel, TUSB_DIR_IN); edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, channel->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); } else { // More data expected - uint16_t const cnt = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + uint16_t const cnt = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_IN], edpt->max_packet_size); btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false); } @@ -302,13 +301,13 @@ static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - channel_dealloc(xfer, dir); + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + channel_dealloc(channel, dir); channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - xfer->queued_len[dir], XFER_RESULT_STALLED, true); + channel->queued_len[dir], XFER_RESULT_STALLED, true); } // Handle error response @@ -319,21 +318,21 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) return; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX); - if (xfer->retry[dir] < HCD_XFER_ERROR_MAX) { + if (channel->retry[dir] < HCD_XFER_ERROR_MAX) { // Retry - xfer->retry[dir]++; + channel->retry[dir]++; ch_change_status(&ch_reg, dir, EP_STAT_VALID); } else { // Failed after retries - channel_dealloc(xfer, dir); + channel_dealloc(channel, dir); ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - xfer->queued_len[dir], XFER_RESULT_FAILED, true); + channel->queued_len[dir], XFER_RESULT_FAILED, true); } ch_write(ch_id, ch_reg, false); } @@ -341,8 +340,8 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // Handle CTR interrupt for the TX/OUT direction static void handle_ctr_tx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_OUT] == 1,); + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + TU_VERIFY(channel->allocated[TUSB_DIR_OUT] == 1,); if ((ch_reg & USB_CH_ERRTX) == 0U) { // No error @@ -361,8 +360,8 @@ static void handle_ctr_tx(uint32_t ch_id) { // Handle CTR interrupt for the RX/IN direction static void handle_ctr_rx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - TU_VERIFY(xfer->allocated[TUSB_DIR_IN] == 1,); + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + TU_VERIFY(channel->allocated[TUSB_DIR_IN] == 1,); if ((ch_reg & USB_CH_ERRRX) == 0U) { // No error @@ -579,12 +578,12 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { tusb_dir_t const dir = tu_edpt_dir(ep_addr); for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + hcd_channel_t* channel = &_hcd_data.channel[i]; - if (xfer->allocated[dir] == 1 && - xfer->dev_addr == dev_addr && - xfer->ep_num == tu_edpt_number(ep_addr)) { - channel_dealloc(xfer, dir); + if (channel->allocated[dir] == 1 && + channel->dev_addr == dev_addr && + channel->ep_num == tu_edpt_number(ep_addr)) { + channel_dealloc(channel, dir); uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; channel_write_status(i, ch_reg, dir, EP_STAT_DISABLED, true); } @@ -654,14 +653,14 @@ static void edpoint_close(uint8_t ep_id) { // disable active channel belong to this endpoint for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - hcd_xfer_t* xfer = &_hcd_data.xfer[i]; + hcd_channel_t* channel = &_hcd_data.channel[i]; uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; - if (xfer->allocated[TUSB_DIR_OUT] == 1 && xfer->edpt[TUSB_DIR_OUT] == edpt) { - channel_dealloc(xfer, TUSB_DIR_OUT); + if (channel->allocated[TUSB_DIR_OUT] == 1 && channel->edpt[TUSB_DIR_OUT] == edpt) { + channel_dealloc(channel, TUSB_DIR_OUT); channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true); } - if (xfer->allocated[TUSB_DIR_IN] == 1 && xfer->edpt[TUSB_DIR_IN] == edpt) { - channel_dealloc(xfer, TUSB_DIR_IN); + if (channel->allocated[TUSB_DIR_IN] == 1 && channel->edpt[TUSB_DIR_IN] == edpt) { + channel_dealloc(channel, TUSB_DIR_IN); channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true); } } @@ -689,27 +688,27 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find channel allocate for same ep_num but other direction tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.xfer[i].allocated[dir] == 0 && - _hcd_data.xfer[i].allocated[other_dir] == 1 && - _hcd_data.xfer[i].dev_addr == dev_addr && - _hcd_data.xfer[i].ep_num == ep_num && - _hcd_data.xfer[i].ep_type == ep_type) { - _hcd_data.xfer[i].allocated[dir] = 1; - _hcd_data.xfer[i].queued_len[dir] = 0; - _hcd_data.xfer[i].retry[dir] = 0; + if (_hcd_data.channel[i].allocated[dir] == 0 && + _hcd_data.channel[i].allocated[other_dir] == 1 && + _hcd_data.channel[i].dev_addr == dev_addr && + _hcd_data.channel[i].ep_num == ep_num && + _hcd_data.channel[i].ep_type == ep_type) { + _hcd_data.channel[i].allocated[dir] = 1; + _hcd_data.channel[i].queued_len[dir] = 0; + _hcd_data.channel[i].retry[dir] = 0; return i; } } // Find free channel for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.xfer[i].allocated[0] == 0 && _hcd_data.xfer[i].allocated[1] == 0) { - _hcd_data.xfer[i].dev_addr = dev_addr; - _hcd_data.xfer[i].ep_num = ep_num; - _hcd_data.xfer[i].ep_type = ep_type; - _hcd_data.xfer[i].allocated[dir] = 1; - _hcd_data.xfer[i].queued_len[dir] = 0; - _hcd_data.xfer[i].retry[dir] = 0; + if (_hcd_data.channel[i].allocated[0] == 0 && _hcd_data.channel[i].allocated[1] == 0) { + _hcd_data.channel[i].dev_addr = dev_addr; + _hcd_data.channel[i].ep_num = ep_num; + _hcd_data.channel[i].ep_type = ep_type; + _hcd_data.channel[i].allocated[dir] = 1; + _hcd_data.channel[i].queued_len[dir] = 0; + _hcd_data.channel[i].retry[dir] = 0; return i; } } @@ -726,15 +725,15 @@ static bool edpt_xfer_kickoff(uint8_t ep_id) { tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - xfer->edpt[dir] = edpt; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + channel->edpt[dir] = edpt; return channel_xfer_start(ch_id, dir); } static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - hcd_endpoint_t* edpt = xfer->edpt[dir]; + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + hcd_endpoint_t* edpt = channel->edpt[dir]; uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK; ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos | @@ -763,12 +762,12 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { btable_set_addr(ch_id, dir == TUSB_DIR_OUT ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); if (dir == TUSB_DIR_OUT) { - uint16_t const len = tu_min16(edpt->buflen - xfer->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[xfer->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - xfer->queued_len[TUSB_DIR_OUT] += len; + channel->queued_len[TUSB_DIR_OUT] += len; } else { btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); } -- cgit v1.3.1 From 270e1492764959c278f1b154b8e42aef4dcd98d8 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Wed, 26 Nov 2025 14:25:06 +0100 Subject: reorganize ctr_rx workaround Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 81 +++++++++++++++++---------- 1 file changed, 50 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 2d05b2633..362d7df7b 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -139,6 +139,53 @@ static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir ch_write(ch_id, ch_reg, need_exclusive); } +static inline uint16_t channel_get_rx_count(uint8_t ch_id) { + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf + * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * + * Note: this errata may also apply to G0, U5, H5 etc. + * + * We choose the delay count based on max CPU frequency (in MHz) to ensure the delay is at least the required time. + */ + +#if CFG_TUSB_MCU == OPT_MCU_STM32H5 + #define FREQUENCY_MHZ 250U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #define FREQUENCY_MHZ 160U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #define FREQUENCY_MHZ 96U +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #define FREQUENCY_MHZ 64U +#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 + #define FREQUENCY_MHZ 48U +#else + #error "FREQUENCY_MHZ not defined for this STM32 MCU" +#endif + + uint32_t ch_reg = ch_read(ch_id); + if (FSDEV_REG->ISTR & USB_ISTR_LS_DCONN || ch_reg & USB_CHEP_LSEP) { + // Low speed mode: 6.4 us delay -> about 2 cycles per MHz + volatile uint32_t cycle_count = FREQUENCY_MHZ * 2U; + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + } else { + // Full speed mode: 800 ns delay -> about 0.25 cycles per MHz + volatile uint32_t cycle_count = FREQUENCY_MHZ / 4U; + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + } + + return btable_get_count(ch_id, BTABLE_BUF_RX); +} //--------------------------------------------------------------------+ // Controller API @@ -175,12 +222,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode - -#if !defined(FSDEV_BUS_32BIT) - // BTABLE register does not exist on 32-bit bus devices - FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; -#endif - FSDEV_REG->ISTR = 0; // Clear pending interrupts // Reset channels to disabled @@ -260,7 +301,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { } } else { // IN/RX direction - uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX); + uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); fsdev_read_packet_memory(edpt->buffer + channel->queued_len[TUSB_DIR_IN], pma_addr, rx_count); @@ -338,7 +379,7 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { } // Handle CTR interrupt for the TX/OUT direction -static void handle_ctr_tx(uint32_t ch_id) { +static inline void handle_ctr_tx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; TU_VERIFY(channel->allocated[TUSB_DIR_OUT] == 1,); @@ -358,7 +399,7 @@ static void handle_ctr_tx(uint32_t ch_id) { } // Handle CTR interrupt for the RX/IN direction -static void handle_ctr_rx(uint32_t ch_id) { +static inline void handle_ctr_rx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; TU_VERIFY(channel->allocated[TUSB_DIR_IN] == 1,); @@ -393,28 +434,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { uint32_t const ch_reg = ch_read(ch_id); if (ch_reg & USB_EP_CTR_RX) { - #ifdef FSDEV_BUS_32BIT - /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf - * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf - * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers - * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses - * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. - * Workaround: - * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay - * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode - * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code - * also takes time, so we'll wait 60 cycles (count = 20). - * - Since Low Speed mode is not supported/popular, we will ignore it for now. - * - * Note: this errata may also apply to G0, U5, H5 etc. - */ - volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver - while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) - } - #endif - ch_write_clear_ctr(ch_id, TUSB_DIR_IN); handle_ctr_rx(ch_id); } -- cgit v1.3.1 From c05d809e3eb9364e4db9f9997dc51dde169ed2c5 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 26 Nov 2025 23:06:15 +0100 Subject: usbh: Stop enumeration gracefully if EP0 can't be open Signed-off-by: HiFiPhile --- src/host/usbh.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 734024771..5fea5fa9f 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1575,7 +1575,11 @@ static void process_enumeration(tuh_xfer_t* xfer) { // TODO probably doesn't need to open/close each enumeration uint8_t const addr0 = 0; - TU_ASSERT(usbh_edpt_control_open(addr0, 8),); + if (!usbh_edpt_control_open(addr0, 8)) { + // Stop enumeration gracefully + enum_full_complete(false); + TU_ASSERT(false,); + } // Get first 8 bytes of device descriptor for control endpoint size TU_LOG_USBH("Get 8 byte of Device Descriptor\r\n"); @@ -1613,7 +1617,12 @@ static void process_enumeration(tuh_xfer_t* xfer) { usbh_device_close(dev0_bus->rhport, 0); // close dev0 - TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->bMaxPacketSize0),); // open new control endpoint + if (!usbh_edpt_control_open(new_addr, new_dev->bMaxPacketSize0)) { // open new control endpoint + // Stop enumeration gracefully + clear_device(new_dev); + enum_full_complete(false); + TU_ASSERT(false,); + } TU_LOG_USBH("Get Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t), -- cgit v1.3.1 From 66ab814520476a03d962aaec880e6c8c1b9de225 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 26 Nov 2025 23:09:29 +0100 Subject: usbh: watch hub status before driver config Signed-off-by: HiFiPhile --- src/host/usbh.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 5fea5fa9f..c655702bd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1420,7 +1420,7 @@ enum { static uint8_t enum_get_new_address(bool is_hub); static bool enum_parse_configuration_desc (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); -static void enum_full_complete(void); +static void enum_full_complete(bool success); static void process_enumeration(tuh_xfer_t* xfer); // start a new enumeration process @@ -1442,7 +1442,7 @@ static bool enum_new_device(hcd_event_t* event) { if (!hcd_port_connect_status(dev0_bus->rhport)) { TU_LOG_USBH("Device unplugged while debouncing\r\n"); - enum_full_complete(); + enum_full_complete(false); return true; } @@ -1453,7 +1453,7 @@ static bool enum_new_device(hcd_event_t* event) { if (!hcd_port_connect_status(dev0_bus->rhport)) { // device unplugged while delaying - enum_full_complete(); + enum_full_complete(false); return true; } @@ -1499,7 +1499,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { } if (!retry) { - enum_full_complete(); // complete as failed + enum_full_complete(false); // complete as failed } return; } @@ -1522,7 +1522,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub while debouncing\r\n"); - enum_full_complete(); + enum_full_complete(false); return; } @@ -1559,7 +1559,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub (not addressed yet)\r\n"); - enum_full_complete(); + enum_full_complete(false); return; } @@ -1776,6 +1776,12 @@ static void process_enumeration(tuh_xfer_t* xfer) { TU_LOG_USBH("Device configured\r\n"); dev->configured = 1; + #if CFG_TUH_HUB + if (_usbh_data.dev0_bus.hub_addr != 0) { + hub_edpt_status_xfer(_usbh_data.dev0_bus.hub_addr); // get next hub status + } + #endif + // Parse configuration & set up drivers // driver_open() must not make any usb transfer TU_ASSERT(enum_parse_configuration_desc(daddr, (tusb_desc_configuration_t*) _usbh_epbuf.ctrl),); @@ -1789,7 +1795,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { } default: - enum_full_complete(); // stop enumeration if unknown state + enum_full_complete(false); // stop enumeration if unknown state break; } } @@ -1926,7 +1932,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { // all interface are configured if (itf_num == CFG_TUH_INTERFACE_MAX) { - enum_full_complete(); + enum_full_complete(true); if (is_hub_addr(dev_addr)) { TU_LOG_USBH("HUB address = %u is mounted\r\n", dev_addr); @@ -1937,14 +1943,17 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { } } -static void enum_full_complete(void) { +static void enum_full_complete(bool success) { // mark enumeration as complete _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; #if CFG_TUH_HUB - if (_usbh_data.dev0_bus.hub_addr != 0) { + // Hub status is already requested in case of successful enumeration + if (_usbh_data.dev0_bus.hub_addr != 0 && !success) { hub_edpt_status_xfer(_usbh_data.dev0_bus.hub_addr); // get next hub status } +#else + (void) success; #endif } -- cgit v1.3.1 From 5d56828e43ef5f894c4586e7e7a61c3fbbbbfaf9 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 11:02:49 +0100 Subject: extract core reset Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 18 +-------------- src/portable/st/stm32_fsdev/fsdev_common.c | 32 ++++++++++++++++++++++++++- src/portable/st/stm32_fsdev/fsdev_common.h | 6 ++++- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 19 +--------------- 4 files changed, 38 insertions(+), 37 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 a6c8d2453..3c4e4fc9b 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -173,23 +173,9 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint8_t epnum, uint //--------------------------------------------------------------------+ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; - // Follow the RM mentions to use a special ordering of PDWN and FRES - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } - - // Perform USB peripheral reset - FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } - FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + fsdev_core_reset(); - // Wait startup time, for F042 and F070, this is <= 1 us. - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } FSDEV_REG->CNTR = 0; // Enable USB #if !defined(FSDEV_BUS_32BIT) @@ -197,8 +183,6 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; #endif - FSDEV_REG->ISTR = 0; // Clear pending interrupts - // Reset endpoints to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED. diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index d021a6abf..5c7df6809 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -31,6 +31,35 @@ #include "fsdev_common.h" +//--------------------------------------------------------------------+ +// Global +//--------------------------------------------------------------------+ + +// Reset the USB Core +void fsdev_core_reset(void) { + // Follow the RM mentions to use a special ordering of PDWN and FRES + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } + + // Perform USB peripheral reset + FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } + + FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + + // Wait startup time, for F042 and F070, this is <= 1 us. + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } + + // Clear pending interrupts + FSDEV_REG->ISTR = 0; +} + + //--------------------------------------------------------------------+ // PMA read/write //--------------------------------------------------------------------+ @@ -199,7 +228,7 @@ bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) // BTable Helper //--------------------------------------------------------------------+ -/* Aligned buffer size according to hardware */ +// Aligned buffer size according to hardware uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { /* The STM32 full speed USB peripheral supports only a limited set of * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ @@ -217,6 +246,7 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_bloc return (*num_block) * block_in_bytes; } +// Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { uint8_t blsize, num_block; (void) pma_align_buffer_size(wCount, &blsize, &num_block); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index e363245ec..9cf61031d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -311,9 +311,13 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_ #endif } -/* Aligned buffer size according to hardware */ +// Reset the USB Core +void fsdev_core_reset(void); + +// Aligned buffer size according to hardware uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); +// Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 362d7df7b..168366058 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -203,26 +203,9 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; - // Follow the RM mentions to use a special ordering of PDWN and FRES - for (volatile uint32_t i = 0; i < 200; i++) { - asm("NOP"); - } - - // Perform USB peripheral reset - FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; - for (volatile uint32_t i = 0; i < 200; i++) { - asm("NOP"); - } - - FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; - - // Wait startup time - for (volatile uint32_t i = 0; i < 200; i++) { - asm("NOP"); - } + fsdev_core_reset(); FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode - FSDEV_REG->ISTR = 0; // Clear pending interrupts // Reset channels to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { -- cgit v1.3.1 From 9742ba734f8ef780fb2b4c94848c4bd534afdafe Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 11:34:37 +0100 Subject: Add fsdev_deinit Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 8 ++++++++ src/portable/st/stm32_fsdev/fsdev_common.c | 15 +++++++++++++++ src/portable/st/stm32_fsdev/fsdev_common.h | 3 +++ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 8 ++++++++ 4 files changed, 34 insertions(+) (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 3c4e4fc9b..351916147 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -199,6 +199,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } +bool dcd_deinit(uint8_t rhport) { + (void)rhport; + + fsdev_deinit(); + + return true; +} + void dcd_sof_enable(uint8_t rhport, bool en) { (void)rhport; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 5c7df6809..d0f3460b6 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -59,6 +59,21 @@ void fsdev_core_reset(void) { FSDEV_REG->ISTR = 0; } +// De-initialize the USB Core +void fsdev_deinit(void) { + // Disable all interrupts and force USB reset + FSDEV_REG->CNTR = USB_CNTR_FRES; + + // Clear pending interrupts + FSDEV_REG->ISTR = 0; + + // Put USB peripheral in power down mode + FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + asm("NOP"); + } +} + //--------------------------------------------------------------------+ // PMA read/write diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 9cf61031d..0c67ee0c7 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -314,6 +314,9 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_ // Reset the USB Core void fsdev_core_reset(void); +// De-initialize the USB Core +void fsdev_deinit(void); + // Aligned buffer size according to hardware uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 168366058..39b9ac2d3 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -226,6 +226,14 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } +bool hcd_deinit(uint8_t rhport) { + (void)rhport; + + fsdev_deinit(); + + return true; +} + static void port_status_handler(uint8_t rhport, bool in_isr) { uint32_t const fnr_reg = FSDEV_REG->FNR; uint32_t const istr_reg = FSDEV_REG->ISTR; -- cgit v1.3.1 From a25e9e86c83785e8ce91b1c7b485a106195d368a Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 11:35:25 +0100 Subject: Remove redundant EP reg clear Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 10 +++------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 5 ----- 2 files changed, 3 insertions(+), 12 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 351916147..087639d4b 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -183,14 +183,10 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; #endif - // Reset endpoints to disabled - for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { - // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED. - ep_write(i, 0u, false); - } - + // Enable interrupts for device mode FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | - USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; + USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; + handle_bus_reset(rhport); // Enable pull-up if supported diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 39b9ac2d3..00c71ce6c 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -207,11 +207,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode - // Reset channels to disabled - for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { - ch_write(i, 0u, false); - } - tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Enable interrupts for host mode -- cgit v1.3.1 From b997ec725812d2f6a573610ba0dd817f271eddea Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 11:49:30 +0100 Subject: usbd: clear state and call callback on deinit Signed-off-by: Zixun LI --- src/device/usbd.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index d4dfae4b4..f923dfe08 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -587,6 +587,10 @@ bool tud_deinit(uint8_t rhport) { } } + // Clear device data + tu_varclr(&_usbd_dev); + usbd_control_reset(); + // Deinit device queue & task osal_queue_delete(_usbd_q); _usbd_q = NULL; @@ -598,6 +602,9 @@ bool tud_deinit(uint8_t rhport) { #endif _usbd_rhport = RHPORT_INVALID; + + tud_umount_cb(); + return true; } -- cgit v1.3.1 From 8914f402e5cdf372ade2ed1f4053ce14feffbeda Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 12:10:27 +0100 Subject: free previously allocated OUT endpoint if IN allocation failed Signed-off-by: Zixun LI --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 00c71ce6c..7d3deba34 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -516,7 +516,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const uint8_t const ep_type = ep_desc->bmAttributes.xfer; uint8_t const ep_id = endpoint_alloc(); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; edpt->dev_addr = dev_addr; @@ -530,7 +530,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const // EP0 is bi-directional, so we need to open both OUT and IN channels if (ep_addr == 0) { uint8_t const ep_id_in = endpoint_alloc(); - TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + if (ep_id_in == TUSB_INDEX_INVALID_8) { + // free previously allocated OUT endpoint + endpoint_dealloc(edpt); + TU_ASSERT(false); + } _hcd_data.edpt[ep_id_in] = *edpt; // copy from OUT endpoint _hcd_data.edpt[ep_id_in].ep_addr = 0 | TUSB_DIR_IN_MASK; @@ -543,13 +547,13 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); edpoint_close(ep_id); if (ep_addr == 0) { uint8_t const ep_id_in = endpoint_find(dev_addr, 0 | TUSB_DIR_IN_MASK); - TU_ASSERT(ep_id_in < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id_in != TUSB_INDEX_INVALID_8); edpoint_close(ep_id_in); } @@ -564,7 +568,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b TU_LOG(FSDEV_DEBUG, "hcd_edpt_xfer addr=%u ep=0x%02X len=%u\r\n", dev_addr, ep_addr, buflen); uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; @@ -579,7 +583,7 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; uint8_t const ep_id = endpoint_find(dev_addr, ep_addr); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); tusb_dir_t const dir = tu_edpt_dir(ep_addr); for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { @@ -602,7 +606,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet (void) rhport; uint8_t const ep_id = endpoint_find(dev_addr, 0); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; edpt->next_setup = true; @@ -618,7 +622,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) ep_addr; uint8_t const ep_id = endpoint_find(dev_addr, 0); - TU_ASSERT(ep_id < CFG_TUH_FSDEV_ENDPOINT_MAX); + TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8); hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; edpt->pid = 0; -- cgit v1.3.1 From e5d775def8927c564c8679f020a02e04d6676d3a Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 27 Nov 2025 19:11:21 +0100 Subject: usbh: detach existing device first if an attach event is received Signed-off-by: HiFiPhile --- src/host/usbh.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index c655702bd..55042b972 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -312,6 +312,7 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_class_driver_t const *get_driver(uint8_ // Function Inline and Prototypes //--------------------------------------------------------------------+ static bool enum_new_device(hcd_event_t* event); +static void process_detach_event(hcd_event_t* event); static void process_removed_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); @@ -605,6 +606,11 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: + // We have likely missed the hub detach event due to high traffic, detach the device first if exists + // Or due to physical debouncing, some devices can cause multiple attaches (actually reset) without detach event + // Force remove currently mounted with the same bus info (rhport, hub addr, hub port) if exists + process_detach_event(&event); + // due to the shared control buffer, we must fully complete enumerating one device first. // TODO better to have an separated queue for newly attached devices if (_usbh_data.enumerating_daddr == TUSB_INDEX_INVALID_8) { @@ -625,15 +631,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); - if (_usbh_data.enumerating_daddr == 0 && - event.rhport == _usbh_data.dev0_bus.rhport && - event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr && - event.connection.hub_port == _usbh_data.dev0_bus.hub_port) { - // dev0 is unplugged while enumerating (not yet assigned an address) - usbh_device_close(_usbh_data.dev0_bus.rhport, 0); - } else { - process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); - } + process_detach_event(&event); break; case HCD_EVENT_XFER_COMPLETE: { @@ -1314,6 +1312,20 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, //--------------------------------------------------------------------+ // Detaching //--------------------------------------------------------------------+ + +// process detach event from rhport:hub_addr:hub_port +static void process_detach_event(hcd_event_t* event) { + if (_usbh_data.enumerating_daddr == 0 && + event->rhport == _usbh_data.dev0_bus.rhport && + event->connection.hub_addr == _usbh_data.dev0_bus.hub_addr && + event->connection.hub_port == _usbh_data.dev0_bus.hub_port) { + // dev0 is unplugged while enumerating (not yet assigned an address) + usbh_device_close(_usbh_data.dev0_bus.rhport, 0); + } else { + process_removed_device(event->rhport, event->connection.hub_addr, event->connection.hub_port); + } +} + // a device unplugged from rhport:hub_addr:hub_port static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { // Find the all devices (star-network) under port that is unplugged @@ -1589,10 +1601,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_SET_ADDR: { - // Due to physical debouncing, some devices can cause multiple attaches (actually reset) without detach event - // Force remove currently mounted with the same bus info (rhport, hub addr, hub port) if exists - process_removed_device(dev0_bus->rhport, dev0_bus->hub_addr, dev0_bus->hub_port); - const tusb_desc_device_t *desc_device = (const tusb_desc_device_t *) _usbh_epbuf.ctrl; const uint8_t new_addr = enum_get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); TU_ASSERT(new_addr != 0,); -- cgit v1.3.1 From 07ff25eb1e9871082b92161296725c5d312d3558 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 27 Nov 2025 17:17:03 +0100 Subject: Add max nak config Signed-off-by: Zixun LI --- src/host/usbh.h | 9 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 203 +++++++++++++++++--------- 2 files changed, 140 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/host/usbh.h b/src/host/usbh.h index 4b6747848..697c911ff 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -95,18 +95,23 @@ enum { TUH_CFGID_INVALID = 0, TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t TUH_CFGID_MAX3421 = 200, + TUH_CFGID_FSDEV = 300, }; typedef struct { - uint8_t max_nak; // max NAK per endpoint per frame to save CPU/SPI bus usage + uint8_t max_nak; // max NAK per endpoint per frame to save CPU/SPI bus usage (0=unlimited) uint8_t cpuctl; // R16: CPU Control Register uint8_t pinctl; // R17: Pin Control Register. FDUPSPI bit is ignored } tuh_configure_max3421_t; +typedef struct { + uint8_t max_nak; // max NAK per endpoint per frame to save CPU usage (0=unlimited) +} tuh_configure_fsdev_t; + typedef union { // For TUH_CFGID_RPI_PIO_USB_CONFIGURATION use pio_usb_configuration_t - tuh_configure_max3421_t max3421; + tuh_configure_fsdev_t fsdev; } tuh_configure_param_t; //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 7d3deba34..ff2f2946e 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -60,48 +60,56 @@ TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); enum { - HCD_XFER_ERROR_MAX = 3 + HCD_XFER_ERROR_MAX = 3, + HCD_XFER_NAK_MAX = 15, + HCD_XFER_NAK_DEFAULT = 3, }; // Host driver struct for each opened endpoint typedef struct { uint8_t *buffer; uint16_t buflen; + uint16_t queued_len; uint16_t max_packet_size; uint8_t dev_addr; uint8_t ep_addr; uint8_t ep_type; uint8_t interval; struct TU_ATTR_PACKED { - uint8_t low_speed : 1; + uint8_t ls_pre : 1; uint8_t allocated : 1; uint8_t next_setup : 1; uint8_t pid : 1; }; } hcd_endpoint_t; +// Channel direction state +typedef struct { + hcd_endpoint_t* edpt; + struct TU_ATTR_PACKED { + uint8_t allocated : 1; + uint8_t retry : 3; + uint8_t nak : 4; // Max NAK count in current frame + }; +} hcd_channel_dir_t; + // Additional info for each channel when it is active typedef struct { - hcd_endpoint_t* edpt[2]; // OUT/IN - uint16_t queued_len[2]; uint8_t dev_addr; uint8_t ep_num; uint8_t ep_type; - uint8_t allocated[2]; - uint8_t retry[2]; + hcd_channel_dir_t out, in; } hcd_channel_t; -// Root hub port state static struct { - bool connected; -} _hcd_port; - -typedef struct { hcd_channel_t channel[FSDEV_EP_COUNT]; hcd_endpoint_t edpt[CFG_TUH_FSDEV_ENDPOINT_MAX]; -} hcd_data_t; + bool connected; +} _hcd_data; -hcd_data_t _hcd_data; +static tuh_configure_fsdev_t _tuh_cfg = { + .max_nak = HCD_XFER_NAK_DEFAULT, +}; //--------------------------------------------------------------------+ // Prototypes @@ -114,7 +122,6 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) static bool edpt_xfer_kickoff(uint8_t ep_id); static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); static void edpoint_close(uint8_t ep_id); -static void port_status_handler(uint8_t rhport, bool in_isr); static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); @@ -129,7 +136,11 @@ static inline void endpoint_dealloc(hcd_endpoint_t* edpt) { } static inline void channel_dealloc(hcd_channel_t* ch, tusb_dir_t dir) { - ch->allocated[dir] = 0; + if (dir == TUSB_DIR_OUT) { + ch->out.allocated = 0; + } else { + ch->in.allocated = 0; + } } // Write channel state in specified direction @@ -194,9 +205,11 @@ static inline uint16_t channel_get_rx_count(uint8_t ch_id) { // Optional HCD configuration, called by tuh_configure() bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { (void) rhport; - (void) cfg_id; - (void) cfg_param; - return false; + TU_VERIFY(cfg_id == TUH_CFGID_FSDEV && cfg_param != NULL); + + tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param; + _tuh_cfg.max_nak = tu_min8(cfg->fsdev.max_nak, HCD_XFER_NAK_MAX); + return true; } // Initialize controller to host mode @@ -210,11 +223,11 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Enable interrupts for host mode - FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | + FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SOFM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM; // Initialize port state - _hcd_port.connected = false; + _hcd_data.connected = false; fsdev_connect(rhport); @@ -229,35 +242,48 @@ bool hcd_deinit(uint8_t rhport) { return true; } -static void port_status_handler(uint8_t rhport, bool in_isr) { +//--------------------------------------------------------------------+ +// Interrupt Helper Functions +//--------------------------------------------------------------------+ + +static inline void sof_handler(void) { + // Reset NAK counters for all active channels + for (uint8_t ch_id = 0; ch_id < FSDEV_EP_COUNT; ch_id++) { + hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + if (channel->out.allocated) { + channel->out.nak = 0; + } + if (channel->in.allocated) { + channel->in.nak = 0; + } + } +} + +static inline void port_status_handler(uint8_t rhport, bool in_isr) { uint32_t const fnr_reg = FSDEV_REG->FNR; uint32_t const istr_reg = FSDEV_REG->ISTR; // SE0 detected USB Disconnected state if ((fnr_reg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U) { - _hcd_port.connected = false; + _hcd_data.connected = false; hcd_event_device_remove(rhport, in_isr); return; } - if (!_hcd_port.connected) { + if (!_hcd_data.connected) { // J-state or K-state detected & LastState=Disconnected if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { - _hcd_port.connected = true; + _hcd_data.connected = true; hcd_event_device_attach(rhport, in_isr); } } else { // J-state or K-state detected & lastState=Connected: a Missed disconnection is detected if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) { - _hcd_port.connected = false; + _hcd_data.connected = false; hcd_event_device_remove(rhport, in_isr); } } } -//--------------------------------------------------------------------+ -// Interrupt Helper Functions -//--------------------------------------------------------------------+ - // Handle ACK response static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; @@ -271,38 +297,40 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { // OUT/TX direction - if (edpt->buflen != channel->queued_len[TUSB_DIR_OUT]) { + if (edpt->buflen != edpt->queued_len) { // More data to send - uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - channel->queued_len[TUSB_DIR_OUT] += len; + edpt->queued_len += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); + channel->out.nak = 0; } else { // Transfer complete channel_dealloc(channel, TUSB_DIR_OUT); edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num, channel->queued_len[TUSB_DIR_OUT], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num, edpt->queued_len, XFER_RESULT_SUCCESS, true); } } else { // IN/RX direction uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - fsdev_read_packet_memory(edpt->buffer + channel->queued_len[TUSB_DIR_IN], pma_addr, rx_count); - channel->queued_len[TUSB_DIR_IN] += rx_count; + fsdev_read_packet_memory(edpt->buffer + edpt->queued_len, pma_addr, rx_count); + edpt->queued_len += rx_count; - if ((rx_count < edpt->max_packet_size) || (channel->queued_len[TUSB_DIR_IN] >= edpt->buflen)) { + if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) { // Transfer complete (short packet or all bytes received) channel_dealloc(channel, TUSB_DIR_IN); edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0; - hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, channel->queued_len[TUSB_DIR_IN], XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, edpt->queued_len, XFER_RESULT_SUCCESS, true); } else { // More data expected - uint16_t const cnt = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_IN], edpt->max_packet_size); + uint16_t const cnt = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt); channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false); + channel->in.nak = 0; } } } @@ -316,10 +344,17 @@ static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { if (ep_id == TUSB_INDEX_INVALID_8) return; hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - // Retry non-periodic transfer immediately, + // Retry non-periodic transfer immediately if NAK count not exceeded // Periodic transfer will be retried by next frame automatically if (edpt->ep_type == TUSB_XFER_CONTROL || edpt->ep_type == TUSB_XFER_BULK) { - channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false); + hcd_channel_dir_t* channel_dir = + (dir == TUSB_DIR_OUT) ? &(_hcd_data.channel[ch_id].out) : &(_hcd_data.channel[ch_id].in); + if (channel_dir->nak < HCD_XFER_NAK_MAX) { + channel_dir->nak++; + } + if (channel_dir->nak < _tuh_cfg.max_nak || _tuh_cfg.max_nak == 0) { + channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false); + } } } @@ -328,13 +363,17 @@ static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD; uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; + uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); + if (ep_id == TUSB_INDEX_INVALID_8) return; + + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; channel_dealloc(channel, dir); channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - channel->queued_len[dir], XFER_RESULT_STALLED, true); + edpt->queued_len, XFER_RESULT_STALLED, true); } // Handle error response @@ -345,21 +384,24 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); if (ep_id == TUSB_INDEX_INVALID_8) return; + hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir); ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX); - if (channel->retry[dir] < HCD_XFER_ERROR_MAX) { + hcd_channel_dir_t* channel_dir = + (dir == TUSB_DIR_OUT) ? &(_hcd_data.channel[ch_id].out) : &(_hcd_data.channel[ch_id].in); + if (channel_dir->retry < HCD_XFER_ERROR_MAX) { // Retry - channel->retry[dir]++; + channel_dir->retry++; ch_change_status(&ch_reg, dir, EP_STAT_VALID); } else { // Failed after retries channel_dealloc(channel, dir); ch_change_status(&ch_reg, dir, EP_STAT_DISABLED); hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0), - channel->queued_len[dir], XFER_RESULT_FAILED, true); + edpt->queued_len, XFER_RESULT_FAILED, true); } ch_write(ch_id, ch_reg, false); } @@ -368,7 +410,7 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { static inline void handle_ctr_tx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - TU_VERIFY(channel->allocated[TUSB_DIR_OUT] == 1,); + TU_VERIFY(channel->out.allocated == 1,); if ((ch_reg & USB_CH_ERRTX) == 0U) { // No error @@ -388,7 +430,7 @@ static inline void handle_ctr_tx(uint32_t ch_id) { static inline void handle_ctr_rx(uint32_t ch_id) { uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - TU_VERIFY(channel->allocated[TUSB_DIR_IN] == 1,); + TU_VERIFY(channel->in.allocated == 1,); if ((ch_reg & USB_CH_ERRRX) == 0U) { // No error @@ -408,7 +450,13 @@ static inline void handle_ctr_rx(uint32_t ch_id) { void hcd_int_handler(uint8_t rhport, bool in_isr) { uint32_t int_status = FSDEV_REG->ISTR; - /* Port Change Detected (Connection/Disconnection) */ + // Start of Frame + if (int_status & USB_ISTR_SOF) { + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; + sof_handler(); + } + + // Port Change Detected (Connection/Disconnection) if (int_status & USB_ISTR_DCON) { FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_DCON; port_status_handler(rhport, in_isr); @@ -464,7 +512,7 @@ uint32_t hcd_frame_number(uint8_t rhport) { // Get the current connect status of roothub port bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; - return _hcd_port.connected; + return _hcd_data.connected; } // Reset USB bus on the port @@ -525,7 +573,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const edpt->max_packet_size = packet_size; edpt->interval = ep_desc->bInterval; edpt->pid = 0; - edpt->low_speed = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; + edpt->ls_pre = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; // EP0 is bi-directional, so we need to open both OUT and IN channels if (ep_addr == 0) { @@ -574,6 +622,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b edpt->buffer = buffer; edpt->buflen = buflen; + edpt->queued_len = 0; return edpt_xfer_kickoff(ep_id); } @@ -588,8 +637,9 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_channel_t* channel = &_hcd_data.channel[i]; + uint8_t const allocated = (dir == TUSB_DIR_OUT) ? channel->out.allocated : channel->in.allocated; - if (channel->allocated[dir] == 1 && + if (allocated == 1 && channel->dev_addr == dev_addr && channel->ep_num == tu_edpt_number(ep_addr)) { channel_dealloc(channel, dir); @@ -664,11 +714,11 @@ static void edpoint_close(uint8_t ep_id) { for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { hcd_channel_t* channel = &_hcd_data.channel[i]; uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX; - if (channel->allocated[TUSB_DIR_OUT] == 1 && channel->edpt[TUSB_DIR_OUT] == edpt) { + if (channel->out.allocated == 1 && channel->out.edpt == edpt) { channel_dealloc(channel, TUSB_DIR_OUT); channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true); } - if (channel->allocated[TUSB_DIR_IN] == 1 && channel->edpt[TUSB_DIR_IN] == edpt) { + if (channel->in.allocated == 1 && channel->in.edpt == edpt) { channel_dealloc(channel, TUSB_DIR_IN); channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true); } @@ -697,27 +747,37 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) // Find channel allocate for same ep_num but other direction tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN; for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.channel[i].allocated[dir] == 0 && - _hcd_data.channel[i].allocated[other_dir] == 1 && + uint8_t const allocated_dir = (dir == TUSB_DIR_OUT) ? _hcd_data.channel[i].out.allocated : _hcd_data.channel[i].in.allocated; + uint8_t const allocated_other = (other_dir == TUSB_DIR_OUT) ? _hcd_data.channel[i].out.allocated : _hcd_data.channel[i].in.allocated; + if (allocated_dir == 0 && + allocated_other == 1 && _hcd_data.channel[i].dev_addr == dev_addr && _hcd_data.channel[i].ep_num == ep_num && _hcd_data.channel[i].ep_type == ep_type) { - _hcd_data.channel[i].allocated[dir] = 1; - _hcd_data.channel[i].queued_len[dir] = 0; - _hcd_data.channel[i].retry[dir] = 0; + if (dir == TUSB_DIR_OUT) { + _hcd_data.channel[i].out.allocated = 1; + _hcd_data.channel[i].out.retry = 0; + } else { + _hcd_data.channel[i].in.allocated = 1; + _hcd_data.channel[i].in.retry = 0; + } return i; } } // Find free channel for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { - if (_hcd_data.channel[i].allocated[0] == 0 && _hcd_data.channel[i].allocated[1] == 0) { + if (_hcd_data.channel[i].out.allocated == 0 && _hcd_data.channel[i].in.allocated == 0) { _hcd_data.channel[i].dev_addr = dev_addr; _hcd_data.channel[i].ep_num = ep_num; _hcd_data.channel[i].ep_type = ep_type; - _hcd_data.channel[i].allocated[dir] = 1; - _hcd_data.channel[i].queued_len[dir] = 0; - _hcd_data.channel[i].retry[dir] = 0; + if (dir == TUSB_DIR_OUT) { + _hcd_data.channel[i].out.allocated = 1; + _hcd_data.channel[i].out.retry = 0; + } else { + _hcd_data.channel[i].in.allocated = 1; + _hcd_data.channel[i].in.retry = 0; + } return i; } } @@ -733,16 +793,19 @@ static bool edpt_xfer_kickoff(uint8_t ep_id) { TU_ASSERT(ch_id != TUSB_INDEX_INVALID_8); // all channel are in used tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); - hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - channel->edpt[dir] = edpt; + if (dir == TUSB_DIR_OUT) { + channel->out.edpt = edpt; + } else { + channel->in.edpt = edpt; + } return channel_xfer_start(ch_id, dir); } static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { hcd_channel_t* channel = &_hcd_data.channel[ch_id]; - hcd_endpoint_t* edpt = channel->edpt[dir]; + hcd_endpoint_t* edpt = (dir == TUSB_DIR_OUT) ? channel->out.edpt : channel->in.edpt; uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK; ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos | @@ -771,28 +834,28 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { btable_set_addr(ch_id, dir == TUSB_DIR_OUT ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); if (dir == TUSB_DIR_OUT) { - uint16_t const len = tu_min16(edpt->buflen - channel->queued_len[TUSB_DIR_OUT], edpt->max_packet_size); + uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[channel->queued_len[TUSB_DIR_OUT]]), len); + fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); - channel->queued_len[TUSB_DIR_OUT] += len; + edpt->queued_len += len; } else { btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size); } - if (edpt->low_speed == 1) { + if (edpt->ls_pre == 1) { ch_reg |= USB_CHEP_LSEP; } else { ch_reg &= ~USB_CHEP_LSEP; } + // Setup DATA/STATUS phase start with DATA1 if (tu_edpt_number(edpt->ep_addr) == 0) { edpt->pid = 1; } if (edpt->next_setup) { - // Setup packet uses IN token edpt->next_setup = false; ch_reg |= USB_EP_SETUP; edpt->pid = 0; -- cgit v1.3.1 From c6b94db2990bf9975650c2879f4aabdade6f90d0 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 28 Nov 2025 00:11:08 +0100 Subject: Use one endpoint for EP0 Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 35 +++++++++++---------------- 1 file changed, 14 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index ff2f2946e..22a74efbe 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -575,19 +575,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const edpt->pid = 0; edpt->ls_pre = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0; - // EP0 is bi-directional, so we need to open both OUT and IN channels - if (ep_addr == 0) { - uint8_t const ep_id_in = endpoint_alloc(); - if (ep_id_in == TUSB_INDEX_INVALID_8) { - // free previously allocated OUT endpoint - endpoint_dealloc(edpt); - TU_ASSERT(false); - } - - _hcd_data.edpt[ep_id_in] = *edpt; // copy from OUT endpoint - _hcd_data.edpt[ep_id_in].ep_addr = 0 | TUSB_DIR_IN_MASK; - } - return true; } @@ -599,13 +586,6 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { edpoint_close(ep_id); - if (ep_addr == 0) { - uint8_t const ep_id_in = endpoint_find(dev_addr, 0 | TUSB_DIR_IN_MASK); - TU_ASSERT(ep_id_in != TUSB_INDEX_INVALID_8); - - edpoint_close(ep_id_in); - } - return true; } @@ -624,6 +604,12 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b edpt->buflen = buflen; edpt->queued_len = 0; + uint8_t const ep_num = tu_edpt_number(ep_addr); + if (ep_num == 0) { + // update ep_dir since control endpoint can switch direction + edpt->ep_addr = ep_addr; + } + return edpt_xfer_kickoff(ep_id); } @@ -696,9 +682,16 @@ static uint8_t endpoint_alloc(void) { } static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr); + for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; - if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && edpt->ep_addr == ep_addr) { + tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr); + uint8_t const num = tu_edpt_number(edpt->ep_addr); + // Match both ep_num and ep_dir, or match ep_num 0 (control endpoint) + if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && num == ep_num && + (dir == ep_dir || ep_num == 0)) { return i; } } -- cgit v1.3.1 From 1ffe00b4363fc2d76751270118091fc3a3a1b92b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 28 Nov 2025 13:18:10 +0100 Subject: Fix deinit glitch Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/fsdev_common.c | 5 --- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 47 +++++++++++++++++---------- 2 files changed, 30 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 4f95d9d7f..60ef339a6 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -37,11 +37,6 @@ // Reset the USB Core void fsdev_core_reset(void) { - // Follow the RM mentions to use a special ordering of PDWN and FRES - for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); - } - // Perform USB peripheral reset FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 22a74efbe..212f620ac 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -59,6 +59,20 @@ TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); +#if CFG_TUSB_MCU == OPT_MCU_STM32H5 + #define CPU_FREQUENCY_MHZ 250U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #define CPU_FREQUENCY_MHZ 160U +#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #define CPU_FREQUENCY_MHZ 96U +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #define CPU_FREQUENCY_MHZ 64U +#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 + #define CPU_FREQUENCY_MHZ 48U +#else + #error "CPU_FREQUENCY_MHZ not defined for this STM32 MCU" +#endif + enum { HCD_XFER_ERROR_MAX = 3, HCD_XFER_NAK_MAX = 15, @@ -122,6 +136,7 @@ static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) static bool edpt_xfer_kickoff(uint8_t ep_id); static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir); static void edpoint_close(uint8_t ep_id); +static void port_status_handler(uint8_t rhport, bool in_isr); static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir); @@ -166,30 +181,16 @@ static inline uint16_t channel_get_rx_count(uint8_t ch_id) { * We choose the delay count based on max CPU frequency (in MHz) to ensure the delay is at least the required time. */ -#if CFG_TUSB_MCU == OPT_MCU_STM32H5 - #define FREQUENCY_MHZ 250U -#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #define FREQUENCY_MHZ 160U -#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 - #define FREQUENCY_MHZ 96U -#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #define FREQUENCY_MHZ 64U -#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - #define FREQUENCY_MHZ 48U -#else - #error "FREQUENCY_MHZ not defined for this STM32 MCU" -#endif - uint32_t ch_reg = ch_read(ch_id); if (FSDEV_REG->ISTR & USB_ISTR_LS_DCONN || ch_reg & USB_CHEP_LSEP) { // Low speed mode: 6.4 us delay -> about 2 cycles per MHz - volatile uint32_t cycle_count = FREQUENCY_MHZ * 2U; + volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ * 2U; while (cycle_count > 0U) { cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) } } else { // Full speed mode: 800 ns delay -> about 0.25 cycles per MHz - volatile uint32_t cycle_count = FREQUENCY_MHZ / 4U; + volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U; while (cycle_count > 0U) { cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) } @@ -231,12 +232,24 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { fsdev_connect(rhport); + // If DCON_STAT is already set, the controller sometimes misses the initial connection interrupt + if (FSDEV_REG->ISTR & USB_ISTR_DCON_STAT) { + // Wait DP/DM stabilize time + volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U; + while (cycle_count > 0U) { + cycle_count--; + } + port_status_handler(rhport, false); + } + return true; } bool hcd_deinit(uint8_t rhport) { (void)rhport; + fsdev_disconnect(rhport); + fsdev_deinit(); return true; @@ -259,7 +272,7 @@ static inline void sof_handler(void) { } } -static inline void port_status_handler(uint8_t rhport, bool in_isr) { +static void port_status_handler(uint8_t rhport, bool in_isr) { uint32_t const fnr_reg = FSDEV_REG->FNR; uint32_t const istr_reg = FSDEV_REG->ISTR; // SE0 detected USB Disconnected state -- cgit v1.3.1 From 97c5151b34158f08fbfb51684cbfbc807abd77e5 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 28 Nov 2025 13:27:09 +0100 Subject: Update note Signed-off-by: HiFiPhile --- README.rst | 264 +++++++++++++++++++++++++++--------------------------- src/device/usbd.h | 2 + src/host/usbh.h | 2 + 3 files changed, 136 insertions(+), 132 deletions(-) (limited to 'src') diff --git a/README.rst b/README.rst index ef19b0ccd..75f93f656 100644 --- a/README.rst +++ b/README.rst @@ -129,138 +129,138 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) Supported CPUs -------------- -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Manufacturer | Family | Device | Host | Highspeed | Driver | Note | -+==============+=============================+========+======+===========+========================+===================+ -| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | -| | MAX78002 | | | | | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | -| ESP32 +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | P4 | ✔ | ✔ | ✔ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | H4 | ✔ | ✔ | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | | -| | +-----------------------+--------+------+-----------+------------------------+-------------------+ -| | | D51, E5x | ✔ | | ✖ | samd | | -| | +-----------------------+--------+------+-----------+------------------------+-------------------+ -| | | G55 | ✔ | | ✖ | samg | 1-dir ep | -| | +-----------------------+--------+------+-----------+------------------------+-------------------+ -| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep | -| +-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| | PIC | 24 | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+-------------------+ -| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+-------------------+ -| | | dsPIC33 | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+-------------------+ -| | | 32mz | ✔ | | | pic32mz | musb variant | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is ISO | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | NUC121/NUC125 | ✔ | ✖ | ✖ | nuc121 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | NUC126 | ✔ | ✖ | ✖ | nuc121 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | NUC505 | ✔ | | ✔ | nuc505 | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | -| +---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | -| | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant | -| +---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | -| | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | -| | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | -| | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | -| | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | -| +---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | -| | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | A15 | ✔ | | | ci_fs | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | -| +-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | | -| | +-----------------------+--------+------+-----------+------------------------+-------------------+ -| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | | -| | +------------------------+--------+------+-----------+------------------------+-------------------+ -| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | C0, G0, H5 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0 | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | -| | +------------------------+--------+------+-----------+------------------------+-------------------+ -| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | N6 | ✔ | ✔ | ✔ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | U3 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0 | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0 | -| | +------------------------+--------+------+-----------+------------------------+-------------------+ -| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | -| | +------------------------+--------+------+-----------+------------------------+-------------------+ -| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | | -+--------------+----+------------------------+--------+------+-----------+------------------------+-------------------+ -| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Manufacturer | Family | Device | Host | Highspeed | Driver | Note | ++==============+=============================+========+======+===========+========================+========================+ +| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | +| | MAX78002 | | | | | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | +| ESP32 +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | P4 | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | H4 | ✔ | ✔ | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ +| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | | +| | +-----------------------+--------+------+-----------+------------------------+------------------------+ +| | | D51, E5x | ✔ | | ✖ | samd | | +| | +-----------------------+--------+------+-----------+------------------------+------------------------+ +| | | G55 | ✔ | | ✖ | samg | 1-dir ep | +| | +-----------------------+--------+------+-----------+------------------------+------------------------+ +| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep | +| +-----+-----------------------+--------+------+-----------+------------------------+------------------------+ +| | PIC | 24 | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+------------------------+ +| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+------------------------+ +| | | dsPIC33 | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+------------------------+ +| | | 32mz | ✔ | | | pic32mz | musb variant | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ +| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ +| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is IO | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | NUC121/NUC125 | ✔ | ✖ | ✖ | nuc121 | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | NUC126 | ✔ | ✖ | ✖ | nuc121 | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | NUC505 | ✔ | | ✔ | nuc505 | | ++--------------+---------+-------------------+--------+------+-----------+------------------------+------------------------+ +| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | +| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ +| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | +| | +-------------------+--------+------+-----------+------------------------+------------------------+ +| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant | +| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ +| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------------+--------+------+-----------+------------------------+------------------------+ +| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | +| | +-------------------+--------+------+-----------+------------------------+------------------------+ +| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | +| | +-------------------+--------+------+-----------+------------------------+------------------------+ +| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------------+--------+------+-----------+------------------------+------------------------+ +| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | +| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ +| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | +| | +-------------------+--------+------+-----------+------------------------+------------------------+ +| | | A15 | ✔ | | | ci_fs | | ++--------------+---------+-------------------+--------+------+-----------+------------------------+------------------------+ +| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ +| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | +| +-----+-----------------------+--------+------+-----------+------------------------+------------------------+ +| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | | +| | +-----------------------+--------+------+-----------+------------------------+------------------------+ +| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ +| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+------------------------+ +| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | +------------------------+--------+------+-----------+------------------------+------------------------+ +| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | +| +----+------------------------+--------+------+-----------+------------------------+------------------------+ +| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | C0, G0, H5 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+------------------------+ +| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | +------------------------+--------+------+-----------+------------------------+------------------------+ +| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | +| +----+------------------------+--------+------+-----------+------------------------+------------------------+ +| | N6 | ✔ | ✔ | ✔ | dwc2 | | +| +----+------------------------+--------+------+-----------+------------------------+------------------------+ +| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+------------------------+ +| | U3 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | +| +----+------------------------+--------+------+-----------+------------------------+------------------------+ +| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | +| | +------------------------+--------+------+-----------+------------------------+------------------------+ +| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | +| | +------------------------+--------+------+-----------+------------------------+------------------------+ +| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | | ++--------------+----+------------------------+--------+------+-----------+------------------------+------------------------+ +| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ +| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | | +| +-----------------------------+--------+------+-----------+------------------------+------------------------+ +| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | | ++--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ Table Legend ^^^^^^^^^^^^ diff --git a/src/device/usbd.h b/src/device/usbd.h index c446638c3..3cf195452 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -38,6 +38,7 @@ extern "C" { //--------------------------------------------------------------------+ // New API to replace tud_init() to init device stack on specific roothub port +// Must be called in the same task/context as tud_task() if RTOS is used bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init); // Init device stack on roothub port @@ -53,6 +54,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_init (uint8_t rhport) { } // Deinit device stack on roothub port +// Must be called in the same task/context as tud_task() if RTOS is used bool tud_deinit(uint8_t rhport); // Check if device stack is already initialized diff --git a/src/host/usbh.h b/src/host/usbh.h index 697c911ff..d86efbcb2 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -150,6 +150,7 @@ void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param); // New API to replace tuh_init() to init host stack on specific roothub port +// Must be called in the same task/context as tuh_task() if RTOS is used bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init); // Init host stack @@ -165,6 +166,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_init(uint8_t rhport) { } // Deinit host stack on rhport +// Must be called in the same task/context as tuh_task() if RTOS is used bool tuh_deinit(uint8_t rhport); // Check if host stack is already initialized with any roothub ports -- cgit v1.3.1 From a412a8e50d07fc789ea598f101a94570b1f33fc4 Mon Sep 17 00:00:00 2001 From: gab-k Date: Wed, 10 Dec 2025 23:04:39 +0100 Subject: hw/mcu: add support for NXP RW612 --- README.rst | 4 ++- src/common/tusb_mcu.h | 8 ++++++ src/portable/chipidea/ci_hs/ci_hs_rw61x.h | 48 +++++++++++++++++++++++++++++++ src/portable/chipidea/ci_hs/dcd_ci_hs.c | 3 ++ src/portable/ehci/ehci.c | 2 +- src/tusb_option.h | 1 + 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/portable/chipidea/ci_hs/ci_hs_rw61x.h (limited to 'src') diff --git a/README.rst b/README.rst index 6a6f07825..463cc8b42 100644 --- a/README.rst +++ b/README.rst @@ -208,7 +208,9 @@ Supported CPUs | | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | A15 | ✔ | | | ci_fs | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ +| +---------+-------------------+--------+------+-----------+------------------------+-------------------+ +| | RW61x | ✔ | | ✔ | ci_hs, ehci | | ++--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | +--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ | Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1e773bf96..89316ee77 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -111,6 +111,14 @@ #define TUP_DCD_ENDPOINT_MAX 16 +#elif TU_CHECK_MCU(OPT_MCU_RW61X) + // USB0 is chipidea HS + #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_MIMXRT1XXX) #include "fsl_device_registers.h" diff --git a/src/portable/chipidea/ci_hs/ci_hs_rw61x.h b/src/portable/chipidea/ci_hs/ci_hs_rw61x.h new file mode 100644 index 000000000..114fe26c3 --- /dev/null +++ b/src/portable/chipidea/ci_hs/ci_hs_rw61x.h @@ -0,0 +1,48 @@ +/* + * 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_RW61X_H_ +#define _CI_HS_RW61X_H_ + +#include "fsl_device_registers.h" + +static const ci_hs_controller_t _ci_controller[] = { + {.reg_base = USBOTG_BASE, .irqnum = USB_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/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 4a5e5c91f..27298989c 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -55,6 +55,9 @@ bool dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { // MCX N9 only port 1 use this controller #include "ci_hs_mcx.h" +#elif TU_CHECK_MCU(OPT_MCU_RW61X) + #include "ci_hs_rw61x.h" + #else #error "Unsupported MCUs" #endif diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index c33c970e4..e604a0360 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -40,7 +40,7 @@ #include "ehci.h" // NXP specific fixes -#if TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX, OPT_MCU_LPC55, OPT_MCU_MCXN9) +#if TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX, OPT_MCU_LPC55, OPT_MCU_MCXN9, OPT_MCU_RW61X) #include "fsl_device_registers.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index be954e01a..68f2d3598 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -199,6 +199,7 @@ // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series #define OPT_MCU_MCXA15 2301 ///< NXP MCX A15 Series +#define OPT_MCU_RW61X 2302 ///< NXP RW61x Series // Analog Devices #define OPT_MCU_MAX32690 2400 ///< ADI MAX32690 -- cgit v1.3.1 From b43b99a571e81fb99f6603d9534f7d4bb55e8d02 Mon Sep 17 00:00:00 2001 From: gab-k Date: Sun, 14 Dec 2025 01:30:12 +0100 Subject: bsp: nxp: add support for RW612 (FRDM-RW612) - Added `rw61x` family support. - Added `frdm_rw612` board support. - Update `get_deps.py` to include mcux-sdk for RW61x. - Add ci_hs_rw61x include to ChipIdea HS driver and enable host examples. --- examples/host/bare_api/only.txt | 1 + examples/host/cdc_msc_hid/only.txt | 1 + examples/host/cdc_msc_hid_freertos/only.txt | 1 + examples/host/device_info/only.txt | 1 + examples/host/hid_controller/only.txt | 1 + examples/host/midi_rx/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h | 150 +++++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/board.cmake | 30 ++++ hw/bsp/rw61x/boards/frdm_rw612/board.h | 76 +++++++++ hw/bsp/rw61x/boards/frdm_rw612/board.mk | 20 +++ hw/bsp/rw61x/boards/frdm_rw612/clock_config.c | 170 ++++++++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/clock_config.h | 116 ++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c | 223 ++++++++++++++++++++++++++ hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h | 146 +++++++++++++++++ hw/bsp/rw61x/family.c | 135 ++++++++++++++++ hw/bsp/rw61x/family.cmake | 102 ++++++++++++ hw/bsp/rw61x/family.mk | 52 ++++++ src/portable/chipidea/ci_hs/hcd_ci_hs.c | 3 + tools/get_deps.py | 4 +- 20 files changed, 1232 insertions(+), 2 deletions(-) create mode 100644 hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/board.cmake create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/board.h create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/board.mk create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/clock_config.c create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/clock_config.h create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c create mode 100644 hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h create mode 100644 hw/bsp/rw61x/family.c create mode 100644 hw/bsp/rw61x/family.cmake create mode 100644 hw/bsp/rw61x/family.mk (limited to 'src') diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index ef0a1ac96..5c5b7c56d 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -6,6 +6,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:MSP432E4 mcu:RX65X mcu:MAX3421 diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 61a08f68d..892cbf4b8 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -9,6 +9,7 @@ mcu:MAX3421 mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:MSP432E4 mcu:RP2040 mcu:RX65X diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index 133a7c9a0..ff9c0bcb8 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -12,6 +12,7 @@ mcu:MAX3421 mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:MSP432E4 mcu:RP2040 mcu:RX65X diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index cba58f8e8..1c9ae72eb 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -8,6 +8,7 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:RW61X mcu:RP2040 mcu:MSP432E4 mcu:RX65X diff --git a/hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..281b4d40c --- /dev/null +++ b/hw/bsp/rw61x/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * 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. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "fsl_device_registers.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 // RW61x has FPU but is disabled due to using cortex-m33-nodsp-nofp.mk +#define configENABLE_TRUSTZONE 0 +#define configRUN_FREERTOS_SECURE_ONLY 1 // Cortex-M33 runs in secure mode after reset by default! +#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 4 +#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 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* 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 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* 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 + +/* 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<CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0U) + { + /* Enable the CAU sleep clock. */ + CLOCK_EnableClock(kCLOCK_RefClkCauSlp); + } + if ((SYSCTL2->SOURCE_CLK_GATE & SYSCTL2_SOURCE_CLK_GATE_REFCLK_SYS_CG_MASK) != 0U) + { + /* Enable the REFCLK_SYS clock. */ + CLOCK_EnableClock(kCLOCK_RefClkSys); + } + /* Initialize T3 PLL and enable outputs that are not clock gated. */ + CLOCK_InitT3RefClk(kCLOCK_T3MciIrc48m); + /* Enable FFRO - T3 PLL 48/60 MHz IRC clock output */ + CLOCK_EnableClock(kCLOCK_T3PllMciIrcClk); + /* Enable T3 PLL 256 MHz clock output */ + CLOCK_EnableClock(kCLOCK_T3PllMci256mClk); + /* Set core clock to safe system oscillator clock for initialization of other sources. */ + CLOCK_AttachClk(kSYSOSC_to_MAIN_CLK); + CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1); + /* Enable TCPU PLL MCI clock output */ + CLOCK_EnableClock(kCLOCK_TcpuMciClk); + /* Initialize TDDR PLL and enable outputs that are not clock gated. */ + CLOCK_InitTddrRefClk(kCLOCK_TddrFlexspiDiv10); + /* Enable TDDR PLL FlexSPI clock output */ + CLOCK_EnableClock(kCLOCK_TddrMciFlexspiClk); + /* Initialize AVPLL and enable both channels. */ + CLOCK_InitAvPll(&avpllConfig_BOARD_BootClockRUN); + /* Set up clock selectors - Attach clocks to the peripheries */ + CLOCK_AttachClk(kRC32K_to_CLK32K); /* Switch CLK32K to RC32K */ + /*!< Please note SYSTICK_CLK source is used only if the SysTick SYST_CSR register CLKSOURCE bit is set to 0. */ + CLOCK_AttachClk(kSYSTICK_DIV_to_SYSTICK_CLK); /* Switch SYSTICK_CLK to SYSTICK_DIV */ + /* Set up dividers */ + CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 1U); /* Set .AUDIOPLLCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk, 13U); /* Set .FRGPLLCLKDIV divider to value 13 */ + CLOCK_SetClkDiv(kCLOCK_DivMainPllClk, 1U); /* Set .MAINPLLCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivAux0PllClk, 1U); /* Set .AUX0PLLCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U); /* Set .SYSTICKFCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivPmuFclk, 5U); /* Set .PMUFCLKDIV divider to value 5 */ + /* Select the main clock source for the main system clock (MAINCLKSELA and MAINCLKSELB). */ + CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK); + /*!< Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_HCLK; +} + diff --git a/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h new file mode 100644 index 000000000..3b467d869 --- /dev/null +++ b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h @@ -0,0 +1,116 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CLOCK_CONFIG_H_ +#define _CLOCK_CONFIG_H_ + +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes default configuration of clocks. + * + */ +void BOARD_InitBootClocks(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockRUN configuration + ******************************************************************************/ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKRUN_AUDIO_PLL_CLK 12287999UL /* Clock consumers of audio_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_AUX0_PLL_CLK 260000000UL /* Clock consumers of aux0_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_AUX1_PLL_CLK 0UL /* Clock consumers of aux1_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_AVPLL_CH1_CLKOUT 12287999UL /* Clock consumers of avpll_ch1_clkout output : N/A */ +#define BOARD_BOOTCLOCKRUN_AVPLL_CH2_CLKOUT 63999997UL /* Clock consumers of avpll_ch2_clkout output : N/A */ +#define BOARD_BOOTCLOCKRUN_CAU_SLP_CLK 4000000UL /* Clock consumers of cau_slp_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLK_32K 32000UL /* Clock consumers of clk_32k output : RTC */ +#define BOARD_BOOTCLOCKRUN_CLK_OUT 0UL /* Clock consumers of clk_out output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLK_PMU_SYS 52000000UL /* Clock consumers of clk_pmu_sys output : PMU */ +#define BOARD_BOOTCLOCKRUN_CTIMER0_FCLK 0UL /* Clock consumers of ctimer0_fclk output : CTIMER0 */ +#define BOARD_BOOTCLOCKRUN_CTIMER1_FCLK 0UL /* Clock consumers of ctimer1_fclk output : CTIMER1 */ +#define BOARD_BOOTCLOCKRUN_CTIMER2_FCLK 0UL /* Clock consumers of ctimer2_fclk output : CTIMER2 */ +#define BOARD_BOOTCLOCKRUN_CTIMER3_FCLK 0UL /* Clock consumers of ctimer3_fclk output : CTIMER3 */ +#define BOARD_BOOTCLOCKRUN_DMIC_FCLK 0UL /* Clock consumers of dmic_fclk output : DMIC0 */ +#define BOARD_BOOTCLOCKRUN_ELS_128M_CLK 128000000UL /* Clock consumers of els_128m_clk output : ELS */ +#define BOARD_BOOTCLOCKRUN_ELS_256M_CLK 256000000UL /* Clock consumers of els_256m_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_ELS_64M_CLK 64000000UL /* Clock consumers of els_64m_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_ELS_FCLK 0UL /* Clock consumers of els_fclk output : ELS */ +#define BOARD_BOOTCLOCKRUN_FFRO_CLK_DIV4 12075471UL /* Clock consumers of ffro_clk_div4 output : N/A */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM0_FCLK 0UL /* Clock consumers of flexcomm0_fclk output : FLEXCOMM0 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM14_FCLK 0UL /* Clock consumers of flexcomm14_fclk output : FLEXCOMM14 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM1_FCLK 0UL /* Clock consumers of flexcomm1_fclk output : FLEXCOMM1 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM2_FCLK 0UL /* Clock consumers of flexcomm2_fclk output : FLEXCOMM2 */ +#define BOARD_BOOTCLOCKRUN_FLEXCOMM3_FCLK 0UL /* Clock consumers of flexcomm3_fclk output : FLEXCOMM3 */ +#define BOARD_BOOTCLOCKRUN_FLEXSPI_FCLK 0UL /* Clock consumers of flexspi_fclk output : FLEXSPI */ +#define BOARD_BOOTCLOCKRUN_GAU_FCLK 0UL /* Clock consumers of gau_fclk output : GAU_ACOMP, GAU_BG, GAU_DAC0, GAU_GPADC0, GAU_GPADC1 */ +#define BOARD_BOOTCLOCKRUN_HCLK 260000000UL /* Clock consumers of hclk output : AHB_SECURE_CTRL, APU0, APU1, BLEAPU, BLECTRL, BUCK11, BUCK18, CACHE64_CTRL0, CACHE64_CTRL1, CACHE64_POLSEL0, CACHE64_POLSEL1, CAU, CDOG, CLKCTL0, CLKCTL1, CRC, CTIMER0, CTIMER1, CTIMER2, CTIMER3, DMA0, DMA1, DMIC0, ELS, ENET, FLEXCOMM0, FLEXCOMM1, FLEXCOMM14, FLEXCOMM2, FLEXCOMM3, FLEXSPI, FREQME, GAU_ACOMP, GAU_BG, GAU_DAC0, GAU_GPADC0, GAU_GPADC1, GDMA, GPIO, INPUTMUX, ITRC, LCDIC, MCI_IO_MUX, MRT0, MRT1, OCOTP, OSTIMER, PINT, PKC, PMU, POWERQUAD, PUF, ROMCP, RSTCTL0, RSTCTL1, RTC, SCT0, SDU_FBR_CARD, SDU_FN0_CARD, SDU_FN_CARD, SECGPIO, SENSOR_CTRL, SOCCTRL, SOC_OTP_CTRL, SYSCTL0, SYSCTL1, SYSCTL2, SysTick, TRNG, USBOTG, USIM, UTICK, WLAPU, WLCTRL, WWDT0 */ +#define BOARD_BOOTCLOCKRUN_LCD_FCLK 0UL /* Clock consumers of lcd_fclk output : LCDIC */ +#define BOARD_BOOTCLOCKRUN_LPOSC_CLK_I 1000000UL /* Clock consumers of lposc_clk_i output : N/A */ +#define BOARD_BOOTCLOCKRUN_MAIN_CLK 260000000UL /* Clock consumers of main_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_MAIN_PLL_CLK 260000000UL /* Clock consumers of main_pll_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_MCLK_OUT 0UL /* Clock consumers of mclk_out output : N/A */ +#define BOARD_BOOTCLOCKRUN_OSEVENT_FCLK 0UL /* Clock consumers of osevent_fclk output : OSTIMER */ +#define BOARD_BOOTCLOCKRUN_OTP_FUSE_32M_CLK 32000000UL /* Clock consumers of otp_fuse_32m_clk output : OCOTP */ +#define BOARD_BOOTCLOCKRUN_REFCLK_PHY 40000000UL /* Clock consumers of refclk_phy output : USBOTG */ +#define BOARD_BOOTCLOCKRUN_REFCLK_SYS 0UL /* Clock consumers of refclk_sys output : N/A */ +#define BOARD_BOOTCLOCKRUN_SCT_FCLK 0UL /* Clock consumers of sct_fclk output : SCT0 */ +#define BOARD_BOOTCLOCKRUN_SFRO_CLK_I 16000000UL /* Clock consumers of sfro_clk_i output : N/A */ +#define BOARD_BOOTCLOCKRUN_SYSOSC_CLK_I 0UL /* Clock consumers of sysosc_clk_i output : N/A */ +#define BOARD_BOOTCLOCKRUN_SYSTICK_FCLK 260000000UL /* Clock consumers of systick_fclk output : SysTick */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_213P3M 0UL /* Clock consumers of t3pll_mci_213p3m output : N/A */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_256M 256000000UL /* Clock consumers of t3pll_mci_256m output : N/A */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_48_60M_IRC 48301886UL /* Clock consumers of t3pll_mci_48_60m_irc output : N/A */ +#define BOARD_BOOTCLOCKRUN_T3PLL_MCI_FLEXSPI_CLK 0UL /* Clock consumers of t3pll_mci_flexspi_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_TCPU_MCI_CLK 260000000UL /* Clock consumers of tcpu_mci_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_TCPU_MCI_FLEXSPI_CLK 0UL /* Clock consumers of tcpu_mci_flexspi_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_TDDR_MCI_ENET_CLK 0UL /* Clock consumers of tddr_mci_enet_clk output : ENET */ +#define BOARD_BOOTCLOCKRUN_TDDR_MCI_FLEXSPI_CLK 320000000UL /* Clock consumers of tddr_mci_flexspi_clk output : N/A */ +#define BOARD_BOOTCLOCKRUN_USIM_FCLK 0UL /* Clock consumers of usim_fclk output : USIM */ +#define BOARD_BOOTCLOCKRUN_UTICK_FCLK 0UL /* Clock consumers of utick_fclk output : UTICK */ +#define BOARD_BOOTCLOCKRUN_WDT0_FCLK 0UL /* Clock consumers of wdt0_fclk output : WWDT0 */ + +/*! @brief AVPLL set for BOARD_BootClockRUN configuration. + */ +extern const clock_avpll_config_t avpllConfig_BOARD_BootClockRUN; +/******************************************************************************* + * API for BOARD_BootClockRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockRUN(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + + +#endif /* _CLOCK_CONFIG_H_ */ + diff --git a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c new file mode 100644 index 000000000..49b74b2bb --- /dev/null +++ b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c @@ -0,0 +1,223 @@ +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Pins v17.0 +processor: RW612 +package_id: RW612ETA2I +mcu_data: ksdk2_0 +processor_version: 25.09.10 +board: FRDM-RW612 +pin_labels: +- {pin_num: M2, pin_signal: GPIO_11, label: 'J1[6]/WAKEUP_BTN', identifier: WAKEUP;WAKEUP_BTN} +- {pin_num: L7, pin_signal: GPIO_5, label: 'J1[7]/MCLK', identifier: MCLKOUT} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +#include "fsl_common.h" +#include "fsl_gpio.h" +#include "fsl_io_mux.h" +#include "pin_mux.h" + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) +{ + BOARD_InitPins(); + BOARD_InitDEBUG_UARTPins(); + BOARD_InitSWD_DEBUGPins(); + BOARD_InitLEDPins(); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: M2, peripheral: GPIO, signal: 'PIO0, 11', pin_signal: GPIO_11, identifier: WAKEUP_BTN, direction: INPUT} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitPins + * Description : + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitPins(void) +{ + /* Enables the clock for the GPIO0 module */ + GPIO_PortInit(GPIO, 0); + + gpio_pin_config_t WAKEUP_BTN_config = { + .pinDirection = kGPIO_DigitalInput, + .outputLogic = 0U + }; + /* Initialize GPIO functionality on pin PIO0_11 (pin M2) */ + GPIO_PinInit(BOARD_INITPINS_WAKEUP_BTN_GPIO, BOARD_INITPINS_WAKEUP_BTN_PORT, BOARD_INITPINS_WAKEUP_BTN_PIN, &WAKEUP_BTN_config); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitDEBUG_UARTPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: E5, peripheral: FLEXCOMM3, signal: USART_RXD, pin_signal: GPIO_24} + - {pin_num: F6, peripheral: FLEXCOMM3, signal: USART_TXD, pin_signal: GPIO_26} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitDEBUG_UARTPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitDEBUG_UARTPins(void) +{ + /* Initialize FC3_USART_DATA functionality on pin GPIO_24, GPIO_26 (pin E5_F6) */ + IO_MUX_SetPinMux(IO_MUX_FC3_USART_DATA); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitSWD_DEBUGPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: G5, peripheral: SWD, signal: CLK, pin_signal: GPIO_13} + - {pin_num: K4, peripheral: SWD, signal: IO, pin_signal: GPIO_14} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitSWD_DEBUGPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitSWD_DEBUGPins(void) +{ + + MCI_IO_MUX->C_TIMER_IN = ((MCI_IO_MUX->C_TIMER_IN & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_C_TIMER_IN_CT_INP3_SEL_MASK | MCI_IO_MUX_C_TIMER_IN_CT_INP4_SEL_MASK))) + + /* sel GPIO-13 as ct_inp3: 0x00u */ + | MCI_IO_MUX_C_TIMER_IN_CT_INP3_SEL(0x00u) + /* sel GPIO-14 as ct_inp4: 0x00u */ + | MCI_IO_MUX_C_TIMER_IN_CT_INP4_SEL(0x00u)); + + MCI_IO_MUX->C_TIMER_OUT = ((MCI_IO_MUX->C_TIMER_OUT & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_C_TIMER_OUT_CT0MAT3_SEL_MASK | MCI_IO_MUX_C_TIMER_OUT_CT1MAT0_SEL_MASK))) + + /* sel GPIO-13 as ct0mat3: 0x00u */ + | MCI_IO_MUX_C_TIMER_OUT_CT0MAT3_SEL(0x00u) + /* sel GPIO-14 as ct1mat0: 0x00u */ + | MCI_IO_MUX_C_TIMER_OUT_CT1MAT0_SEL(0x00u)); + + MCI_IO_MUX->FC2 = + ((MCI_IO_MUX->FC2 & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_FC2_SEL_FC2_I2C_MASK | MCI_IO_MUX_FC2_SEL_FC2_I2S_MASK | MCI_IO_MUX_FC2_SEL_FC2_SPI_MASK | MCI_IO_MUX_FC2_SEL_FC2_I2S_DATA_ONLY_MASK | MCI_IO_MUX_FC2_SEL_FC2_USART_DATA_MASK))) + + /* flexcomm2:select GPIO-13/14 as i2c function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_I2C(0x00u) + /* flexcomm2:select GPIO-13/14/15 as i2s function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_I2S(0x00u) + /* flexcomm2:select GPIO-13/14/15/16 as spi function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_SPI(0x00u) + /* flexcomm2:select GPIO-13 as i2s data function: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_I2S_DATA_ONLY(0x00u) + /* flexcomm2:select GPIO-13/14 as usart rxd/txd: 0x00u */ + | MCI_IO_MUX_FC2_SEL_FC2_USART_DATA(0x00u)); + + MCI_IO_MUX->GPIO_GRP0 = ((MCI_IO_MUX->GPIO_GRP0 & + /* Mask bits to zero which are setting */ + (~(MCI_IO_MUX_GPIO_GRP0_SEL_13_MASK | MCI_IO_MUX_GPIO_GRP0_SEL_14_MASK))) + + /* pio0[31:0] selection, high valid; sel[i]->pio0[i]->GPIO[i]: 0x00u */ + | MCI_IO_MUX_GPIO_GRP0_SEL(0x00u)); + + SOCCTRL->MCI_IOMUX_EN0 = ((SOCCTRL->MCI_IOMUX_EN0 & + /* Mask bits to zero which are setting */ + (~(SOCCIU_MCI_IOMUX_EN0_EN_21_0_13_MASK | SOCCIU_MCI_IOMUX_EN0_EN_21_0_14_MASK))) + + /* Bitwise enable control for mci_io_mux GPIO[21:0]: 0x00u */ + | SOCCIU_MCI_IOMUX_EN0_EN_21_0(0x00u)); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitLEDPins: +- options: {callFromInitBoot: 'true', coreID: cm33, enableClock: 'true'} +- pin_list: + - {pin_num: M1, peripheral: GPIO, signal: 'PIO0, 0', pin_signal: GPIO_0, direction: OUTPUT, gpio_init_state: 'true'} + - {pin_num: N2, peripheral: GPIO, signal: 'PIO0, 1', pin_signal: GPIO_1, direction: OUTPUT, gpio_init_state: 'true'} + - {pin_num: N8, peripheral: GPIO, signal: 'PIO0, 12', pin_signal: GPIO_12, direction: OUTPUT, gpio_init_state: 'true'} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitLEDPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M33 */ +void BOARD_InitLEDPins(void) +{ + /* Enables the clock for the GPIO0 module */ + CLOCK_EnableClock(kCLOCK_HsGpio0); + + gpio_pin_config_t LED_BLUE_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO0_0 (pin M1) */ + GPIO_PinInit(BOARD_INITLEDPINS_LED_BLUE_GPIO, BOARD_INITLEDPINS_LED_BLUE_PORT, BOARD_INITLEDPINS_LED_BLUE_PIN, &LED_BLUE_config); + + gpio_pin_config_t LED_RED_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO0_1 (pin N2) */ + GPIO_PinInit(BOARD_INITLEDPINS_LED_RED_GPIO, BOARD_INITLEDPINS_LED_RED_PORT, BOARD_INITLEDPINS_LED_RED_PIN, &LED_RED_config); + + gpio_pin_config_t LED_GREEN_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO0_12 (pin N8) */ + GPIO_PinInit(BOARD_INITLEDPINS_LED_GREEN_GPIO, BOARD_INITLEDPINS_LED_GREEN_PORT, BOARD_INITLEDPINS_LED_GREEN_PIN, &LED_GREEN_config); + /* Initialize GPIO0 functionality on pin GPIO_0 (pin M1) */ + IO_MUX_SetPinMux(IO_MUX_GPIO0); + /* Initialize GPIO1 functionality on pin GPIO_1 (pin N2) */ + IO_MUX_SetPinMux(IO_MUX_GPIO1); + /* Initialize GPIO12 functionality on pin GPIO_12 (pin N8) */ + IO_MUX_SetPinMux(IO_MUX_GPIO12); +} +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h new file mode 100644 index 000000000..f4c9a9127 --- /dev/null +++ b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h @@ -0,0 +1,146 @@ +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _PIN_MUX_H_ +#define _PIN_MUX_H_ + +/*! + * @addtogroup pin_mux + * @{ + */ + +/*********************************************************************************************************************** + * API + **********************************************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Calls initialization functions. + * + */ +void BOARD_InitBootPins(void); + +/*! + * @brief mclk direction control: MCLK is in the output direction. */ +#define MCLKPINDIR_MCLKPINDIR_OUTPUT_DIRECTION 0x01u + +/*! @name GPIO_5 (coord L7), J1[7]/MCLK + @{ */ +/* Routed pin properties */ +#define BOARD_INITPINS_MCLKOUT_PERIPHERAL CLKCTL1 /*!<@brief Peripheral name */ +#define BOARD_INITPINS_MCLKOUT_SIGNAL MCLK /*!<@brief Signal name */ +#define BOARD_INITPINS_MCLKOUT_GPIO_PIN 5U /*!<@brief GPIO pin number */ +#define BOARD_INITPINS_MCLKOUT_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITPINS_MCLKOUT_PIN 5U /*!<@brief PORT pin number */ +#define BOARD_INITPINS_MCLKOUT_PIN_MASK (1U << 5U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name GPIO_11 (coord M2), J1[6]/WAKEUP_BTN + @{ */ +/* Routed pin properties */ +#define BOARD_INITPINS_WAKEUP_BTN_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITPINS_WAKEUP_BTN_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITPINS_WAKEUP_BTN_CHANNEL 11 /*!<@brief Signal channel */ +#define BOARD_INITPINS_WAKEUP_BTN_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITPINS_WAKEUP_BTN_GPIO_PIN 11U /*!<@brief GPIO pin number */ +#define BOARD_INITPINS_WAKEUP_BTN_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITPINS_WAKEUP_BTN_PIN 11U /*!<@brief PORT pin number */ +#define BOARD_INITPINS_WAKEUP_BTN_PIN_MASK (1U << 11U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief + * + */ +void BOARD_InitPins(void); /* Function assigned for the Cortex-M33 */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitDEBUG_UARTPins(void); /* Function assigned for the Cortex-M33 */ + +/*! + * @brief pio0[31:0] selection, high valid; sel[i]->pio0[i]->GPIO[i] Mask for item 13. */ +#define MCI_IO_MUX_GPIO_GRP0_SEL_13_MASK 0x2000u +/*! + * @brief pio0[31:0] selection, high valid; sel[i]->pio0[i]->GPIO[i] Mask for item 14. */ +#define MCI_IO_MUX_GPIO_GRP0_SEL_14_MASK 0x4000u +/*! + * @brief Bitwise enable control for mci_io_mux GPIO[21:0] Mask for item 13. */ +#define SOCCIU_MCI_IOMUX_EN0_EN_21_0_13_MASK 0x2000u +/*! + * @brief Bitwise enable control for mci_io_mux GPIO[21:0] Mask for item 14. */ +#define SOCCIU_MCI_IOMUX_EN0_EN_21_0_14_MASK 0x4000u + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitSWD_DEBUGPins(void); /* Function assigned for the Cortex-M33 */ + +/*! @name GPIO_0 (coord M1), J1[14]/LED_BLUE + @{ */ +/* Routed pin properties */ +#define BOARD_INITLEDPINS_LED_BLUE_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITLEDPINS_LED_BLUE_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITLEDPINS_LED_BLUE_CHANNEL 0 /*!<@brief Signal channel */ +#define BOARD_INITLEDPINS_LED_BLUE_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDPINS_LED_BLUE_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDPINS_LED_BLUE_GPIO_PIN 0U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDPINS_LED_BLUE_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITLEDPINS_LED_BLUE_PIN 0U /*!<@brief PORT pin number */ +#define BOARD_INITLEDPINS_LED_BLUE_PIN_MASK (1U << 0U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name GPIO_1 (coord N2), J5[1]/LED_RED + @{ */ +/* Routed pin properties */ +#define BOARD_INITLEDPINS_LED_RED_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITLEDPINS_LED_RED_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITLEDPINS_LED_RED_CHANNEL 1 /*!<@brief Signal channel */ +#define BOARD_INITLEDPINS_LED_RED_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDPINS_LED_RED_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDPINS_LED_RED_GPIO_PIN 1U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDPINS_LED_RED_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITLEDPINS_LED_RED_PIN 1U /*!<@brief PORT pin number */ +#define BOARD_INITLEDPINS_LED_RED_PIN_MASK (1U << 1U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name GPIO_12 (coord N8), LED_GREEN + @{ */ +/* Routed pin properties */ +#define BOARD_INITLEDPINS_LED_GREEN_PERIPHERAL GPIO /*!<@brief Peripheral name */ +#define BOARD_INITLEDPINS_LED_GREEN_SIGNAL PIO0 /*!<@brief Signal name */ +#define BOARD_INITLEDPINS_LED_GREEN_CHANNEL 12 /*!<@brief Signal channel */ +#define BOARD_INITLEDPINS_LED_GREEN_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDPINS_LED_GREEN_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDPINS_LED_GREEN_GPIO_PIN 12U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDPINS_LED_GREEN_PORT 0U /*!<@brief PORT number */ +#define BOARD_INITLEDPINS_LED_GREEN_PIN 12U /*!<@brief PORT pin number */ +#define BOARD_INITLEDPINS_LED_GREEN_PIN_MASK (1U << 12U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitLEDPins(void); /* Function assigned for the Cortex-M33 */ + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/rw61x/family.c b/hw/bsp/rw61x/family.c new file mode 100644 index 000000000..226956f15 --- /dev/null +++ b/hw/bsp/rw61x/family.c @@ -0,0 +1,135 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * Copyright (c) 2025, Gabriel Koppenstein + * + * 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. + */ + +/* metadata: + manufacturer: NXP +*/ + +#include "bsp/board_api.h" +#include "fsl_device_registers.h" +#include "fsl_gpio.h" +#include "board.h" +#include "fsl_usart.h" +#include "fsl_clock.h" + +#include "pin_mux.h" +#include "clock_config.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +void USB_IRQHandler(void) { + tusb_int_handler(1, true); +} + +void board_init(void) { + + // Init button pin, LED pins, SWD pins & UART pins + BOARD_InitBootPins(); + + // Init Clocks + BOARD_InitBootClocks(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR from running before scheduler start + SysTick->CTRL &= ~1U; + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + +#ifdef NEOPIXEL_PIN + // No neo pixel support yet +#endif + +#ifdef UART_DEV + // Enable UART when debug log is on + board_uart_init_clock(); + usart_config_t uart_config; + USART_GetDefaultConfig(&uart_config); + uart_config.baudRate_Bps = CFG_BOARD_UART_BAUDRATE; + uart_config.enableRx = true; + uart_config.enableTx = true; + USART_Init(UART_DEV, &uart_config, CLOCK_GetFlexCommClkFreq(LP_FLEXCOMM_INST)); +#endif + + // USB Initialization + // Reset USB + RESET_PeripheralReset(kUSB_RST_SHIFT_RSTn); + + // Enable USB Clock + CLOCK_EnableClock(kCLOCK_Usb); + + // Enable USB PHY + CLOCK_EnableUsbhsPhyClock(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { + GPIO_PinWrite(LED_GPIO, LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); +} + +uint32_t board_button_read(void) { +#ifdef BUTTON_GPIO + return BUTTON_STATE_ACTIVE == GPIO_PinRead(BUTTON_GPIO, BOARD_INITPINS_WAKEUP_BTN_PORT, 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 + USART_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/rw61x/family.cmake b/hw/bsp/rw61x/family.cmake new file mode 100644 index 000000000..5428b7e50 --- /dev/null +++ b/hw/bsp/rw61x/family.cmake @@ -0,0 +1,102 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/nxp/mcux-sdk) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m33-nodsp-nofp CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS RW61X CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ + +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) +set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${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_power.c + ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c + ${SDK_DIR}/drivers/common/fsl_common_arm.c + ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c + ${SDK_DIR}/drivers/flexcomm/usart/fsl_usart.c + ${SDK_DIR}/drivers/flexspi/fsl_flexspi.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMSIS_5}/CMSIS/Core/Include + ${SDK_DIR}/devices/${MCU_VARIANT} + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + ${SDK_DIR}/drivers + ${SDK_DIR}/drivers/common + ${SDK_DIR}/drivers/lpc_gpio + ${SDK_DIR}/drivers/flexcomm + ${SDK_DIR}/drivers/flexcomm/usart + ${SDK_DIR}/drivers/flexspi + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_RW61X) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + + # ChipIdea HS + ${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 + + # Startup File + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + # Add Board specific includes + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Linker Options + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs + --specs=nano.specs + ) + endif() + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + + # Handle Startup File Properties (Linting/Warnings) + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w + ) + + # Flashing & Binary Generation + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() \ No newline at end of file diff --git a/hw/bsp/rw61x/family.mk b/hw/bsp/rw61x/family.mk new file mode 100644 index 000000000..e715adfa8 --- /dev/null +++ b/hw/bsp/rw61x/family.mk @@ -0,0 +1,52 @@ +UF2_FAMILY_ID = 0x2abc77ec +SDK_DIR = hw/mcu/nxp/mcux-sdk + +include $(TOP)/$(BOARD_PATH)/board.mk + +# Default to Highspeed PORT1 +PORT ?= 1 + +CFLAGS += \ + -flto \ + -DBOARD_TUD_RHPORT=$(PORT) \ + -DBOARD_TUH_RHPORT=$(PORT) \ + -DSERIAL_PORT_TYPE_UART=1 \ + -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED \ + -DBOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED \ + +# mcu driver cause following warnings +CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration -Wno-error=redundant-decls + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +# 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 \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.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_power.c \ + $(SDK_DIR)/drivers/lpc_gpio/fsl_gpio.c \ + $(SDK_DIR)/drivers/common/fsl_common_arm.c\ + $(SDK_DIR)/drivers/flexcomm/fsl_flexcomm.c \ + $(SDK_DIR)/drivers/flexcomm/usart/fsl_usart.c \ + $(SDK_DIR)/drivers/flexspi/fsl_flexspi.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 \ + $(TOP)/$(SDK_DIR)/drivers/ \ + $(TOP)/$(SDK_DIR)/drivers/common\ + $(TOP)/$(SDK_DIR)/drivers/lpc_gpio\ + $(TOP)/$(SDK_DIR)/drivers/flexcomm \ + $(TOP)/$(SDK_DIR)/drivers/flexcomm/usart \ + $(TOP)/$(SDK_DIR)/drivers/flexspi \ + + +SRC_S += $(SDK_DIR)/devices/$(MCU_VARIANT)/gcc/startup_$(MCU_CORE).S diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index b5324a754..fe2895f6a 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -61,6 +61,9 @@ bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { #include "ci_hs_lpc18_43.h" +#elif TU_CHECK_MCU(OPT_MCU_RW61X) +#include "ci_hs_rw61x.h" + #else #error "Unsupported MCUs" #endif diff --git a/tools/get_deps.py b/tools/get_deps.py index 0d9c1a8f1..17c2ab8b8 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -60,7 +60,7 @@ deps_optional = { 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43'], 'hw/mcu/nxp/mcux-sdk': ['https://github.com/nxp-mcuxpresso/mcux-sdk', 'a1bdae309a14ec95a4f64a96d3315a4f89c397c6', - 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], + 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx rw61x imxrt'], 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', '675543bcc9baa8170f868ab7ba316d418dbcf41f', 'rp2040'], @@ -246,7 +246,7 @@ deps_optional = { 'at32f413'], 'lib/CMSIS_5': ['https://github.com/ARM-software/CMSIS_5.git', '2b7495b8535bdcb306dac29b9ded4cfb679d7e5c', - 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x ' + 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx rw61x mm32 msp432e4 nrf saml2x ' 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 ' 'stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 ' 'stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u0 stm32u5 stm32wb stm32wba ' -- cgit v1.3.1 From 1583864e0b1379cc2f03717f1bed2429e5473407 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Dec 2025 13:28:24 +0700 Subject: minor clean up --- README.rst | 260 +++++++++++++------------- examples/host/bare_api/only.txt | 15 +- examples/host/cdc_msc_hid/only.txt | 15 +- examples/host/cdc_msc_hid_freertos/only.txt | 13 +- examples/host/device_info/only.txt | 13 +- examples/host/hid_controller/only.txt | 15 +- examples/host/midi_rx/only.txt | 13 +- examples/host/msc_file_explorer/only.txt | 15 +- hw/bsp/stm32u5/family.mk | 6 +- src/device/usbd.c | 6 +- src/portable/st/stm32_fsdev/fsdev_common.c | 16 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 10 +- 12 files changed, 211 insertions(+), 186 deletions(-) (limited to 'src') diff --git a/README.rst b/README.rst index 75f93f656..da1f49fcd 100644 --- a/README.rst +++ b/README.rst @@ -129,138 +129,134 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) Supported CPUs -------------- -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Manufacturer | Family | Device | Host | Highspeed | Driver | Note | -+==============+=============================+========+======+===========+========================+========================+ -| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | -| | MAX78002 | | | | | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | -| ESP32 +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | P4 | ✔ | ✔ | ✔ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | H4 | ✔ | ✔ | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | D51, E5x | ✔ | | ✖ | samd | | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | G55 | ✔ | | ✖ | samg | 1-dir ep | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep | -| +-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| | PIC | 24 | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | dsPIC33 | ✔ | | | pic | ci_fs variant | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | 32mz | ✔ | | | pic32mz | musb variant | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is IO | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | NUC121/NUC125 | ✔ | ✖ | ✖ | nuc121 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | NUC126 | ✔ | ✖ | ✖ | nuc121 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | NUC505 | ✔ | | ✔ | nuc505 | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | -| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant | -| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | -| +---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | -| | +-------------------+--------+------+-----------+------------------------+------------------------+ -| | | A15 | ✔ | | | ci_fs | | -+--------------+---------+-------------------+--------+------+-----------+------------------------+------------------------+ -| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | -| +-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | | -| | +-----------------------+--------+------+-----------+------------------------+------------------------+ -| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | | -+--------------+-----+-----------------------+--------+------+-----------+------------------------+------------------------+ -| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | C0, G0, H5 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | N6 | ✔ | ✔ | ✔ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | U3 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | -| +----+------------------------+--------+------+-----------+------------------------+------------------------+ -| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Host tested on C0, H5 | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | -| | +------------------------+--------+------+-----------+------------------------+------------------------+ -| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | | -+--------------+----+------------------------+--------+------+-----------+------------------------+------------------------+ -| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ -| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | | -| +-----------------------------+--------+------+-----------+------------------------+------------------------+ -| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | | -+--------------+-----------------------------+--------+------+-----------+------------------------+------------------------+ ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Manufacturer | Family | Device | Host | Highspeed | Driver | Note | ++==============+=============================+========+======+===========+========================+====================+ +| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | +| | MAX78002 | | | | | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | Packet SRAM 512 | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | +| ESP32 +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | P4 | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | H4 | ✔ | ✔ | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | D51, E5x | ✔ | | ✖ | samd | | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | G55 | ✔ | | ✖ | samg | 1-dir ep | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep | +| +-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| | PIC | 24 | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | dsPIC33 | ✔ | | | pic | ci_fs variant | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | 32mz | ✔ | | | pic32mz | musb variant | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is ISO | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | NUC121/NUC125, NUC126 | ✔ | ✖ | ✖ | nuc121 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | NUC505 | ✔ | | ✔ | nuc505 | | ++--------------+---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | +| +---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant | +| +---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | +| +---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | +| | +-------------------+--------+------+-----------+------------------------+--------------------+ +| | | A15 | ✔ | | | ci_fs | | ++--------------+---------+-------------------+--------+------+-----------+------------------------+--------------------+ +| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | | +| +-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | | +| | +-----------------------+--------+------+-----------+------------------------+--------------------+ +| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | | ++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+ +| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 512 | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | N6 | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| +----+------------------------+--------+------+-----------+------------------------+--------------------+ +| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | +| | +------------------------+--------+------+-----------+------------------------+--------------------+ +| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | | ++--------------+----+------------------------+--------+------+-----------+------------------------+--------------------+ +| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ +| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | | +| +-----------------------------+--------+------+-----------+------------------------+--------------------+ +| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | | ++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ Table Legend ^^^^^^^^^^^^ diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index 4cd457879..52e51242c 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,20 +7,21 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index 4cd457879..52e51242c 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,20 +7,21 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index 2322d4ecf..4cff741c3 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -1,21 +1,24 @@ +family:espressif +family:samd21 +family:samd5x_e5x mcu:LPC175X_6X mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:MIMXRT1XXX mcu:MSP432E4 mcu:RX65X -mcu:MAX3421 mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:espressif -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 5b68f0774..becc8252d 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -1,3 +1,6 @@ +family:espressif +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -6,20 +9,20 @@ mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX mcu:MAX3421 -mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:MIMXRT1XXX mcu:MSP432E4 +mcu:RAXXX mcu:RP2040 mcu:RX65X -mcu:RAXXX mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:espressif -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index b859b4cc0..35b7c2361 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,19 +7,20 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index 09d725860..a3976f08d 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -1,7 +1,9 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X +mcu:ESP32P4 mcu:ESP32S2 mcu:ESP32S3 -mcu:ESP32P4 mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X @@ -9,19 +11,20 @@ mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX mcu:MAX3421 -mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX +mcu:MIMXRT1XXX mcu:MSP432E4 +mcu:RAXXX mcu:RP2040 mcu:RX65X -mcu:RAXXX mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index 4cd457879..52e51242c 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -1,3 +1,5 @@ +family:samd21 +family:samd5x_e5x mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X @@ -5,20 +7,21 @@ mcu:LPC177X_8X mcu:LPC18XX mcu:LPC40XX mcu:LPC43XX -mcu:MIMXRT1XXX +mcu:MAX3421 mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 +mcu:MIMXRT1XXX mcu:MSP432E4 -mcu:RX65X mcu:RAXXX -mcu:MAX3421 +mcu:RP2040 +mcu:RX65X mcu:STM32C0 mcu:STM32F4 mcu:STM32F7 +mcu:STM32G0 mcu:STM32H5 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 -family:samd21 -family:samd5x_e5x +mcu:STM32U3 +mcu:STM32U5 diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 79f181a68..47aed10a9 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -37,11 +37,7 @@ SRC_C += \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c -ifeq ($(MCU_VARIANT),stm32u545xx) -SRC_C += \ - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ - src/portable/st/stm32_fsdev/fsdev_common.c -else ifeq ($(MCU_VARIANT),stm32u535xx) +ifneq ($(filter stm32u545xx stm32u535xx,$(MCU_VARIANT)),) SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ src/portable/st/stm32_fsdev/fsdev_common.c diff --git a/src/device/usbd.c b/src/device/usbd.c index 5365ae2c2..1a9eb630c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -574,6 +574,8 @@ bool tud_deinit(uint8_t rhport) { TU_LOG_USBD("USBD deinit on controller %u\r\n", rhport); + const uint8_t cfg_num = _usbd_dev.cfg_num; + // Deinit device controller driver dcd_int_disable(rhport); dcd_disconnect(rhport); @@ -604,7 +606,9 @@ bool tud_deinit(uint8_t rhport) { _usbd_rhport = RHPORT_INVALID; - tud_umount_cb(); + if (cfg_num > 0) { + tud_umount_cb(); + } return true; } diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 60ef339a6..5d60ad9a2 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -78,7 +78,9 @@ void fsdev_deinit(void) { // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT // - Uses unaligned for RAM (since M0 cannot access unaligned address) bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) return true; + if (nbytes == 0) { + return true; + } uint32_t n_write = nbytes / FSDEV_BUS_SIZE; fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); @@ -107,7 +109,9 @@ bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_ // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT // - Uses unaligned for RAM (since M0 cannot access unaligned address) bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) return true; + if (nbytes == 0) { + return true; + } uint32_t n_read = nbytes / FSDEV_BUS_SIZE; fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); @@ -134,7 +138,9 @@ bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbyte // Write to PMA from FIFO bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { - if (wNBytes == 0) return true; + if (wNBytes == 0) { + return true; + } // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies tu_fifo_buffer_info_t info; @@ -183,7 +189,9 @@ bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) // Read from PMA to FIFO bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { - if (wNBytes == 0) return true; + if (wNBytes == 0) { + return true; + } // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 212f620ac..da9c6961c 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -28,11 +28,11 @@ * This driver provides USB Host controller support for STM32 MCUs with "USB A"/"PCD"/"HCD" peripheral. * This covers these MCU families: * - * C0 2048 byte buffer; 32-bit bus; host mode - * G0 2048 byte buffer; 32-bit bus; host mode - * U3 2048 byte buffer; 32-bit bus; host mode - * H5 2048 byte buffer; 32-bit bus; host mode - * U535, U545 2048 byte buffer; 32-bit bus; host mode + * C0 2048 byte buffer; 32-bit bus; host mode + * G0 2048 byte buffer; 32-bit bus; host mode + * U3 2048 byte buffer; 32-bit bus; host mode + * H5 2048 byte buffer; 32-bit bus; host mode + * U535, U545 2048 byte buffer; 32-bit bus; host mode * */ -- cgit v1.3.1 From ebf7ce76ccd32436d6fc3688226709886ddc81e4 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Dec 2025 17:15:39 +0700 Subject: minor update --- src/host/usbh.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 5950aee11..e99d9e977 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -312,8 +312,8 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_class_driver_t const *get_driver(uint8_ // Function Inline and Prototypes //--------------------------------------------------------------------+ static bool enum_new_device(hcd_event_t* event); -static void process_detach_event(hcd_event_t* event); -static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); +static void process_remove_event(hcd_event_t *event); +static void remove_device_tree(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); @@ -541,8 +541,8 @@ bool tuh_deinit(uint8_t rhport) { hcd_deinit(rhport); _usbh_data.controller_id = TUSB_INDEX_INVALID_8; - // "unplug" all devices on this rhport (hub_addr = 0, hub_port = 0) - process_removed_device(rhport, 0, 0); + // remove all devices on this rhport (hub_addr = 0, hub_port = 0) + remove_device_tree(rhport, 0, 0); // deinit host stack if no controller is active if (!tuh_inited()) { @@ -606,10 +606,10 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: - // We have likely missed the hub detach event due to high traffic, detach the device first if exists - // Or due to physical debouncing, some devices can cause multiple attaches (actually reset) without detach event + // Should we miss the hub detach event due to high traffic, Or due to physical debouncing, some devices can + // cause multiple attaches (actually reset) without detach event. // Force remove currently mounted with the same bus info (rhport, hub addr, hub port) if exists - process_detach_event(&event); + process_remove_event(&event); // due to the shared control buffer, we must fully complete enumerating one device first. // TODO better to have an separated queue for newly attached devices @@ -631,7 +631,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_detach_event(&event); + process_remove_event(&event); break; case HCD_EVENT_XFER_COMPLETE: { @@ -1321,7 +1321,7 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, //--------------------------------------------------------------------+ // process detach event from rhport:hub_addr:hub_port -static void process_detach_event(hcd_event_t* event) { +static void process_remove_event(hcd_event_t *event) { if (_usbh_data.enumerating_daddr == 0 && event->rhport == _usbh_data.dev0_bus.rhport && event->connection.hub_addr == _usbh_data.dev0_bus.hub_addr && @@ -1329,12 +1329,12 @@ static void process_detach_event(hcd_event_t* event) { // dev0 is unplugged while enumerating (not yet assigned an address) usbh_device_close(_usbh_data.dev0_bus.rhport, 0); } else { - process_removed_device(event->rhport, event->connection.hub_addr, event->connection.hub_port); + remove_device_tree(event->rhport, event->connection.hub_addr, event->connection.hub_port); } } -// a device unplugged from rhport:hub_addr:hub_port -static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { +// remove a device at rhport:hub_addr:hub_port and all of its downstream +static void remove_device_tree(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { // Find the all devices (star-network) under port that is unplugged #if CFG_TUH_HUB uint8_t removing_hubs[CFG_TUH_HUB] = { 0 }; @@ -1925,6 +1925,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { } static void enum_full_complete(bool success) { + (void)success; // mark enumeration as complete _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; @@ -1933,8 +1934,6 @@ static void enum_full_complete(bool success) { if (_usbh_data.dev0_bus.hub_addr != 0 && !success) { hub_edpt_status_xfer(_usbh_data.dev0_bus.hub_addr); // get next hub status } -#else - (void) success; #endif } -- cgit v1.3.1 From 0a9e05f47adca971eb4af8b08adf0debbc6b83db Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Dec 2025 00:19:13 +0700 Subject: make fifo access mode fixed addr work with 16 bit also --- src/common/tusb_fifo.c | 106 ++++++++++++++++++++++++------------------ src/common/tusb_fifo.h | 19 +++++++- src/osal/osal_none.h | 2 +- test/unit-test/CMakeLists.txt | 2 +- test/unit-test/project.yml | 2 +- 5 files changed, 80 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e97b6ccce..450c31f57 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -114,40 +114,54 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // Pull & Push // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ -#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 +#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH + #if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 32 + #define fixed_unaligned_write tu_unaligned_write32 + #define fixed_unaligned_read tu_unaligned_read32 +typedef uint32_t fixed_access_item_t; + #elif CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 16 + #define fixed_unaligned_write tu_unaligned_write16 + #define fixed_unaligned_read tu_unaligned_read16 +typedef uint16_t fixed_access_item_t; + #endif + +enum { + FIXED_ACCESS_REMAINDER_MASK = sizeof(fixed_access_item_t) - 1u +}; + // Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_fixed_addr_rw32(uint8_t *ff_buf, const volatile uint32_t *reg_rx, uint16_t len) { - // Reading full available 32 bit words from const app address - uint16_t full_words = len >> 2; - while (full_words--) { - const uint32_t tmp32 = *reg_rx; - tu_unaligned_write32(ff_buf, tmp32); - ff_buf += 4; +static void ff_push_fixed_addr(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len) { + // Reading full available 16/32-bit data from const app address + uint16_t n_items = len / sizeof(fixed_access_item_t); + while (n_items--) { + const fixed_access_item_t tmp = *reg_rx; + fixed_unaligned_write(ff_buf, tmp); + ff_buf += sizeof(fixed_access_item_t); } - // Read the remaining 1-3 bytes from const app address - const uint8_t bytes_rem = len & 0x03; + // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) from const app address + const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK; if (bytes_rem) { - const uint32_t tmp32 = *reg_rx; - memcpy(ff_buf, &tmp32, bytes_rem); + const fixed_access_item_t tmp = *reg_rx; + memcpy(ff_buf, &tmp, bytes_rem); } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_pull_fixed_addr_rw32(volatile uint32_t *reg_tx, const uint8_t *ff_buf, uint16_t len) { +static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8_t *ff_buf, uint16_t len) { // Write full available 32 bit words to const address - uint16_t full_words = len >> 2u; - while (full_words--) { - *reg_tx = tu_unaligned_read32(ff_buf); - ff_buf += 4u; + uint16_t n_itmes = len / sizeof(fixed_access_item_t); + while (n_itmes--) { + *reg_tx = fixed_unaligned_read(ff_buf); + ff_buf += sizeof(fixed_access_item_t); } - // Write the remaining 1-3 bytes - const uint8_t bytes_rem = len & 0x03; + // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) + const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK; if (bytes_rem) { - uint32_t tmp32 = 0u; - memcpy(&tmp32, ff_buf, bytes_rem); - *reg_tx = tmp32; + fixed_access_item_t tmp = 0u; + memcpy(&tmp, ff_buf, bytes_rem); + *reg_tx = tmp; } } #endif @@ -176,26 +190,26 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 } break; -#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 +#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH case TU_FIFO_FIXED_ADDR_RW32: { - const volatile uint32_t *reg_rx = (volatile const uint32_t *)app_buf; + const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; if (n <= lin_count) { // Linear only - ff_push_fixed_addr_rw32(ff_buf, reg_rx, n * f->item_size); + ff_push_fixed_addr(ff_buf, reg_rx, n * f->item_size); } else { // Wrap around // Write full words to linear part of buffer - uint16_t lin_4n_bytes = lin_bytes & 0xFFFC; - ff_push_fixed_addr_rw32(ff_buf, reg_rx, lin_4n_bytes); - ff_buf += lin_4n_bytes; + uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; + ff_push_fixed_addr(ff_buf, reg_rx, lin_nitems_bytes); + ff_buf += lin_nitems_bytes; - // There could be odd 1-3 bytes before the wrap-around boundary - const uint8_t rem = lin_bytes & 0x03; + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem); - const uint32_t tmp32 = *reg_rx; - tu_scatter_write32(tmp32, ff_buf, rem, f->buffer, remrem); + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); + const fixed_access_item_t tmp = *reg_rx; + tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); wrap_bytes -= remrem; ff_buf = f->buffer + remrem; // wrap around @@ -205,7 +219,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 // Write data wrapped part if (wrap_bytes > 0) { - ff_push_fixed_addr_rw32(ff_buf, reg_rx, wrap_bytes); + ff_push_fixed_addr(ff_buf, reg_rx, wrap_bytes); } } break; @@ -240,28 +254,28 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd } break; -#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 +#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH case TU_FIFO_FIXED_ADDR_RW32: { - volatile uint32_t *reg_tx = (volatile uint32_t *)app_buf; + volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf; if (n <= lin_count) { // Linear only - ff_pull_fixed_addr_rw32(reg_tx, ff_buf, n * f->item_size); + ff_pull_fixed_addr(reg_tx, ff_buf, n * f->item_size); } else { // Wrap around case // Read full words from linear part - uint16_t lin_4n_bytes = lin_bytes & 0xFFFC; - ff_pull_fixed_addr_rw32(reg_tx, ff_buf, lin_4n_bytes); - ff_buf += lin_4n_bytes; + uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; + ff_pull_fixed_addr(reg_tx, ff_buf, lin_nitems_bytes); + ff_buf += lin_nitems_bytes; - // There could be odd 1-3 bytes before the wrap-around boundary - const uint8_t rem = lin_bytes & 0x03; + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem); - const uint32_t scatter32 = tu_scatter_read32(ff_buf, rem, f->buffer, remrem); + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); + const fixed_access_item_t scatter = (fixed_access_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); - *reg_tx = scatter32; + *reg_tx = scatter; wrap_bytes -= remrem; ff_buf = f->buffer + remrem; // wrap around @@ -271,7 +285,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd // Read data wrapped part if (wrap_bytes > 0) { - ff_pull_fixed_addr_rw32(reg_tx, ff_buf, wrap_bytes); + ff_pull_fixed_addr(reg_tx, ff_buf, wrap_bytes); } } break; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 2e2a0db6f..f58cc3fcb 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -49,9 +49,16 @@ extern "C" { #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED #if CFG_TUD_EDPT_DEDICATED_HWFIFO || CFG_TUH_EDPT_DEDICATED_HWFIFO - #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 + #ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH + #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 32 + #endif #endif +#ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH + #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0 +#endif + + /* Write/Read "pointer" is in the range of: 0 .. depth - 1, and is used to get the fifo data. * Write/Read "index" is always in the range of: 0 .. 2*depth-1 * @@ -150,7 +157,7 @@ typedef struct { // copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others typedef enum { TU_FIFO_INC_ADDR_RW8, // increased address read/write by bytes - normal (default) mode - TU_FIFO_FIXED_ADDR_RW32, // fixed address read/write by 4 bytes (word). Used for STM32 access into USB hardware FIFO + TU_FIFO_FIXED_ADDR_RW32, // fixed address read/write by 2/4 bytes (items). } tu_fifo_access_mode_t; //--------------------------------------------------------------------+ @@ -205,6 +212,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void * return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n_fixed_addr(tu_fifo_t *f, void *buffer, uint16_t n) { + return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_FIXED_ADDR_RW32); +} + // discard first n items from fifo i.e advance read pointer by n with mutex // return number of discarded items uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); @@ -218,6 +229,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_INC_ADDR_RW8); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n_fixed_addr(tu_fifo_t *f, const void *data, uint16_t n) { + return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_FIXED_ADDR_RW32); +} + //--------------------------------------------------------------------+ // Internal Helper Local // work on local copies of read/write indices in order to only access them once for re-entrancy diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 174136e38..aa6111a16 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -171,7 +171,7 @@ typedef osal_queue_def_t* osal_queue_t; } TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { - (void) tu_fifo_clear(&qdef->ff); + tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index 7172f5575..3339361db 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -113,7 +113,7 @@ add_ceedling_test( ${CEEDLING_WORKDIR}/../../src/common/tusb_fifo.c "" ) -target_compile_definitions(test_fifo PRIVATE CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32=1) +target_compile_definitions(test_fifo PRIVATE CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32) add_ceedling_test( test_usbd diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index d971d098d..3968faaef 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -128,7 +128,7 @@ :defines: :test: - _UNITY_TEST_ - - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 + - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. -- cgit v1.3.1 From ba3319d90d546143d169b398166b457082ad21d4 Mon Sep 17 00:00:00 2001 From: Zhihong Chen Date: Mon, 8 Dec 2025 13:59:21 +0800 Subject: support hpmicro chips Signed-off-by: Zhihong Chen --- hw/bsp/hpmicro/boards/hpm6750evk2/board.c | 295 +++++++++ hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake | 22 + hw/bsp/hpmicro/boards/hpm6750evk2/board.h | 105 ++++ hw/bsp/hpmicro/boards/hpm6750evk2/board.mk | 16 + hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c | 862 ++++++++++++++++++++++++++ hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h | 89 +++ hw/bsp/hpmicro/family.c | 115 ++++ hw/bsp/hpmicro/family.cmake | 131 ++++ hw/bsp/hpmicro/family.mk | 76 +++ src/common/tusb_mcu.h | 12 + src/portable/chipidea/ci_hs/ci_hs_hpm.h | 54 ++ src/portable/chipidea/ci_hs/dcd_ci_hs.c | 14 +- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 8 + src/portable/ehci/ehci.c | 12 + src/tusb_option.h | 3 + tools/get_deps.py | 3 + 16 files changed, 1816 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.c create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.h create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/board.mk create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c create mode 100644 hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h create mode 100644 hw/bsp/hpmicro/family.c create mode 100644 hw/bsp/hpmicro/family.cmake create mode 100644 hw/bsp/hpmicro/family.mk create mode 100644 src/portable/chipidea/ci_hs/ci_hs_hpm.h (limited to 'src') diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.c b/hw/bsp/hpmicro/boards/hpm6750evk2/board.c new file mode 100644 index 000000000..c281356e3 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.c @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2025 HPMicro + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "board.h" +#include "pinmux.h" +#include "hpm_pmp_drv.h" +#include "hpm_pllctl_drv.h" +#include "hpm_clock_drv.h" +#include "hpm_sysctl_drv.h" +#include "hpm_pcfg_drv.h" +#include "hpm_uart_drv.h" +#include "hpm_gpio_drv.h" + +/** + * @brief FLASH configuration option definitions: + * option[0]: + * [31:16] 0xfcf9 - FLASH configuration option tag + * [15:4] 0 - Reserved + * [3:0] option words (exclude option[0]) + * option[1]: + * [31:28] Flash probe type + * 0 - SFDP SDR / 1 - SFDP DDR + * 2 - 1-4-4 Read (0xEB, 24-bit address) / 3 - 1-2-2 Read(0xBB, 24-bit address) + * 4 - HyperFLASH 1.8V / 5 - HyperFLASH 3V + * 6 - OctaBus DDR (SPI -> OPI DDR) + * 8 - Xccela DDR (SPI -> OPI DDR) + * 10 - EcoXiP DDR (SPI -> OPI DDR) + * [27:24] Command Pads after Power-on Reset + * 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI + * [23:20] Command Pads after Configuring FLASH + * 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI + * [19:16] Quad Enable Sequence (for the device support SFDP 1.0 only) + * 0 - Not needed + * 1 - QE bit is at bit 6 in Status Register 1 + * 2 - QE bit is at bit1 in Status Register 2 + * 3 - QE bit is at bit7 in Status Register 2 + * 4 - QE bit is at bit1 in Status Register 2 and should be programmed by 0x31 + * [15:8] Dummy cycles + * 0 - Auto-probed / detected / default value + * Others - User specified value, for DDR read, the dummy cycles should be 2 * cycles on FLASH datasheet + * [7:4] Misc. + * 0 - Not used + * 1 - SPI mode + * 2 - Internal loopback + * 3 - External DQS + * [3:0] Frequency option + * 1 - 30MHz / 2 - 50MHz / 3 - 66MHz / 4 - 80MHz / 5 - 100MHz / 6 - 120MHz / 7 - 133MHz / 8 - 166MHz + * + * option[2] (Effective only if the bit[3:0] in option[0] > 1) + * [31:20] Reserved + * [19:16] IO voltage + * 0 - 3V / 1 - 1.8V + * [15:12] Pin group + * 0 - 1st group / 1 - 2nd group + * [11:8] Connection selection + * 0 - CA_CS0 / 1 - CB_CS0 / 2 - CA_CS0 + CB_CS0 (Two FLASH connected to CA and CB respectively) + * [7:0] Drive Strength + * 0 - Default value + * option[3] (Effective only if the bit[3:0] in option[0] > 2, required only for the QSPI NOR FLASH that not supports + * JESD216) + * [31:16] reserved + * [15:12] Sector Erase Command Option, not required here + * [11:8] Sector Size Option, not required here + * [7:0] Flash Size Option + * 0 - 4MB / 1 - 8MB / 2 - 16MB + */ +#if defined(FLASH_XIP) && FLASH_XIP +__attribute__ ((section(".nor_cfg_option"), used)) const uint32_t option[4] = {0xfcf90002, 0x00000007, 0xE, 0x0}; +#endif + +#if defined(FLASH_UF2) && FLASH_UF2 +ATTR_PLACE_AT(".uf2_signature") __attribute__((used)) const uint32_t uf2_signature = BOARD_UF2_SIGNATURE; +#endif + + +/* static function declarations */ +static void board_turnoff_rgb_led(void); +static void init_uart_pins(UART_Type *ptr); +static uint32_t board_init_uart_clock(UART_Type *ptr); +static void init_gpio_pins(void); +static void init_usb_pins(USB_Type *ptr); + +/* extern function definitions */ +void board_init_clock(void) +{ + uint32_t cpu0_freq = clock_get_frequency(clock_cpu0); + if (cpu0_freq == PLLCTL_SOC_PLL_REFCLK_FREQ) { + /* Configure the External OSC ramp-up time: ~9ms */ + pllctl_xtal_set_rampup_time(HPM_PLLCTL, 32UL * 1000UL * 9U); + + /* Select clock setting preset1 */ + sysctl_clock_set_preset(HPM_SYSCTL, sysctl_preset_1); + } + + /* Add clocks to group 0 */ + clock_add_to_group(clock_cpu0, 0); + clock_add_to_group(clock_mchtmr0, 0); + clock_add_to_group(clock_axi0, 0); + clock_add_to_group(clock_axi1, 0); + clock_add_to_group(clock_axi2, 0); + clock_add_to_group(clock_ahb, 0); + clock_add_to_group(clock_xdma, 0); + clock_add_to_group(clock_hdma, 0); + clock_add_to_group(clock_xpi0, 0); + clock_add_to_group(clock_xpi1, 0); + clock_add_to_group(clock_ram0, 0); + clock_add_to_group(clock_ram1, 0); + clock_add_to_group(clock_lmm0, 0); + clock_add_to_group(clock_lmm1, 0); + clock_add_to_group(clock_gpio, 0); + clock_add_to_group(clock_mot0, 0); + clock_add_to_group(clock_mot1, 0); + clock_add_to_group(clock_mot2, 0); + clock_add_to_group(clock_mot3, 0); + clock_add_to_group(clock_synt, 0); + clock_add_to_group(clock_ptpc, 0); + /* Connect Group0 to CPU0 */ + clock_connect_group_to_cpu(0, 0); + + /* Add clocks to Group1 */ + clock_add_to_group(clock_cpu1, 1); + clock_add_to_group(clock_mchtmr1, 1); + /* Connect Group1 to CPU1 */ + clock_connect_group_to_cpu(1, 1); + + /* Bump up DCDC voltage to 1275mv */ + pcfg_dcdc_set_voltage(HPM_PCFG, 1275); + pcfg_dcdc_switch_to_dcm_mode(HPM_PCFG); + + if (status_success != pllctl_init_int_pll_with_freq(HPM_PLLCTL, 0, BOARD_CPU_FREQ)) { + printf("Failed to set pll0_clk0 to %ldHz\n", BOARD_CPU_FREQ); + while (1) { + } + } + + clock_set_source_divider(clock_cpu0, clk_src_pll0_clk0, 1); + clock_set_source_divider(clock_cpu1, clk_src_pll0_clk0, 1); + clock_update_core_clock(); + + clock_set_source_divider(clock_ahb, clk_src_pll1_clk1, 2); /*200m hz*/ + clock_set_source_divider(clock_mchtmr0, clk_src_osc24m, 1); + clock_set_source_divider(clock_mchtmr1, clk_src_osc24m, 1); +} + +void board_init_pmp(void) +{ + uint32_t start_addr; + uint32_t end_addr; + uint32_t length; + pmp_entry_t pmp_entry[16] = {0}; + uint8_t index = 0; + + /* Init noncachable memory */ + extern uint32_t __noncacheable_start__[]; + extern uint32_t __noncacheable_end__[]; + start_addr = (uint32_t) __noncacheable_start__; + end_addr = (uint32_t) __noncacheable_end__; + length = end_addr - start_addr; + if (length > 0) { + /* Ensure the address and the length are power of 2 aligned */ + assert((length & (length - 1U)) == 0U); + assert((start_addr & (length - 1U)) == 0U); + pmp_entry[index].pmp_addr = PMP_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pmp_cfg.val = PMP_CFG(READ_EN, WRITE_EN, EXECUTE_EN, ADDR_MATCH_NAPOT, REG_UNLOCK); + pmp_entry[index].pma_addr = PMA_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pma_cfg.val = PMA_CFG(ADDR_MATCH_NAPOT, MEM_TYPE_MEM_NON_CACHE_BUF, AMO_EN); + index++; + } + + /* Init share memory */ + extern uint32_t __share_mem_start__[]; + extern uint32_t __share_mem_end__[]; + start_addr = (uint32_t)__share_mem_start__; + end_addr = (uint32_t)__share_mem_end__; + length = end_addr - start_addr; + if (length > 0) { + /* Ensure the address and the length are power of 2 aligned */ + assert((length & (length - 1U)) == 0U); + assert((start_addr & (length - 1U)) == 0U); + pmp_entry[index].pmp_addr = PMP_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pmp_cfg.val = PMP_CFG(READ_EN, WRITE_EN, EXECUTE_EN, ADDR_MATCH_NAPOT, REG_UNLOCK); + pmp_entry[index].pma_addr = PMA_NAPOT_ADDR(start_addr, length); + pmp_entry[index].pma_cfg.val = PMA_CFG(ADDR_MATCH_NAPOT, MEM_TYPE_MEM_NON_CACHE_BUF, AMO_EN); + index++; + } + + pmp_config(&pmp_entry[0], index); +} + +void board_init_console(void) +{ + uart_config_t config = {0}; + uint32_t freq; + + /* uart needs to configure pin function before enabling clock, otherwise the level change of + uart rx pin when configuring pin function will cause a wrong data to be received. + And a uart rx dma request will be generated by default uart fifo dma trigger level. */ + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); + + freq = board_init_uart_clock((UART_Type *)BOARD_CONSOLE_UART_BASE); + + uart_default_config((UART_Type *)BOARD_CONSOLE_UART_BASE, &config); + config.src_freq_in_hz = freq; + config.baudrate = BOARD_CONSOLE_UART_BAUDRATE; + uart_init((UART_Type *)BOARD_CONSOLE_UART_BASE, &config); +} + +void board_init_gpio_pins(void) +{ + init_gpio_pins(); +} + +void board_init_led_pins(void) +{ + board_turnoff_rgb_led(); + init_led_pins_as_gpio(); + gpio_set_pin_output_with_initial(BOARD_R_GPIO_CTRL, BOARD_R_GPIO_INDEX, BOARD_R_GPIO_PIN, BOARD_LED_OFF_LEVEL); + gpio_set_pin_output_with_initial(BOARD_G_GPIO_CTRL, BOARD_G_GPIO_INDEX, BOARD_G_GPIO_PIN, BOARD_LED_OFF_LEVEL); + gpio_set_pin_output_with_initial(BOARD_B_GPIO_CTRL, BOARD_B_GPIO_INDEX, BOARD_B_GPIO_PIN, BOARD_LED_OFF_LEVEL); +} + +void board_init_usb(USB_Type *ptr) +{ + clock_name_t usb_clk = (ptr == HPM_USB0) ? clock_usb0 : clock_usb1; + + init_usb_pins(ptr); + clock_add_to_group(usb_clk, 0); +} + +/* static function definitions */ +static void board_turnoff_rgb_led(void) +{ + uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(BOARD_LED_OFF_LEVEL); + HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PB11_FUNC_CTL_GPIO_B_11; + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_GPIO_B_12; + HPM_IOC->PAD[IOC_PAD_PB13].FUNC_CTL = IOC_PB13_FUNC_CTL_GPIO_B_13; + + HPM_IOC->PAD[IOC_PAD_PB11].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PB12].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PB13].PAD_CTL = pad_ctl; +} + +static void init_uart_pins(UART_Type *ptr) +{ + if (ptr == HPM_UART0) { + init_uart0_pins(); + } else if (ptr == HPM_UART2) { + init_uart2_pins(); + } else if (ptr == HPM_UART13) { + init_uart13_pins(); + } else if (ptr == HPM_PUART) { + init_puart_pins(); + } +} + +static uint32_t board_init_uart_clock(UART_Type *ptr) +{ + uint32_t freq = 0U; + if (ptr == HPM_UART0) { + clock_add_to_group(clock_uart0, 0); + freq = clock_get_frequency(clock_uart0); + } else if (ptr == HPM_UART6) { + clock_add_to_group(clock_uart6, 0); + freq = clock_get_frequency(clock_uart6); + } else if (ptr == HPM_UART13) { + clock_add_to_group(clock_uart13, 0); + freq = clock_get_frequency(clock_uart13); + } else if (ptr == HPM_UART14) { + clock_add_to_group(clock_uart14, 0); + freq = clock_get_frequency(clock_uart14); + } else { + /* Not supported */ + } + return freq; +} + +static void init_gpio_pins(void) +{ + init_gpio_pins_with_pull_up(); +#ifdef USING_GPIO0_FOR_GPIOZ + init_gpio_pins_using_gpio0(); +#endif +} + +static void init_usb_pins(USB_Type *ptr) +{ + if (ptr == HPM_USB0) { + init_usb0_pins(); + } else if (ptr == HPM_USB1) { + init_usb1_pins(); + } +} diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake b/hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake new file mode 100644 index 000000000..b15911cb5 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.cmake @@ -0,0 +1,22 @@ +set(MCU_VARIANT HPM6750xVMx) +set(JLINK_DEVICE ${MCU_VARIANT}) + +set(JLINK_IF jtag) + +set(HPM_SOC ${SDK_DIR}/soc/HPM6700/HPM6750) +set(HPM_IP_REGS ${SDK_DIR}/soc/HPM6700/ip) + +set(BOARD_FLASH_SIZE 16M) +set(BOARD_STACK_SIZE 16K) +set(BOARD_HEAP_SIZE 16K) + +set(HPM_PLLCTL_DRV_FILE hpm_pllctl_drv.c) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + BOARD_TUD_RHPORT=0 + BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + BOARD_TUH_RHPORT=1 + BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED + ) +endfunction() diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.h b/hw/bsp/hpmicro/boards/hpm6750evk2/board.h new file mode 100644 index 000000000..0636a4722 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021-2025 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _HPM_BOARD_H +#define _HPM_BOARD_H + +#include +#include "hpm_common.h" +#include "hpm_soc.h" +#include "hpm_soc_feature.h" +#include "pinmux.h" + +#define BOARD_NAME "hpm6750evk2" + +#ifndef BOARD_RUNNING_CORE +#define BOARD_RUNNING_CORE HPM_CORE0 +#endif + +#define BOARD_CPU_FREQ (816000000UL) + +/* console section */ +#if BOARD_RUNNING_CORE == HPM_CORE0 + #define BOARD_CONSOLE_UART_BASE HPM_UART0 + #define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 + #define BOARD_CONSOLE_UART_IRQ IRQn_UART0 + #define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX + #define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX +#else + #define BOARD_CONSOLE_UART_BASE HPM_UART13 + #define BOARD_CONSOLE_UART_CLK_NAME clock_uart13 + #define BOARD_CONSOLE_UART_IRQ IRQn_UART13 + #define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX + #define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX +#endif + +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) + +/* sdram section */ +#define BOARD_SDRAM_ADDRESS (0x40000000UL) +#define BOARD_SDRAM_SIZE (32 * SIZE_1MB) +#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 +#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_32_BITS +#define BOARD_SDRAM_COLUMN_ADDR_BITS FEMC_SDRAM_COLUMN_ADDR_9_BITS +#define BOARD_SDRAM_REFRESH_COUNT (8192UL) +#define BOARD_SDRAM_REFRESH_IN_MS (64UL) + +#define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) +#define BOARD_FLASH_SIZE (16 << 20) + +/* gpio section */ +#define BOARD_R_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_R_GPIO_PIN 11 +#define BOARD_G_GPIO_CTRL HPM_GPIO0 +#define BOARD_G_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_G_GPIO_PIN 12 +#define BOARD_B_GPIO_CTRL HPM_GPIO0 +#define BOARD_B_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_B_GPIO_PIN 13 + +#define BOARD_LED_GPIO_CTRL HPM_GPIO0 + +#define BOARD_LED_GPIO_INDEX GPIO_DI_GPIOB +#define BOARD_LED_GPIO_PIN 12 +#define BOARD_LED_OFF_LEVEL 0 +#define BOARD_LED_ON_LEVEL 1 + +#define BOARD_LED_TOGGLE_RGB 1 + +#define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOZ +#define BOARD_APP_GPIO_PIN 2 +#define BOARD_BUTTON_PRESSED_VALUE 0 + +#define USING_GPIO0_FOR_GPIOZ +#ifndef USING_GPIO0_FOR_GPIOZ +#define BOARD_APP_GPIO_CTRL HPM_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#else +#define BOARD_APP_GPIO_CTRL HPM_GPIO0 +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z +#endif + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + + +void board_init_clock(void); +void board_init_pmp(void); +void board_init_console(void); +void board_init_gpio_pins(void); +void board_init_led_pins(void); +void board_init_usb(USB_Type *ptr); +void board_print_banner(void); +void board_print_clock_freq(void); + + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ +#endif /* _HPM_BOARD_H */ diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/board.mk b/hw/bsp/hpmicro/boards/hpm6750evk2/board.mk new file mode 100644 index 000000000..26981ce28 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/board.mk @@ -0,0 +1,16 @@ +MCU_VARIANT = HPM6750xVMx +JLINK_DEVICE = ${MCU_VARIANT} + +JLINK_IF = jtag + +HPM_SOC = $(SDK_DIR)/soc/HPM6700/HPM6750 +HPM_IP_REGS = $(SDK_DIR)/soc/HPM6700/ip + +BOARD_FLASH_SIZE = 16M +BOARD_STACK_SIZE = 16K +BOARD_HEAP_SIZE = 16K + +BOARD_TUD_RHPORT = 0 +BOARD_TUH_RHPORT = 1 + +HPM_PLLCTL_DRV_FILE = hpm_pllctl_drv.c diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c new file mode 100644 index 000000000..7554e3a76 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.c @@ -0,0 +1,862 @@ + +/* + * Copyright (c) 2025 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + * Automatically generated by HPM Pinmux Tool + * + * + * Note: + * PY and PZ IOs: if any SOC pin function needs to be routed to these IOs, + * besides of IOC, PIOC/BIOC needs to be configured SOC_GPIO_X_xx, so that + * expected SoC function can be enabled on these IOs. + */ + +#include "pinmux.h" +#include "board.h" +#include "hpm_trgm_drv.h" + + +/* PY port IO needs to configure PIOC as well */ +void init_uart0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07; + + HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06; +} + +void init_uart2_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PE16_FUNC_CTL_UART2_TXD; + + HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PE21_FUNC_CTL_UART2_RXD; +} + +/* PZ port IO needs to configure BIOC as well */ +void init_uart13_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_UART13_RXD; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; + + HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_UART13_TXD; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; +} + +void init_puart_pins(void) +{ + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_PUART_TXD; + + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_PUART_RXD; +} + +/* + * PZ port IO needs to configure BIOC as well. + * PZ08 and PZ09 need pull up. + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_uart13_pins_as_gpio(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_GPIO_Z_08; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_IOC->PAD[IOC_PAD_PZ08].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); + + HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_GPIO_Z_09; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; +} + +void init_lcd0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PB03].FUNC_CTL = IOC_PB03_FUNC_CTL_DIS0_R_0; + + HPM_IOC->PAD[IOC_PAD_PB04].FUNC_CTL = IOC_PB04_FUNC_CTL_DIS0_R_1; + + HPM_IOC->PAD[IOC_PAD_PB00].FUNC_CTL = IOC_PB00_FUNC_CTL_DIS0_R_2; + + HPM_IOC->PAD[IOC_PAD_PA31].FUNC_CTL = IOC_PA31_FUNC_CTL_DIS0_R_3; + + HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_DIS0_R_4; + + HPM_IOC->PAD[IOC_PAD_PA21].FUNC_CTL = IOC_PA21_FUNC_CTL_DIS0_R_5; + + HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_DIS0_R_6; + + HPM_IOC->PAD[IOC_PAD_PA28].FUNC_CTL = IOC_PA28_FUNC_CTL_DIS0_R_7; + + HPM_IOC->PAD[IOC_PAD_PB06].FUNC_CTL = IOC_PB06_FUNC_CTL_DIS0_G_0; + + HPM_IOC->PAD[IOC_PAD_PB01].FUNC_CTL = IOC_PB01_FUNC_CTL_DIS0_G_1; + + HPM_IOC->PAD[IOC_PAD_PA22].FUNC_CTL = IOC_PA22_FUNC_CTL_DIS0_G_2; + + HPM_IOC->PAD[IOC_PAD_PA23].FUNC_CTL = IOC_PA23_FUNC_CTL_DIS0_G_3; + + HPM_IOC->PAD[IOC_PAD_PA29].FUNC_CTL = IOC_PA29_FUNC_CTL_DIS0_G_4; + + HPM_IOC->PAD[IOC_PAD_PA24].FUNC_CTL = IOC_PA24_FUNC_CTL_DIS0_G_5; + + HPM_IOC->PAD[IOC_PAD_PA30].FUNC_CTL = IOC_PA30_FUNC_CTL_DIS0_G_6; + + HPM_IOC->PAD[IOC_PAD_PA25].FUNC_CTL = IOC_PA25_FUNC_CTL_DIS0_G_7; + + HPM_IOC->PAD[IOC_PAD_PB05].FUNC_CTL = IOC_PB05_FUNC_CTL_DIS0_B_0; + + HPM_IOC->PAD[IOC_PAD_PB07].FUNC_CTL = IOC_PB07_FUNC_CTL_DIS0_B_1; + + HPM_IOC->PAD[IOC_PAD_PB02].FUNC_CTL = IOC_PB02_FUNC_CTL_DIS0_B_2; + + HPM_IOC->PAD[IOC_PAD_PA16].FUNC_CTL = IOC_PA16_FUNC_CTL_DIS0_B_3; + + HPM_IOC->PAD[IOC_PAD_PA12].FUNC_CTL = IOC_PA12_FUNC_CTL_DIS0_B_4; + + HPM_IOC->PAD[IOC_PAD_PA17].FUNC_CTL = IOC_PA17_FUNC_CTL_DIS0_B_5; + + HPM_IOC->PAD[IOC_PAD_PA13].FUNC_CTL = IOC_PA13_FUNC_CTL_DIS0_B_6; + + HPM_IOC->PAD[IOC_PAD_PA18].FUNC_CTL = IOC_PA18_FUNC_CTL_DIS0_B_7; + + HPM_IOC->PAD[IOC_PAD_PA20].FUNC_CTL = IOC_PA20_FUNC_CTL_DIS0_CLK; + + HPM_IOC->PAD[IOC_PAD_PA15].FUNC_CTL = IOC_PA15_FUNC_CTL_DIS0_EN; + + HPM_IOC->PAD[IOC_PAD_PA19].FUNC_CTL = IOC_PA19_FUNC_CTL_DIS0_HSYNC; + + HPM_IOC->PAD[IOC_PAD_PA14].FUNC_CTL = IOC_PA14_FUNC_CTL_DIS0_VSYNC; + + /* PWM */ + HPM_IOC->PAD[IOC_PAD_PB10].FUNC_CTL = IOC_PB10_FUNC_CTL_GPIO_B_10; + + /* RST */ + HPM_IOC->PAD[IOC_PAD_PB16].FUNC_CTL = IOC_PB16_FUNC_CTL_GPIO_B_16; + + HPM_IOC->PAD[IOC_PAD_PZ00].FUNC_CTL = IOC_PZ00_FUNC_CTL_GPIO_Z_00; + HPM_BIOC->PAD[IOC_PAD_PZ00].FUNC_CTL = BIOC_PZ00_FUNC_CTL_SOC_PZ_00; + HPM_IOC->PAD[IOC_PAD_PZ00].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_cap_pins(void) +{ + /* CAP_INT */ + HPM_IOC->PAD[IOC_PAD_PB08].FUNC_CTL = IOC_PB08_FUNC_CTL_GPIO_B_08; + HPM_IOC->PAD[IOC_PAD_PB08].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(1); + + /* CAP_RST */ + HPM_IOC->PAD[IOC_PAD_PB09].FUNC_CTL = IOC_PB09_FUNC_CTL_GPIO_B_09; + HPM_IOC->PAD[IOC_PAD_PB09].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(1); +} + +/* PZ port IO needs to configure BIOC as well */ +void init_i2c0_pins_as_gpio(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_GPIO_Z_11; + HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = BIOC_PZ11_FUNC_CTL_SOC_PZ_11; + + HPM_IOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_GPIO_Z_10; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_SOC_PZ_10; +} + +/* PZ port IO needs to configure BIOC as well */ +void init_i2c0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_I2C0_SCL | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = BIOC_PZ11_FUNC_CTL_SOC_PZ_11; + HPM_IOC->PAD[IOC_PAD_PZ11].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); + + HPM_IOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_I2C0_SDA | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_SOC_PZ_10; + HPM_IOC->PAD[IOC_PAD_PZ10].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); +} + +void init_femc_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PC01].FUNC_CTL = IOC_PC01_FUNC_CTL_FEMC_DQ_16; + + HPM_IOC->PAD[IOC_PAD_PC00].FUNC_CTL = IOC_PC00_FUNC_CTL_FEMC_DQ_17; + + HPM_IOC->PAD[IOC_PAD_PB31].FUNC_CTL = IOC_PB31_FUNC_CTL_FEMC_DQ_18; + + HPM_IOC->PAD[IOC_PAD_PB30].FUNC_CTL = IOC_PB30_FUNC_CTL_FEMC_DQ_30; + + HPM_IOC->PAD[IOC_PAD_PB29].FUNC_CTL = IOC_PB29_FUNC_CTL_FEMC_DQ_31; + + HPM_IOC->PAD[IOC_PAD_PB28].FUNC_CTL = IOC_PB28_FUNC_CTL_FEMC_DQ_19; + + HPM_IOC->PAD[IOC_PAD_PB27].FUNC_CTL = IOC_PB27_FUNC_CTL_FEMC_DQ_20; + + HPM_IOC->PAD[IOC_PAD_PB26].FUNC_CTL = IOC_PB26_FUNC_CTL_FEMC_DQ_21; + + HPM_IOC->PAD[IOC_PAD_PB25].FUNC_CTL = IOC_PB25_FUNC_CTL_FEMC_DQ_28; + + HPM_IOC->PAD[IOC_PAD_PB24].FUNC_CTL = IOC_PB24_FUNC_CTL_FEMC_DQ_29; + + HPM_IOC->PAD[IOC_PAD_PB23].FUNC_CTL = IOC_PB23_FUNC_CTL_FEMC_DQ_22; + + HPM_IOC->PAD[IOC_PAD_PB22].FUNC_CTL = IOC_PB22_FUNC_CTL_FEMC_DQ_26; + + HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_FEMC_DQ_27; + + HPM_IOC->PAD[IOC_PAD_PB20].FUNC_CTL = IOC_PB20_FUNC_CTL_FEMC_DQ_23; + + HPM_IOC->PAD[IOC_PAD_PB19].FUNC_CTL = IOC_PB19_FUNC_CTL_FEMC_DQ_24; + + HPM_IOC->PAD[IOC_PAD_PB18].FUNC_CTL = IOC_PB18_FUNC_CTL_FEMC_DQ_25; + + HPM_IOC->PAD[IOC_PAD_PD13].FUNC_CTL = IOC_PD13_FUNC_CTL_FEMC_DQ_14; + + HPM_IOC->PAD[IOC_PAD_PD12].FUNC_CTL = IOC_PD12_FUNC_CTL_FEMC_DQ_15; + + HPM_IOC->PAD[IOC_PAD_PD10].FUNC_CTL = IOC_PD10_FUNC_CTL_FEMC_DQ_12; + + HPM_IOC->PAD[IOC_PAD_PD09].FUNC_CTL = IOC_PD09_FUNC_CTL_FEMC_DQ_13; + + HPM_IOC->PAD[IOC_PAD_PD08].FUNC_CTL = IOC_PD08_FUNC_CTL_FEMC_DQ_00; + + HPM_IOC->PAD[IOC_PAD_PD07].FUNC_CTL = IOC_PD07_FUNC_CTL_FEMC_DQ_10; + + HPM_IOC->PAD[IOC_PAD_PD06].FUNC_CTL = IOC_PD06_FUNC_CTL_FEMC_DQ_11; + + HPM_IOC->PAD[IOC_PAD_PD05].FUNC_CTL = IOC_PD05_FUNC_CTL_FEMC_DQ_01; + + HPM_IOC->PAD[IOC_PAD_PD04].FUNC_CTL = IOC_PD04_FUNC_CTL_FEMC_DQ_08; + + HPM_IOC->PAD[IOC_PAD_PD03].FUNC_CTL = IOC_PD03_FUNC_CTL_FEMC_DQ_09; + + HPM_IOC->PAD[IOC_PAD_PD02].FUNC_CTL = IOC_PD02_FUNC_CTL_FEMC_DQ_04; + + HPM_IOC->PAD[IOC_PAD_PD01].FUNC_CTL = IOC_PD01_FUNC_CTL_FEMC_DQ_03; + + HPM_IOC->PAD[IOC_PAD_PD00].FUNC_CTL = IOC_PD00_FUNC_CTL_FEMC_DQ_02; + + HPM_IOC->PAD[IOC_PAD_PC29].FUNC_CTL = IOC_PC29_FUNC_CTL_FEMC_DQ_07; + + HPM_IOC->PAD[IOC_PAD_PC28].FUNC_CTL = IOC_PC28_FUNC_CTL_FEMC_DQ_06; + + HPM_IOC->PAD[IOC_PAD_PC27].FUNC_CTL = IOC_PC27_FUNC_CTL_FEMC_DQ_05; + + /* SRAM #WE */ + HPM_IOC->PAD[IOC_PAD_PC21].FUNC_CTL = IOC_PC21_FUNC_CTL_FEMC_A_11; + + HPM_IOC->PAD[IOC_PAD_PC17].FUNC_CTL = IOC_PC17_FUNC_CTL_FEMC_A_09; + + HPM_IOC->PAD[IOC_PAD_PC15].FUNC_CTL = IOC_PC15_FUNC_CTL_FEMC_A_10; + + HPM_IOC->PAD[IOC_PAD_PC12].FUNC_CTL = IOC_PC12_FUNC_CTL_FEMC_A_08; + + HPM_IOC->PAD[IOC_PAD_PC11].FUNC_CTL = IOC_PC11_FUNC_CTL_FEMC_A_07; + + HPM_IOC->PAD[IOC_PAD_PC10].FUNC_CTL = IOC_PC10_FUNC_CTL_FEMC_A_06; + + HPM_IOC->PAD[IOC_PAD_PC09].FUNC_CTL = IOC_PC09_FUNC_CTL_FEMC_A_01; + + HPM_IOC->PAD[IOC_PAD_PC08].FUNC_CTL = IOC_PC08_FUNC_CTL_FEMC_A_00; + + HPM_IOC->PAD[IOC_PAD_PC07].FUNC_CTL = IOC_PC07_FUNC_CTL_FEMC_A_05; + + HPM_IOC->PAD[IOC_PAD_PC06].FUNC_CTL = IOC_PC06_FUNC_CTL_FEMC_A_04; + + HPM_IOC->PAD[IOC_PAD_PC05].FUNC_CTL = IOC_PC05_FUNC_CTL_FEMC_A_03; + + HPM_IOC->PAD[IOC_PAD_PC04].FUNC_CTL = IOC_PC04_FUNC_CTL_FEMC_A_02; + + /* SRAM #ADV */ + HPM_IOC->PAD[IOC_PAD_PC14].FUNC_CTL = IOC_PC14_FUNC_CTL_FEMC_BA1; + + HPM_IOC->PAD[IOC_PAD_PC13].FUNC_CTL = IOC_PC13_FUNC_CTL_FEMC_BA0; + + HPM_IOC->PAD[IOC_PAD_PC16].FUNC_CTL = IOC_PC16_FUNC_CTL_FEMC_DQS | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + + HPM_IOC->PAD[IOC_PAD_PC26].FUNC_CTL = IOC_PC26_FUNC_CTL_FEMC_CLK; + + HPM_IOC->PAD[IOC_PAD_PC25].FUNC_CTL = IOC_PC25_FUNC_CTL_FEMC_CKE; + + HPM_IOC->PAD[IOC_PAD_PC19].FUNC_CTL = IOC_PC19_FUNC_CTL_FEMC_CS_0; + + HPM_IOC->PAD[IOC_PAD_PC18].FUNC_CTL = IOC_PC18_FUNC_CTL_FEMC_RAS; + + HPM_IOC->PAD[IOC_PAD_PC23].FUNC_CTL = IOC_PC23_FUNC_CTL_FEMC_CAS; + + HPM_IOC->PAD[IOC_PAD_PC24].FUNC_CTL = IOC_PC24_FUNC_CTL_FEMC_WE; + + /* SRAM #LB */ + HPM_IOC->PAD[IOC_PAD_PC30].FUNC_CTL = IOC_PC30_FUNC_CTL_FEMC_DM_0; + + /* SRAM #UB */ + HPM_IOC->PAD[IOC_PAD_PC31].FUNC_CTL = IOC_PC31_FUNC_CTL_FEMC_DM_1; + + HPM_IOC->PAD[IOC_PAD_PC02].FUNC_CTL = IOC_PC02_FUNC_CTL_FEMC_DM_2; + + HPM_IOC->PAD[IOC_PAD_PC03].FUNC_CTL = IOC_PC03_FUNC_CTL_FEMC_DM_3; + + /* SRAM #CE */ + HPM_IOC->PAD[IOC_PAD_PC20].FUNC_CTL = IOC_PC20_FUNC_CTL_FEMC_CS_1; + + /* SRAM #OE */ + HPM_IOC->PAD[IOC_PAD_PC22].FUNC_CTL = IOC_PC22_FUNC_CTL_FEMC_A_12; +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_gpio_pins_with_pull_up(void) +{ + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_GPIO_B_12; + HPM_IOC->PAD[IOC_PAD_PB12].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(0); +} + +/* + * PZ port IO needs to configure BIOC as well. + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_gpio_pins_using_gpio0(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_GPIO_Z_02; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_SOC_PZ_02; + HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_spi2_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE31].FUNC_CTL = IOC_PE31_FUNC_CTL_SPI2_CSN; + HPM_IOC->PAD[IOC_PAD_PE31].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); + + HPM_IOC->PAD[IOC_PAD_PE30].FUNC_CTL = IOC_PE30_FUNC_CTL_SPI2_MOSI; + HPM_IOC->PAD[IOC_PAD_PE30].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE27].FUNC_CTL = IOC_PE27_FUNC_CTL_SPI2_SCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PE27].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE28].FUNC_CTL = IOC_PE28_FUNC_CTL_SPI2_MISO; + HPM_IOC->PAD[IOC_PAD_PE28].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; +} + +/* + * Errata: E00029:IOC PAD_CTL register write restrictions. + * When the PE bit is 1, bit [3] must be set to 1, + * and DS can only be selected as 0b001 (low drive strength) or 0b110 (high drive strength). + */ +void init_spi2_pins_with_gpio_as_cs(void) +{ + HPM_IOC->PAD[IOC_PAD_PE27].FUNC_CTL = IOC_PE27_FUNC_CTL_SPI2_SCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PE27].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE28].FUNC_CTL = IOC_PE28_FUNC_CTL_SPI2_MISO; + HPM_IOC->PAD[IOC_PAD_PE28].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE30].FUNC_CTL = IOC_PE30_FUNC_CTL_SPI2_MOSI; + HPM_IOC->PAD[IOC_PAD_PE30].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08; + + HPM_IOC->PAD[IOC_PAD_PE31].FUNC_CTL = IOC_PE31_FUNC_CTL_GPIO_E_31; + HPM_IOC->PAD[IOC_PAD_PE31].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_gptmr3_pins(void) +{ + /* TMR3 compare 1 */ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PE24_FUNC_CTL_GPTMR3_COMP_1; +} + +void init_gptmr4_pins(void) +{ + /* TMR4 capture 1 */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_GPTMR4_CAPT_1; +} + +void init_gptmr5_pins(void) +{ + /* TMR5 compare 2 */ + HPM_IOC->PAD[IOC_PAD_PD24].FUNC_CTL = IOC_PD24_FUNC_CTL_TRGM2_P_10; + + /* TMR5 compare 3 */ + HPM_IOC->PAD[IOC_PAD_PD23].FUNC_CTL = IOC_PD23_FUNC_CTL_TRGM2_P_11; + + trgm_output_t trgm2_io_config0 = {0}; + trgm2_io_config0.invert = 0; + trgm2_io_config0.type = trgm_output_same_as_input; + trgm2_io_config0.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT2; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P10, &trgm2_io_config0); + + trgm_enable_io_output(HPM_TRGM2, 1 << 10); + + trgm_output_t trgm2_io_config1 = {0}; + trgm2_io_config1.invert = 0; + trgm2_io_config1.type = trgm_output_same_as_input; + trgm2_io_config1.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT3; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P11, &trgm2_io_config1); + + trgm_enable_io_output(HPM_TRGM2, 1 << 11); +} + +void init_hall_trgm_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PD16].FUNC_CTL = IOC_PD16_FUNC_CTL_TRGM2_P_06; + + HPM_IOC->PAD[IOC_PAD_PD20].FUNC_CTL = IOC_PD20_FUNC_CTL_TRGM2_P_07; + + HPM_IOC->PAD[IOC_PAD_PD25].FUNC_CTL = IOC_PD25_FUNC_CTL_TRGM2_P_08; +} + +void init_qei_trgm_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PD19].FUNC_CTL = IOC_PD19_FUNC_CTL_TRGM2_P_09; + + HPM_IOC->PAD[IOC_PAD_PD24].FUNC_CTL = IOC_PD24_FUNC_CTL_TRGM2_P_10; +} + +void init_i2s0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF02].FUNC_CTL = IOC_PF02_FUNC_CTL_I2S0_RXD_2; + + HPM_IOC->PAD[IOC_PAD_PF03].FUNC_CTL = IOC_PF03_FUNC_CTL_I2S0_MCLK; + + HPM_IOC->PAD[IOC_PAD_PF04].FUNC_CTL = IOC_PF04_FUNC_CTL_I2S0_TXD_2; + + HPM_IOC->PAD[IOC_PAD_PF06].FUNC_CTL = IOC_PF06_FUNC_CTL_I2S0_BCLK; + + HPM_IOC->PAD[IOC_PAD_PF09].FUNC_CTL = IOC_PF09_FUNC_CTL_I2S0_FCLK; +} + +/* PY port IO needs to configure PIOC */ +void init_dao_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PY08].FUNC_CTL = IOC_PY08_FUNC_CTL_DAOR_P; + HPM_PIOC->PAD[IOC_PAD_PY08].FUNC_CTL = PIOC_PY08_FUNC_CTL_SOC_PY_08; + + HPM_IOC->PAD[IOC_PAD_PY09].FUNC_CTL = IOC_PY09_FUNC_CTL_DAOR_N; + HPM_PIOC->PAD[IOC_PAD_PY09].FUNC_CTL = PIOC_PY09_FUNC_CTL_SOC_PY_09; +} + +/* PY port IO needs to configure PIOC */ +void init_pdm_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_PDM0_CLK; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_SOC_PY_10; + + HPM_IOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_PDM0_D_0; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_SOC_PY_11; +} + +void init_vad_pins(void) +{ + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_VAD_CLK; + + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_VAD_DAT; +} + +void init_cam_pins(void) +{ + /* configure rst pin function, PY port IO needs to configure PIOC */ + HPM_IOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_GPIO_Y_05; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_SOC_PY_05; + + HPM_IOC->PAD[IOC_PAD_PA07].FUNC_CTL = IOC_PA07_FUNC_CTL_CAM0_D_2; + + HPM_IOC->PAD[IOC_PAD_PA03].FUNC_CTL = IOC_PA03_FUNC_CTL_CAM0_D_3; + + HPM_IOC->PAD[IOC_PAD_PA08].FUNC_CTL = IOC_PA08_FUNC_CTL_CAM0_D_4; + + HPM_IOC->PAD[IOC_PAD_PA09].FUNC_CTL = IOC_PA09_FUNC_CTL_CAM0_D_5; + + HPM_IOC->PAD[IOC_PAD_PA00].FUNC_CTL = IOC_PA00_FUNC_CTL_CAM0_D_6; + + HPM_IOC->PAD[IOC_PAD_PA04].FUNC_CTL = IOC_PA04_FUNC_CTL_CAM0_D_7; + + HPM_IOC->PAD[IOC_PAD_PA01].FUNC_CTL = IOC_PA01_FUNC_CTL_CAM0_D_8; + + HPM_IOC->PAD[IOC_PAD_PA02].FUNC_CTL = IOC_PA02_FUNC_CTL_CAM0_D_9; + + HPM_IOC->PAD[IOC_PAD_PA10].FUNC_CTL = IOC_PA10_FUNC_CTL_CAM0_XCLK; + + HPM_IOC->PAD[IOC_PAD_PA05].FUNC_CTL = IOC_PA05_FUNC_CTL_CAM0_HSYNC; + + HPM_IOC->PAD[IOC_PAD_PA06].FUNC_CTL = IOC_PA06_FUNC_CTL_CAM0_VSYNC; + + HPM_IOC->PAD[IOC_PAD_PA11].FUNC_CTL = IOC_PA11_FUNC_CTL_CAM0_PIXCLK; +} + +void init_butn_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_PBUTN; + + HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = BIOC_PZ03_FUNC_CTL_WBUTN; + + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_PLED; + + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_WLED; +} + +void init_acmp_pins(void) +{ + /* configure to ACMP_COMP_1(ALT16) function */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_ACMP_COMP_1; + + /* configure to CMP1_INP7 function */ + HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + + /* configure to CMP1_INN6 function */ + HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_enet0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF00].FUNC_CTL = IOC_PF00_FUNC_CTL_GPIO_F_00; + + HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PE23_FUNC_CTL_ETH0_MDIO; + + HPM_IOC->PAD[IOC_PAD_PE22].FUNC_CTL = IOC_PE22_FUNC_CTL_ETH0_MDC; + + HPM_IOC->PAD[IOC_PAD_PD31].FUNC_CTL = IOC_PD31_FUNC_CTL_ETH0_RXD_0; + + HPM_IOC->PAD[IOC_PAD_PE04].FUNC_CTL = IOC_PE04_FUNC_CTL_ETH0_RXD_1; + + HPM_IOC->PAD[IOC_PAD_PE02].FUNC_CTL = IOC_PE02_FUNC_CTL_ETH0_RXD_2; + + HPM_IOC->PAD[IOC_PAD_PE07].FUNC_CTL = IOC_PE07_FUNC_CTL_ETH0_RXD_3; + + HPM_IOC->PAD[IOC_PAD_PE03].FUNC_CTL = IOC_PE03_FUNC_CTL_ETH0_RXCK; + + HPM_IOC->PAD[IOC_PAD_PD30].FUNC_CTL = IOC_PD30_FUNC_CTL_ETH0_RXDV; + + HPM_IOC->PAD[IOC_PAD_PE06].FUNC_CTL = IOC_PE06_FUNC_CTL_ETH0_TXD_0; + + HPM_IOC->PAD[IOC_PAD_PD29].FUNC_CTL = IOC_PD29_FUNC_CTL_ETH0_TXD_1; + + HPM_IOC->PAD[IOC_PAD_PD28].FUNC_CTL = IOC_PD28_FUNC_CTL_ETH0_TXD_2; + + HPM_IOC->PAD[IOC_PAD_PE05].FUNC_CTL = IOC_PE05_FUNC_CTL_ETH0_TXD_3; + + HPM_IOC->PAD[IOC_PAD_PE01].FUNC_CTL = IOC_PE01_FUNC_CTL_ETH0_TXCK; + + HPM_IOC->PAD[IOC_PAD_PE00].FUNC_CTL = IOC_PE00_FUNC_CTL_ETH0_TXEN; +} + +void init_enet1_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE26].FUNC_CTL = IOC_PE26_FUNC_CTL_GPIO_E_26; + + HPM_IOC->PAD[IOC_PAD_PD11].FUNC_CTL = IOC_PD11_FUNC_CTL_ETH1_MDC; + + HPM_IOC->PAD[IOC_PAD_PD14].FUNC_CTL = IOC_PD14_FUNC_CTL_ETH1_MDIO; + + HPM_IOC->PAD[IOC_PAD_PE20].FUNC_CTL = IOC_PE20_FUNC_CTL_ETH1_RXD_0; + + HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PE18_FUNC_CTL_ETH1_RXD_1; + + HPM_IOC->PAD[IOC_PAD_PE15].FUNC_CTL = IOC_PE15_FUNC_CTL_ETH1_RXDV; + + HPM_IOC->PAD[IOC_PAD_PE19].FUNC_CTL = IOC_PE19_FUNC_CTL_ETH1_TXD_0; + + HPM_IOC->PAD[IOC_PAD_PE17].FUNC_CTL = IOC_PE17_FUNC_CTL_ETH1_TXD_1; + + HPM_IOC->PAD[IOC_PAD_PE14].FUNC_CTL = IOC_PE14_FUNC_CTL_ETH1_TXEN; + + HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PE16_FUNC_CTL_ETH1_REFCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; +} + +void init_pwm2_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PD28].FUNC_CTL = IOC_PD28_FUNC_CTL_PWM2_P_5; + + HPM_IOC->PAD[IOC_PAD_PD29].FUNC_CTL = IOC_PD29_FUNC_CTL_PWM2_P_4; + + HPM_IOC->PAD[IOC_PAD_PD30].FUNC_CTL = IOC_PD30_FUNC_CTL_PWM2_P_1; + + HPM_IOC->PAD[IOC_PAD_PD31].FUNC_CTL = IOC_PD31_FUNC_CTL_PWM2_P_0; + + HPM_IOC->PAD[IOC_PAD_PE03].FUNC_CTL = IOC_PE03_FUNC_CTL_PWM2_P_3; + + HPM_IOC->PAD[IOC_PAD_PE04].FUNC_CTL = IOC_PE04_FUNC_CTL_PWM2_P_2; +} + +void init_pwm3_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE17].FUNC_CTL = IOC_PE17_FUNC_CTL_PWM3_P_6; + + HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PE18_FUNC_CTL_PWM3_P_7; +} + +void init_adc12_pins(void) +{ + /* ADC0.VIN11 */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_adc16_pins(void) +{ + /* ADC3.INA2 */ + HPM_IOC->PAD[IOC_PAD_PE29].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_adc_bldc_pins(void) +{ + /* ADC0.VINP7 */ + HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + + /* ADC1.VINP10 */ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + + /* ADC2.VINP11 */ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_usb0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF10].FUNC_CTL = IOC_PF10_FUNC_CTL_USB0_ID; + + HPM_IOC->PAD[IOC_PAD_PF08].FUNC_CTL = IOC_PF08_FUNC_CTL_USB0_OC; +} + +void init_usb1_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF07].FUNC_CTL = IOC_PF07_FUNC_CTL_USB1_ID; + + HPM_IOC->PAD[IOC_PAD_PF05].FUNC_CTL = IOC_PF05_FUNC_CTL_USB1_OC; +} + +void init_can0_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PB15].FUNC_CTL = IOC_PB15_FUNC_CTL_CAN0_TXD; + + HPM_IOC->PAD[IOC_PAD_PB17].FUNC_CTL = IOC_PB17_FUNC_CTL_CAN0_RXD; +} + +void init_mcan0_transceiver_phy_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PB14].FUNC_CTL = IOC_PB14_FUNC_CTL_GPIO_B_14; +} + +void init_sdxc1_cmd_pin_enable_1v8_enable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(1); +} + +void init_sdxc1_cmd_pin_enable_1v8_disable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(0); +} + +void init_sdxc1_cmd_pin_disable_1v8_enable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(1); +} + +void init_sdxc1_cmd_pin_disable_1v8_disable_opendrain(void) +{ + /* SDXC1.CMD */ + HPM_IOC->PAD[IOC_PAD_PD21].FUNC_CTL = IOC_PD21_FUNC_CTL_SDC1_CMD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PD21].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(0); +} + +void init_sdxc1_cd_pin(void) +{ + /* SDXC1.CDN */ + HPM_IOC->PAD[IOC_PAD_PD15].FUNC_CTL = IOC_PD15_FUNC_CTL_GPIO_D_15; + HPM_IOC->PAD[IOC_PAD_PD15].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_enable_1v8(void) +{ + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_disable_1v8(void) +{ + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_width4_enable_1v8(void) +{ + /* SDXC1.DATA1 */ + HPM_IOC->PAD[IOC_PAD_PD17].FUNC_CTL = IOC_PD17_FUNC_CTL_SDC1_DATA_1; + HPM_IOC->PAD[IOC_PAD_PD17].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA2 */ + HPM_IOC->PAD[IOC_PAD_PD27].FUNC_CTL = IOC_PD27_FUNC_CTL_SDC1_DATA_2; + HPM_IOC->PAD[IOC_PAD_PD27].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA3 */ + HPM_IOC->PAD[IOC_PAD_PD26].FUNC_CTL = IOC_PD26_FUNC_CTL_SDC1_DATA_3; + HPM_IOC->PAD[IOC_PAD_PD26].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_clk_data_pins_width4_disable_1v8(void) +{ + /* SDXC1.DATA1 */ + HPM_IOC->PAD[IOC_PAD_PD17].FUNC_CTL = IOC_PD17_FUNC_CTL_SDC1_DATA_1; + HPM_IOC->PAD[IOC_PAD_PD17].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA2 */ + HPM_IOC->PAD[IOC_PAD_PD27].FUNC_CTL = IOC_PD27_FUNC_CTL_SDC1_DATA_2; + HPM_IOC->PAD[IOC_PAD_PD27].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA3 */ + HPM_IOC->PAD[IOC_PAD_PD26].FUNC_CTL = IOC_PD26_FUNC_CTL_SDC1_DATA_3; + HPM_IOC->PAD[IOC_PAD_PD26].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.CLK */ + HPM_IOC->PAD[IOC_PAD_PD22].FUNC_CTL = IOC_PD22_FUNC_CTL_SDC1_CLK; + HPM_IOC->PAD[IOC_PAD_PD22].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); + + /* SDXC1.DATA0 */ + HPM_IOC->PAD[IOC_PAD_PD18].FUNC_CTL = IOC_PD18_FUNC_CTL_SDC1_DATA_0; + HPM_IOC->PAD[IOC_PAD_PD18].PAD_CTL = IOC_PAD_PAD_CTL_MS_SET(0) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_DS_SET(6) | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_sdxc1_pwr_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PC20].FUNC_CTL = IOC_PC20_FUNC_CTL_GPIO_C_20; + HPM_IOC->PAD[IOC_PAD_PC20].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_clk_obs_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PB02].FUNC_CTL = IOC_PB02_FUNC_CTL_SYSCTL_CLK_OBS_0; +} + +void init_rgb_pwm_pins(void) +{ + /* Red */ + HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PB11_FUNC_CTL_TRGM1_P_01; + + /* Green */ + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_TRGM0_P_06; + + /* BLUE */ + HPM_IOC->PAD[IOC_PAD_PB13].FUNC_CTL = IOC_PB13_FUNC_CTL_TRGM1_P_03; +} + +void init_led_pins_as_gpio(void) +{ + HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PB11_FUNC_CTL_GPIO_B_11; + + HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PB12_FUNC_CTL_GPIO_B_12; + + HPM_IOC->PAD[IOC_PAD_PB13].FUNC_CTL = IOC_PB13_FUNC_CTL_GPIO_B_13; +} + +void init_enet_pps_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PF05].FUNC_CTL = IOC_PF05_FUNC_CTL_ETH0_EVTO_0; +} + +void init_enet_pps_capture_pins(void) +{ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_ETH0_EVTI_1; +} + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_TAMP_08 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_TAMP_09; + + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_TAMP_10; +} + +/* for uart_rx_line_status case, need to a gpio pin to sent break signal */ +void init_uart_break_signal_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PE31].FUNC_CTL = IOC_PE31_FUNC_CTL_GPIO_E_31; + HPM_IOC->PAD[IOC_PAD_PE31].PAD_CTL = IOC_PAD_PAD_CTL_DS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | 0x08 | IOC_PAD_PAD_CTL_PS_SET(1); +} + +void init_gptmr3_channel_pin_as_output(void) +{ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PE24_FUNC_CTL_GPTMR3_COMP_1; +} + +void init_gptmr4_channel_pin_as_capture(void) +{ + HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_GPTMR4_CAPT_1; +} + +void init_gptmr5_channel2_pin_as_output(void) +{ + HPM_IOC->PAD[IOC_PAD_PD24].FUNC_CTL = IOC_PD24_FUNC_CTL_TRGM2_P_10; + + trgm_output_t trgm2_io_config0 = {0}; + trgm2_io_config0.invert = 0; + trgm2_io_config0.type = trgm_output_same_as_input; + trgm2_io_config0.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT2; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P10, &trgm2_io_config0); + + trgm_enable_io_output(HPM_TRGM2, 1 << 10); +} + +void init_gptmr5_channel3_pin_as_output(void) +{ + HPM_IOC->PAD[IOC_PAD_PD23].FUNC_CTL = IOC_PD23_FUNC_CTL_TRGM2_P_11; + + trgm_output_t trgm2_io_config0 = {0}; + trgm2_io_config0.invert = 0; + trgm2_io_config0.type = trgm_output_same_as_input; + trgm2_io_config0.input = HPM_TRGM2_INPUT_SRC_GPTMR5_OUT3; + trgm_output_config(HPM_TRGM2, HPM_TRGM2_OUTPUT_SRC_TRGM2_P11, &trgm2_io_config0); + + trgm_enable_io_output(HPM_TRGM2, 1 << 11); +} + +void init_clk_ref_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PE24_FUNC_CTL_SOC_REF1; +} + +void init_brownout_indicate_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PE30].FUNC_CTL = IOC_PE30_FUNC_CTL_GPIO_E_30; +} + +void board_init_i2c_eeprom_pin(void) +{ + HPM_IOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_I2C0_SCL | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = BIOC_PZ11_FUNC_CTL_SOC_PZ_11; + HPM_IOC->PAD[IOC_PAD_PZ11].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); + + HPM_IOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_I2C0_SDA | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_SOC_PZ_10; + HPM_IOC->PAD[IOC_PAD_PZ10].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1); +} diff --git a/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h new file mode 100644 index 000000000..460feded2 --- /dev/null +++ b/hw/bsp/hpmicro/boards/hpm6750evk2/pinmux.h @@ -0,0 +1,89 @@ + +/* + * Copyright (c) 2025 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + * Automatically generated by HPM Pinmux Tool + * + * + * Note: + * PY and PZ IOs: if any SOC pin function needs to be routed to these IOs, + * besides of IOC, PIOC/BIOC needs to be configured SOC_GPIO_X_xx, so that + * expected SoC function can be enabled on these IOs. + */ + +#ifndef HPM_PINMUX_H +#define HPM_PINMUX_H + +#ifdef __cplusplus +extern "C" { +#endif + +void init_uart0_pins(void); +void init_uart2_pins(void); +void init_uart13_pins(void); +void init_puart_pins(void); +void init_uart13_pins_as_gpio(void); +void init_lcd0_pins(void); +void init_cap_pins(void); +void init_i2c0_pins_as_gpio(void); +void init_i2c0_pins(void); +void init_femc_pins(void); +void init_gpio_pins_with_pull_up(void); +void init_gpio_pins_using_gpio0(void); +void init_spi2_pins(void); +void init_spi2_pins_with_gpio_as_cs(void); +void init_gptmr3_pins(void); +void init_gptmr4_pins(void); +void init_gptmr5_pins(void); +void init_hall_trgm_pins(void); +void init_qei_trgm_pins(void); +void init_i2s0_pins(void); +void init_dao_pins(void); +void init_pdm_pins(void); +void init_vad_pins(void); +void init_cam_pins(void); +void init_butn_pins(void); +void init_acmp_pins(void); +void init_enet0_pins(void); +void init_enet1_pins(void); +void init_pwm2_pins(void); +void init_pwm3_pins(void); +void init_adc12_pins(void); +void init_adc16_pins(void); +void init_adc_bldc_pins(void); +void init_usb0_pins(void); +void init_usb1_pins(void); +void init_can0_pins(void); +void init_mcan0_transceiver_phy_pin(void); +void init_sdxc1_cmd_pin_enable_1v8_enable_opendrain(void); +void init_sdxc1_cmd_pin_enable_1v8_disable_opendrain(void); +void init_sdxc1_cmd_pin_disable_1v8_enable_opendrain(void); +void init_sdxc1_cmd_pin_disable_1v8_disable_opendrain(void); +void init_sdxc1_cd_pin(void); +void init_sdxc1_clk_data_pins_enable_1v8(void); +void init_sdxc1_clk_data_pins_disable_1v8(void); +void init_sdxc1_clk_data_pins_width4_enable_1v8(void); +void init_sdxc1_clk_data_pins_width4_disable_1v8(void); +void init_sdxc1_pwr_pin(void); +void init_clk_obs_pins(void); +void init_rgb_pwm_pins(void); +void init_led_pins_as_gpio(void); +void init_enet_pps_pins(void); +void init_enet_pps_capture_pins(void); +void init_tamper_pins(void); +void init_uart_break_signal_pin(void); +void init_gptmr3_channel_pin_as_output(void); +void init_gptmr4_channel_pin_as_capture(void); +void init_gptmr5_channel2_pin_as_output(void); +void init_gptmr5_channel3_pin_as_output(void); +void init_clk_ref_pin(void); +void init_brownout_indicate_pin(void); +void board_init_i2c_eeprom_pin(void); + +#ifdef __cplusplus +} +#endif +#endif /* HPM_PINMUX_H */ diff --git a/hw/bsp/hpmicro/family.c b/hw/bsp/hpmicro/family.c new file mode 100644 index 000000000..ffec2523a --- /dev/null +++ b/hw/bsp/hpmicro/family.c @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (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. + */ + +/* metadata: + manufacturer: HPMicro +*/ + +#include "bsp/board_api.h" +#include "board.h" +#include "hpm_clock_drv.h" +#include "hpm_uart_drv.h" +#include "hpm_gpio_drv.h" +#include "hpm_romapi.h" + + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) { + board_init_clock(); + board_init_pmp(); + + board_init_usb(HPM_USB0); +#ifdef HPM_USB1 + board_init_usb(HPM_USB1); +#endif + + board_init_console(); + board_init_gpio_pins(); + board_init_led_pins(); +} + +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usb0) +void isr_usb0(void) { + tusb_int_handler(0, true); +} + +#ifdef HPM_USB1_BASE +SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usb1) +void isr_usb1(void) { + tusb_int_handler(1, true); +} +#endif + +void board_led_write(bool state) { + if (state) { + gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN, BOARD_LED_ON_LEVEL); + } else { + gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN, BOARD_LED_OFF_LEVEL); + } +} + +uint32_t board_button_read(void) { + return (gpio_read_pin(BOARD_APP_GPIO_CTRL, BOARD_APP_GPIO_INDEX, BOARD_APP_GPIO_PIN) == BOARD_BUTTON_PRESSED_VALUE) ? 1 : 0; +} + +// Get characters from UART. Return number of read bytes +int board_uart_read(uint8_t *buf, int len) { + int count = 0; + hpm_stat_t status; + + while (count < len) { + status = uart_try_receive_byte((UART_Type *)BOARD_CONSOLE_UART_BASE, (uint8_t *)&buf[count]); + if (status == status_success) { + count++; + } else { + break; + } + } + + return count; +} + +// Send characters to UART. Return number of sent bytes +int board_uart_write(void const *buf, int len) { + uart_send_data((UART_Type *)BOARD_CONSOLE_UART_BASE, (uint8_t const *)buf, len); + + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +// Get current milliseconds, must be implemented when no RTOS is used +uint32_t board_millis(void) { + return (hpm_csr_get_core_cycle() / clock_get_core_clock_ticks_per_ms()); +} + +#endif diff --git a/hw/bsp/hpmicro/family.cmake b/hw/bsp/hpmicro/family.cmake new file mode 100644 index 000000000..4500f326f --- /dev/null +++ b/hw/bsp/hpmicro/family.cmake @@ -0,0 +1,131 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/hpmicro/hpm_sdk) + +set(CROSS_COMPILE "riscv32-unknown-elf-") + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +if (NOT DEFINED CMAKE_SYSTEM_CPU) + set(CMAKE_SYSTEM_CPU rv32imac-ilp32 CACHE INTERNAL "System Processor") +endif () +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS HPMIRCO CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${HPM_SOC}/toolchains/gcc/flash_xip.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) + +set(STARTUP_FILE_GNU ${HPM_SOC}/toolchains/gcc/start.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/pinmux.c + ${HPM_SOC}/boot/hpm_bootheader.c + ${HPM_SOC}/toolchains/gcc/initfini.c + ${HPM_SOC}/toolchains/reset.c + ${HPM_SOC}/toolchains/trap.c + ${HPM_SOC}/system.c + ${HPM_SOC}/hpm_sysctl_drv.c + ${HPM_SOC}/hpm_clock_drv.c + ${HPM_SOC}/hpm_otp_drv.c + ${SDK_DIR}/arch/riscv/l1c/hpm_l1c_drv.c + ${SDK_DIR}/drivers/src/hpm_gpio_drv.c + ${SDK_DIR}/drivers/src/hpm_uart_drv.c + ${SDK_DIR}/drivers/src/hpm_usb_drv.c + ${SDK_DIR}/drivers/src/hpm_pcfg_drv.c + ${SDK_DIR}/drivers/src/hpm_pmp_drv.c + ${SDK_DIR}/drivers/src/${HPM_PLLCTL_DRV_FILE} + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + FLASH_XIP + [=[CFG_TUD_MEM_SECTION=__attribute__((section(".noncacheable.non_init")))]=] + [=[CFG_TUH_MEM_SECTION=__attribute__((section(".noncacheable.non_init")))]=] + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board + ${HPM_SOC} + ${HPM_IP_REGS} + ${HPM_SOC}/boot + ${HPM_SOC}/toolchains + ${HPM_SOC}/toolchains/gcc + ${SDK_DIR}/arch + ${SDK_DIR}/arch/riscv/intc + ${SDK_DIR}/arch/riscv/l1c + ${SDK_DIR}/drivers/inc + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_HPM) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${SDK_DIR}/utils/hpm_sbrk.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 + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ${TOP}/src/portable/chipidea/ci_hs + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + -Wl,--defsym,_flash_size=${BOARD_FLASH_SIZE} + -Wl,--defsym,_stack_size=${BOARD_STACK_SIZE} + -Wl,--defsym,_heap_size=${BOARD_HEAP_SIZE} + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -Wl,--defsym,_flash_size=${BOARD_FLASH_SIZE} + -Wl,--defsym,_stack_size=${BOARD_STACK_SIZE} + -Wl,--defsym,_heap_size=${BOARD_HEAP_SIZE} + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${SDK_DIR}/utils/hpm_sbrk.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-cast-align -Wno-discarded-qualifiers" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/hpmicro/family.mk b/hw/bsp/hpmicro/family.mk new file mode 100644 index 000000000..9721e2f7d --- /dev/null +++ b/hw/bsp/hpmicro/family.mk @@ -0,0 +1,76 @@ +SDK_DIR = hw/mcu/hpmicro/hpm_sdk + +CROSS_COMPILE ?= riscv32-unknown-elf- + +include $(TOP)/$(BOARD_PATH)/board.mk + +CPU_CORE ?= rv32imac-ilp32 + +# All source paths should be relative to the top level. +LD_FILE = $(HPM_SOC)/toolchains/gcc/flash_xip.ld + +CFLAGS += \ + -DFLASH_XIP \ + -DCFG_TUSB_MCU=OPT_MCU_HPM \ + -DCFG_TUD_MEM_SECTION='__attribute__((section(".noncacheable.non_init")))' \ + -DCFG_TUH_MEM_SECTION='__attribute__((section(".noncacheable.non_init")))' + +ifdef BOARD_TUD_RHPORT +CFLAGS += -DBOARD_TUD_RHPORT=$(BOARD_TUD_RHPORT) +CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED +endif + +ifdef BOARD_TUH_RHPORT +CFLAGS += -DBOARD_TUH_RHPORT=$(BOARD_TUH_RHPORT) +CFLAGS += -DBOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED +endif + +# mcu driver cause following warnings +CFLAGS += -Wno-error=cast-align -Wno-error=double-promotion -Wno-error=discarded-qualifiers \ + -Wno-error=undef -Wno-error=unused-parameter -Wno-error=redundant-decls + +LDFLAGS_GCC += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs + +LDFLAGS += -Wl,--defsym,_flash_size=$(BOARD_FLASH_SIZE) +LDFLAGS += -Wl,--defsym,_stack_size=$(BOARD_STACK_SIZE) +LDFLAGS += -Wl,--defsym,_heap_size=$(BOARD_HEAP_SIZE) + +SRC_C += \ + src/portable/chipidea/ci_hs/dcd_ci_hs.c \ + src/portable/chipidea/ci_hs/hcd_ci_hs.c \ + src/portable/ehci/ehci.c \ + ${BOARD_PATH}/board.c \ + ${BOARD_PATH}/pinmux.c \ + $(HPM_SOC)/boot/hpm_bootheader.c \ + $(HPM_SOC)/toolchains/gcc/initfini.c \ + $(HPM_SOC)/toolchains/reset.c \ + $(HPM_SOC)/toolchains/trap.c \ + $(HPM_SOC)/system.c \ + $(HPM_SOC)/hpm_sysctl_drv.c \ + $(HPM_SOC)/hpm_clock_drv.c \ + $(HPM_SOC)/hpm_otp_drv.c \ + $(SDK_DIR)/arch/riscv/l1c/hpm_l1c_drv.c \ + $(SDK_DIR)/utils/hpm_sbrk.c \ + $(SDK_DIR)/drivers/src/hpm_gpio_drv.c \ + $(SDK_DIR)/drivers/src/hpm_uart_drv.c \ + $(SDK_DIR)/drivers/src/hpm_usb_drv.c \ + $(SDK_DIR)/drivers/src/hpm_pcfg_drv.c \ + $(SDK_DIR)/drivers/src/hpm_pmp_drv.c \ + $(SDK_DIR)/drivers/src/$(HPM_PLLCTL_DRV_FILE) \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/src/portable/chipidea/ci_hs \ + $(TOP)/$(HPM_SOC) \ + $(TOP)/$(HPM_IP_REGS) \ + $(TOP)/$(HPM_SOC)/boot \ + $(TOP)/$(HPM_SOC)/toolchains \ + $(TOP)/$(HPM_SOC)/toolchains/gcc \ + $(TOP)/$(SDK_DIR)/arch \ + $(TOP)/$(SDK_DIR)/arch/riscv/intc \ + $(TOP)/$(SDK_DIR)/arch/riscv/l1c \ + $(TOP)/$(SDK_DIR)/drivers/inc \ + +SRC_S += $(HPM_SOC)/toolchains/gcc/start.S diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1e773bf96..95fbc061f 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -653,6 +653,18 @@ #define TUP_USBIP_DWC2_AT32 #define TUP_DCD_ENDPOINT_MAX 8 +//--------------------------------------------------------------------+ +// HPMicro +//--------------------------------------------------------------------+ +#elif TU_CHECK_MCU(OPT_MCU_HPM) + #define TUP_USBIP_CHIPIDEA_HS + #define TUP_USBIP_EHCI + + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_RHPORT_HIGHSPEED 1 + + #define TU_ATTR_FAST_FUNC __attribute__((section(".fast"))) + #endif //--------------------------------------------------------------------+ diff --git a/src/portable/chipidea/ci_hs/ci_hs_hpm.h b/src/portable/chipidea/ci_hs/ci_hs_hpm.h new file mode 100644 index 000000000..68211448c --- /dev/null +++ b/src/portable/chipidea/ci_hs/ci_hs_hpm.h @@ -0,0 +1,54 @@ +/* + * 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_HPM_H_ +#define _CI_HS_HPM_H_ + +#include "ci_hs_type.h" +#include "hpm_soc.h" +#include "hpm_interrupt.h" +#include "hpm_usb_drv.h" + +static const ci_hs_controller_t _ci_controller[] = +{ + { .reg_base = HPM_USB0_BASE, .irqnum = IRQn_USB0}, + #ifdef HPM_USB1_BASE + { .reg_base = HPM_USB1_BASE, .irqnum = IRQn_USB1}, + #endif +}; + +#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base) + +//------------- DCD -------------// +#define CI_DCD_INT_ENABLE(_p) intc_m_enable_irq (_ci_controller[_p].irqnum) +#define CI_DCD_INT_DISABLE(_p) intc_m_disable_irq(_ci_controller[_p].irqnum) + +//------------- HCD -------------// +#define CI_HCD_INT_ENABLE(_p) intc_m_enable_irq (_ci_controller[_p].irqnum) +#define CI_HCD_INT_DISABLE(_p) intc_m_disable_irq(_ci_controller[_p].irqnum) + + +#endif diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 4a5e5c91f..00df434d8 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -55,6 +55,10 @@ bool dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { // MCX N9 only port 1 use this controller #include "ci_hs_mcx.h" +#elif TU_CHECK_MCU(OPT_MCU_HPM) + + #include "ci_hs_hpm.h" + #else #error "Unsupported MCUs" #endif @@ -230,6 +234,10 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_ASSERT(ci_ep_count(dcd_reg) <= TUP_DCD_ENDPOINT_MAX); +#if TU_CHECK_MCU(OPT_MCU_HPM) + usb_phy_init((USB_Type *)dcd_reg, false); +#endif + // Reset controller dcd_reg->USBCMD |= USBCMD_RESET; while( dcd_reg->USBCMD & USBCMD_RESET ) {} @@ -246,7 +254,11 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #endif #if !TUD_OPT_HIGH_SPEED - dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; + dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; +#endif + +#if TU_CHECK_MCU(OPT_MCU_HPM) + dcd_reg->PORTSC1 &= ~USB_PORTSC1_STS_MASK; #endif dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index b5324a754..922d32989 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -61,6 +61,10 @@ bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { #include "ci_hs_lpc18_43.h" +#elif TU_CHECK_MCU(OPT_MCU_HPM) + +#include "ci_hs_hpm.h" + #else #error "Unsupported MCUs" #endif @@ -77,6 +81,10 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; ci_hs_regs_t *hcd_reg = CI_HS_REG(rhport); +#if CFG_TUSB_MCU == OPT_MCU_HPM + usb_phy_init((USB_Type *)hcd_reg, true); +#endif + // Reset controller hcd_reg->USBCMD |= USBCMD_RESET; while ( hcd_reg->USBCMD & USBCMD_RESET ) {} diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index c33c970e4..0d6f5ef12 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -44,6 +44,10 @@ #include "fsl_device_registers.h" #endif +#if TU_CHECK_MCU(OPT_MCU_HPM) +#include "ci_hs_hpm.h" +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -237,6 +241,14 @@ void hcd_port_reset(uint8_t rhport) { // mask out Write-1-to-Clear bits uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; +#if TU_CHECK_MCU(OPT_MCU_HPM) + if (usb_phy_get_line_state((USB_Type *)CI_HS_REG(rhport)) == usb_line_state2) { + portsc |= USB_PORTSC1_STS_MASK; + } else { + portsc &= ~USB_PORTSC1_STS_MASK; + } +#endif + // 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); diff --git a/src/tusb_option.h b/src/tusb_option.h index 1dc920d84..cd131c119 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -216,6 +216,9 @@ #define OPT_MCU_AT32F425 2505 ///< ArteryTek AT32F425 #define OPT_MCU_AT32F413 2506 ///< ArteryTek AT32F413 +// HPMicro +#define OPT_MCU_HPM 2600 ///< HPMicro + // Check if configured MCU is one of listed // Apply TU_MCU_IS_EQUAL with || as separator to list of input #define TU_MCU_IS_EQUAL(_m) (CFG_TUSB_MCU == (_m)) diff --git a/tools/get_deps.py b/tools/get_deps.py index b1b50d319..42ead17ff 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -244,6 +244,9 @@ deps_optional = { 'hw/mcu/artery/at32f413': ['https://github.com/ArteryTek/AT32F413_Firmware_Library.git', 'f6fe62dfec9fd40c5b63d92fc5ef2c2b5e77a450', 'at32f413'], + 'hw/mcu/hpmicro/hpm_sdk': ['https://github.com/hpmicro/hpm_sdk', + '8d2af741ecc4aaa82d7ee395dc1ce25d7070c3ff', + 'hpm_sdk hpmicro hpm6750 hpm6300 hpm6200 hpm6800 hpm5300 hpm6e00 hpm5e00'], 'lib/CMSIS_5': ['https://github.com/ARM-software/CMSIS_5.git', '2b7495b8535bdcb306dac29b9ded4cfb679d7e5c', 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x ' -- cgit v1.3.1 From c130fc07c628a0b2d79f35b743857aa53d79130b Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Tue, 16 Dec 2025 12:29:04 +0100 Subject: fix pre-commit Signed-off-by: Zixun LI --- hw/bsp/rw61x/boards/frdm_rw612/board.cmake | 2 +- hw/bsp/rw61x/boards/frdm_rw612/board.h | 6 ++---- hw/bsp/rw61x/boards/frdm_rw612/clock_config.c | 1 - hw/bsp/rw61x/boards/frdm_rw612/clock_config.h | 1 - hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c | 2 +- hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h | 2 +- hw/bsp/rw61x/family.c | 6 +++--- hw/bsp/rw61x/family.cmake | 4 ++-- hw/bsp/rw61x/family.mk | 4 ++-- src/tusb_option.h | 2 +- 10 files changed, 13 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/hw/bsp/rw61x/boards/frdm_rw612/board.cmake b/hw/bsp/rw61x/boards/frdm_rw612/board.cmake index 09feb0cab..7d77956fa 100644 --- a/hw/bsp/rw61x/boards/frdm_rw612/board.cmake +++ b/hw/bsp/rw61x/boards/frdm_rw612/board.cmake @@ -27,4 +27,4 @@ function(update_board BOARD_TARGET) target_include_directories(${BOARD_TARGET} PUBLIC ${BOARD_DIR}/flash_config ) -endfunction() \ No newline at end of file +endfunction() diff --git a/hw/bsp/rw61x/boards/frdm_rw612/board.h b/hw/bsp/rw61x/boards/frdm_rw612/board.h index ebb357c29..fd9eec8b6 100644 --- a/hw/bsp/rw61x/boards/frdm_rw612/board.h +++ b/hw/bsp/rw61x/boards/frdm_rw612/board.h @@ -41,8 +41,8 @@ // LED - Green channel of RGB LED #define LED_GPIO BOARD_INITLEDPINS_LED_GREEN_PERIPHERAL #define LED_CLK kCLOCK_HsGpio0 -#define LED_PIN BOARD_INITLEDPINS_LED_GREEN_PIN -#define LED_PORT BOARD_INITLEDPINS_LED_GREEN_PORT +#define LED_PIN BOARD_INITLEDPINS_LED_GREEN_PIN +#define LED_PORT BOARD_INITLEDPINS_LED_GREEN_PORT #define LED_STATE_ON 0 // WAKE button (Dummy, use unused pin @@ -72,5 +72,3 @@ static inline void board_uart_init_clock(void) { #endif #endif - - diff --git a/hw/bsp/rw61x/boards/frdm_rw612/clock_config.c b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.c index 513e40f66..9ad78fe43 100644 --- a/hw/bsp/rw61x/boards/frdm_rw612/clock_config.c +++ b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.c @@ -167,4 +167,3 @@ void BOARD_BootClockRUN(void) /*!< Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_HCLK; } - diff --git a/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h index 3b467d869..57e3bbb4d 100644 --- a/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h +++ b/hw/bsp/rw61x/boards/frdm_rw612/clock_config.h @@ -113,4 +113,3 @@ void BOARD_BootClockRUN(void); #endif /* _CLOCK_CONFIG_H_ */ - diff --git a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c index 49b74b2bb..eba6b4123 100644 --- a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c +++ b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.c @@ -53,7 +53,7 @@ BOARD_InitPins: /* FUNCTION ************************************************************************************************************ * * Function Name : BOARD_InitPins - * Description : + * Description : * * END ****************************************************************************************************************/ /* Function assigned for the Cortex-M33 */ diff --git a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h index f4c9a9127..c43b304d5 100644 --- a/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h +++ b/hw/bsp/rw61x/boards/frdm_rw612/pin_mux.h @@ -54,7 +54,7 @@ void BOARD_InitBootPins(void); /* @} */ /*! - * @brief + * @brief * */ void BOARD_InitPins(void); /* Function assigned for the Cortex-M33 */ diff --git a/hw/bsp/rw61x/family.c b/hw/bsp/rw61x/family.c index 226956f15..265d5fcc0 100644 --- a/hw/bsp/rw61x/family.c +++ b/hw/bsp/rw61x/family.c @@ -51,7 +51,7 @@ void board_init(void) { // Init button pin, LED pins, SWD pins & UART pins BOARD_InitBootPins(); - + // Init Clocks BOARD_InitBootClocks(); @@ -86,8 +86,8 @@ void board_init(void) { // Enable USB Clock CLOCK_EnableClock(kCLOCK_Usb); - - // Enable USB PHY + + // Enable USB PHY CLOCK_EnableUsbhsPhyClock(); } diff --git a/hw/bsp/rw61x/family.cmake b/hw/bsp/rw61x/family.cmake index 5428b7e50..62233a404 100644 --- a/hw/bsp/rw61x/family.cmake +++ b/hw/bsp/rw61x/family.cmake @@ -81,7 +81,7 @@ function(family_configure_example TARGET RTOS) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs + --specs=nosys.specs --specs=nano.specs ) endif() @@ -99,4 +99,4 @@ function(family_configure_example TARGET RTOS) # Flashing & Binary Generation family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) -endfunction() \ No newline at end of file +endfunction() diff --git a/hw/bsp/rw61x/family.mk b/hw/bsp/rw61x/family.mk index e715adfa8..08eafddbc 100644 --- a/hw/bsp/rw61x/family.mk +++ b/hw/bsp/rw61x/family.mk @@ -13,7 +13,7 @@ CFLAGS += \ -DSERIAL_PORT_TYPE_UART=1 \ -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED \ -DBOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED \ - + # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration -Wno-error=redundant-decls @@ -35,7 +35,7 @@ SRC_C += \ $(SDK_DIR)/drivers/flexcomm/fsl_flexcomm.c \ $(SDK_DIR)/drivers/flexcomm/usart/fsl_usart.c \ $(SDK_DIR)/drivers/flexspi/fsl_flexspi.c \ - + INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ diff --git a/src/tusb_option.h b/src/tusb_option.h index 413bf2a82..caf8c4156 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -199,7 +199,7 @@ // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series #define OPT_MCU_MCXA15 2301 ///< NXP MCX A15 Series -#define OPT_MCU_RW61X 2302 ///< NXP RW61x Series +#define OPT_MCU_RW61X 2302 ///< NXP RW61x Series // Analog Devices #define OPT_MCU_MAX32690 2400 ///< ADI MAX32690 -- cgit v1.3.1 From 7f4a76151357509f74e4afa67c02d6dd91537a88 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Dec 2025 11:08:49 +0700 Subject: remove the usage snprintf --- src/common/tusb_debug.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index e0e09f5ce..470a8a18b 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -117,12 +117,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 } } - // not found return the key value in hex - static char not_found[11]; - if (snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key) <= 0) { - not_found[0] = 0; - } - return not_found; + return "NotFound"; } #endif // CFG_TUSB_DEBUG -- cgit v1.3.1 From 49a8529dcf8f5b2616640e6f96dcb27e930d1f0d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Dec 2025 12:24:06 +0700 Subject: clean up cmake, remove family_get_project_name() --- examples/CMakeLists.txt | 7 ++++++- examples/device/audio_4_channel_mic/CMakeLists.txt | 17 +++++++---------- .../audio_4_channel_mic_freertos/CMakeLists.txt | 17 +++++++---------- examples/device/audio_test/CMakeLists.txt | 15 ++++++--------- examples/device/audio_test_freertos/CMakeLists.txt | 15 ++++++--------- .../device/audio_test_multi_rate/CMakeLists.txt | 15 ++++++--------- examples/device/board_test/CMakeLists.txt | 9 +++------ examples/device/cdc_dual_ports/CMakeLists.txt | 15 ++++++--------- examples/device/cdc_msc/CMakeLists.txt | 10 +++------- examples/device/cdc_msc_freertos/CMakeLists.txt | 15 ++++++--------- examples/device/cdc_uac2/CMakeLists.txt | 17 +++++++---------- examples/device/dfu/CMakeLists.txt | 15 ++++++--------- examples/device/dfu_runtime/CMakeLists.txt | 15 ++++++--------- .../device/dynamic_configuration/CMakeLists.txt | 15 ++++++--------- examples/device/hid_boot_interface/CMakeLists.txt | 15 ++++++--------- examples/device/hid_composite/CMakeLists.txt | 15 ++++++--------- .../device/hid_composite_freertos/CMakeLists.txt | 15 ++++++--------- examples/device/hid_generic_inout/CMakeLists.txt | 15 ++++++--------- .../device/hid_multiple_interface/CMakeLists.txt | 15 ++++++--------- examples/device/midi_test/CMakeLists.txt | 15 ++++++--------- examples/device/midi_test_freertos/CMakeLists.txt | 15 ++++++--------- examples/device/msc_dual_lun/CMakeLists.txt | 9 +++------ examples/device/mtp/CMakeLists.txt | 9 +++------ examples/device/net_lwip_webserver/CMakeLists.txt | 22 ++++++++++------------ examples/device/uac2_headset/CMakeLists.txt | 15 ++++++--------- examples/device/uac2_speaker_fb/CMakeLists.txt | 15 ++++++--------- examples/device/usbtmc/CMakeLists.txt | 15 ++++++--------- examples/device/video_capture/CMakeLists.txt | 17 +++++++---------- examples/device/video_capture_2ch/CMakeLists.txt | 17 +++++++---------- examples/device/webusb_serial/CMakeLists.txt | 15 ++++++--------- .../dual/host_hid_to_device_cdc/CMakeLists.txt | 17 +++++++---------- .../dual/host_info_to_device_cdc/CMakeLists.txt | 17 +++++++---------- examples/host/bare_api/CMakeLists.txt | 15 ++++++--------- examples/host/cdc_msc_hid/CMakeLists.txt | 15 ++++++--------- examples/host/cdc_msc_hid_freertos/CMakeLists.txt | 15 ++++++--------- examples/host/device_info/CMakeLists.txt | 15 ++++++--------- examples/host/hid_controller/CMakeLists.txt | 15 ++++++--------- examples/host/midi_rx/CMakeLists.txt | 15 ++++++--------- examples/host/msc_file_explorer/CMakeLists.txt | 15 ++++++--------- examples/typec/power_delivery/CMakeLists.txt | 15 ++++++--------- hw/bsp/family_support.cmake | 5 ----- hw/bsp/rp2040/family.cmake | 2 +- src/common/tusb_debug.h | 9 +++++++++ test/fuzz/device/cdc/CMakeLists.txt | 15 ++++++--------- test/fuzz/device/msc/CMakeLists.txt | 15 ++++++--------- test/fuzz/device/net/CMakeLists.txt | 15 ++++++--------- 46 files changed, 267 insertions(+), 384 deletions(-) (limited to 'src') diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b34131c2b..b458c9ce3 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.20) -#set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(${CMAKE_CURRENT_SOURCE_DIR}/../hw/bsp/family_support.cmake) project(tinyusb_examples C CXX ASM) @@ -27,3 +26,9 @@ add_custom_target(tinyusb_metrics COMMENT "Generating average code size metrics" VERBATIM ) + +#add_custom_command(TARGET tinyusb_metrics POST_BUILD +# COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../tools/metrics.py compare ${TOP}/cmake-build/cmake-build-${BOARD}/metrics.json ${CMAKE_BINARY_DIR}/metrics.json +# COMMENT "Generating average code size metrics" +# VERBATIM +# ) diff --git a/examples/device/audio_4_channel_mic/CMakeLists.txt b/examples/device/audio_4_channel_mic/CMakeLists.txt index c8086ae46..5d7ffa4fc 100644 --- a/examples/device/audio_4_channel_mic/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic/CMakeLists.txt @@ -2,37 +2,34 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(audio_4_channel_mic C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Add libm for GCC if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_libraries(${PROJECT} PUBLIC m) + target_link_libraries(${PROJECT_NAME} PUBLIC m) endif() # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt index c50d4fef7..d43a72e58 100644 --- a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt @@ -2,37 +2,34 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(audio_4_channel_mic_freertos C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Add libm for GCC if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_libraries(${PROJECT} PUBLIC m) + target_link_libraries(${PROJECT_NAME} PUBLIC m) endif() # Configure compilation flags and libraries for the example with FreeRTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} freertos) +family_configure_device_example(${PROJECT_NAME} freertos) diff --git a/examples/device/audio_test/CMakeLists.txt b/examples/device/audio_test/CMakeLists.txt index 6a7e68c3d..3382530c6 100644 --- a/examples/device/audio_test/CMakeLists.txt +++ b/examples/device/audio_test/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(audio_test C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/audio_test_freertos/CMakeLists.txt b/examples/device/audio_test_freertos/CMakeLists.txt index 6ce9e72fe..71d65eccc 100644 --- a/examples/device/audio_test_freertos/CMakeLists.txt +++ b/examples/device/audio_test_freertos/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(audio_test_freertos C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example with FreeRTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} freertos) +family_configure_device_example(${PROJECT_NAME} freertos) diff --git a/examples/device/audio_test_multi_rate/CMakeLists.txt b/examples/device/audio_test_multi_rate/CMakeLists.txt index 6a7e68c3d..c17831cda 100644 --- a/examples/device/audio_test_multi_rate/CMakeLists.txt +++ b/examples/device/audio_test_multi_rate/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(audio_test_multi_rate C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/board_test/CMakeLists.txt b/examples/device/board_test/CMakeLists.txt index 9a604a732..bd7b8e0ca 100644 --- a/examples/device/board_test/CMakeLists.txt +++ b/examples/device/board_test/CMakeLists.txt @@ -2,13 +2,10 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(board_test C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") @@ -18,7 +15,7 @@ endif() if (RTOS STREQUAL zephyr) set(EXE_NAME app) else() - set(EXE_NAME ${PROJECT}) + set(EXE_NAME ${PROJECT_NAME}) add_executable(${EXE_NAME}) endif() diff --git a/examples/device/cdc_dual_ports/CMakeLists.txt b/examples/device/cdc_dual_ports/CMakeLists.txt index 6a7e68c3d..697906b83 100644 --- a/examples/device/cdc_dual_ports/CMakeLists.txt +++ b/examples/device/cdc_dual_ports/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(cdc_dual_ports C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/cdc_msc/CMakeLists.txt b/examples/device/cdc_msc/CMakeLists.txt index b07f92342..293b497a7 100644 --- a/examples/device/cdc_msc/CMakeLists.txt +++ b/examples/device/cdc_msc/CMakeLists.txt @@ -1,15 +1,11 @@ cmake_minimum_required(VERSION 3.20) -#set_property(GLOBAL PROPERTY USE_FOLDERS ON) 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} C CXX ASM) +project(cdc_msc C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") @@ -19,7 +15,7 @@ endif() if (RTOS STREQUAL zephyr) set(EXE_NAME app) else() - set(EXE_NAME ${PROJECT}) + set(EXE_NAME ${PROJECT_NAME}) add_executable(${EXE_NAME}) endif() diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt index f7636a07a..429000427 100644 --- a/examples/device/cdc_msc_freertos/CMakeLists.txt +++ b/examples/device/cdc_msc_freertos/CMakeLists.txt @@ -2,33 +2,30 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(cdc_msc_freertos C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${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 +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example with FreeRTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} freertos) +family_configure_device_example(${PROJECT_NAME} freertos) diff --git a/examples/device/cdc_uac2/CMakeLists.txt b/examples/device/cdc_uac2/CMakeLists.txt index c8c797637..fb14dc184 100644 --- a/examples/device/cdc_uac2/CMakeLists.txt +++ b/examples/device/cdc_uac2/CMakeLists.txt @@ -2,23 +2,20 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(cdc_uac2 C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/uac2_app.c @@ -26,13 +23,13 @@ target_sources(${PROJECT} PUBLIC ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} 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. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) # Uncomment me to enable UART based debugging -# pico_enable_stdio_uart(${PROJECT} 1) +# pico_enable_stdio_uart(${PROJECT_NAME} 1) diff --git a/examples/device/dfu/CMakeLists.txt b/examples/device/dfu/CMakeLists.txt index 3da8ee3df..61d169460 100644 --- a/examples/device/dfu/CMakeLists.txt +++ b/examples/device/dfu/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(dfu C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/dfu_runtime/CMakeLists.txt b/examples/device/dfu_runtime/CMakeLists.txt index 3da8ee3df..8f6df9f75 100644 --- a/examples/device/dfu_runtime/CMakeLists.txt +++ b/examples/device/dfu_runtime/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(dfu_runtime C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/dynamic_configuration/CMakeLists.txt b/examples/device/dynamic_configuration/CMakeLists.txt index 8a62d6ba2..4a1b67a69 100644 --- a/examples/device/dynamic_configuration/CMakeLists.txt +++ b/examples/device/dynamic_configuration/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(dynamic_configuration C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${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 +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/hid_boot_interface/CMakeLists.txt b/examples/device/hid_boot_interface/CMakeLists.txt index 3da8ee3df..2fee46517 100644 --- a/examples/device/hid_boot_interface/CMakeLists.txt +++ b/examples/device/hid_boot_interface/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(hid_boot_interface C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/hid_composite/CMakeLists.txt b/examples/device/hid_composite/CMakeLists.txt index 3da8ee3df..f1ddbd125 100644 --- a/examples/device/hid_composite/CMakeLists.txt +++ b/examples/device/hid_composite/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(hid_composite C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt index 6ce9e72fe..b52373011 100644 --- a/examples/device/hid_composite_freertos/CMakeLists.txt +++ b/examples/device/hid_composite_freertos/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(hid_composite_freertos C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example with FreeRTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} freertos) +family_configure_device_example(${PROJECT_NAME} freertos) diff --git a/examples/device/hid_generic_inout/CMakeLists.txt b/examples/device/hid_generic_inout/CMakeLists.txt index 3da8ee3df..b363c161b 100644 --- a/examples/device/hid_generic_inout/CMakeLists.txt +++ b/examples/device/hid_generic_inout/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(hid_generic_inout C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/hid_multiple_interface/CMakeLists.txt b/examples/device/hid_multiple_interface/CMakeLists.txt index 3da8ee3df..f4a9895d5 100644 --- a/examples/device/hid_multiple_interface/CMakeLists.txt +++ b/examples/device/hid_multiple_interface/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(hid_multiple_interface C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/midi_test/CMakeLists.txt b/examples/device/midi_test/CMakeLists.txt index 6a7e68c3d..09fbf20f0 100644 --- a/examples/device/midi_test/CMakeLists.txt +++ b/examples/device/midi_test/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(midi_test C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/midi_test_freertos/CMakeLists.txt b/examples/device/midi_test_freertos/CMakeLists.txt index 6ce9e72fe..7e5d3e89e 100644 --- a/examples/device/midi_test_freertos/CMakeLists.txt +++ b/examples/device/midi_test_freertos/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(midi_test_freertos C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example with FreeRTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} freertos) +family_configure_device_example(${PROJECT_NAME} freertos) diff --git a/examples/device/msc_dual_lun/CMakeLists.txt b/examples/device/msc_dual_lun/CMakeLists.txt index 3955bfb49..72a55eebc 100644 --- a/examples/device/msc_dual_lun/CMakeLists.txt +++ b/examples/device/msc_dual_lun/CMakeLists.txt @@ -2,13 +2,10 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(msc_dual_lun C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") @@ -18,7 +15,7 @@ endif() if (RTOS STREQUAL zephyr) set(EXE_NAME app) else() - set(EXE_NAME ${PROJECT}) + set(EXE_NAME ${PROJECT_NAME}) add_executable(${EXE_NAME}) endif() diff --git a/examples/device/mtp/CMakeLists.txt b/examples/device/mtp/CMakeLists.txt index e91eb8fd9..a9f2f1a90 100644 --- a/examples/device/mtp/CMakeLists.txt +++ b/examples/device/mtp/CMakeLists.txt @@ -2,13 +2,10 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(mtp C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") @@ -18,7 +15,7 @@ endif() if (RTOS STREQUAL zephyr) set(EXE_NAME app) else() - set(EXE_NAME ${PROJECT}) + set(EXE_NAME ${PROJECT_NAME}) add_executable(${EXE_NAME}) endif() diff --git a/examples/device/net_lwip_webserver/CMakeLists.txt b/examples/device/net_lwip_webserver/CMakeLists.txt index 87b92f4dc..9c4349d24 100644 --- a/examples/device/net_lwip_webserver/CMakeLists.txt +++ b/examples/device/net_lwip_webserver/CMakeLists.txt @@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.20) include(${CMAKE_CURRENT_LIST_DIR}/../../../hw/bsp/family_support.cmake) -# gets PROJECT name for the example (e.g. -) -family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) # Prefer the tinyusb lwip set(LWIP ${TOP}/lib/lwip) @@ -14,25 +12,25 @@ if (NOT EXISTS ${LWIP}/src) endif() if (NOT EXISTS ${LWIP}/src) - family_example_missing_dependency(${PROJECT} "lib/lwip") + family_example_missing_dependency(${PROJECT_NAME} "lib/lwip") return() endif() -project(${PROJECT} C CXX ASM) +project(net_lwip_webserver C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/main.c ${CMAKE_CURRENT_LIST_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src ${LWIP}/src/include ${LWIP}/src/include/ipv4 @@ -41,14 +39,14 @@ target_include_directories(${PROJECT} PUBLIC ) # lib/networking sources -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${TOP}/lib/networking/dhserver.c ${TOP}/lib/networking/dnserver.c ${TOP}/lib/networking/rndis_reports.c ) # lwip sources -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${LWIP}/src/core/altcp.c ${LWIP}/src/core/altcp_alloc.c ${LWIP}/src/core/altcp_tcp.c @@ -86,7 +84,7 @@ target_sources(${PROJECT} PUBLIC # due to warnings from other net source, we need to prevent error from some of the warnings options if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(${PROJECT} PUBLIC + target_compile_options(${PROJECT_NAME} PUBLIC -Wno-error=null-dereference -Wno-error=conversion -Wno-error=sign-conversion @@ -98,4 +96,4 @@ endif () # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/uac2_headset/CMakeLists.txt b/examples/device/uac2_headset/CMakeLists.txt index ced98a909..52b88aac0 100644 --- a/examples/device/uac2_headset/CMakeLists.txt +++ b/examples/device/uac2_headset/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(uac2_headset C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/uac2_speaker_fb/CMakeLists.txt b/examples/device/uac2_speaker_fb/CMakeLists.txt index ced98a909..cddbf6a31 100644 --- a/examples/device/uac2_speaker_fb/CMakeLists.txt +++ b/examples/device/uac2_speaker_fb/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(uac2_speaker_fb C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/usbtmc/CMakeLists.txt b/examples/device/usbtmc/CMakeLists.txt index d2deb72d5..6181c303b 100644 --- a/examples/device/usbtmc/CMakeLists.txt +++ b/examples/device/usbtmc/CMakeLists.txt @@ -2,33 +2,30 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(usbtmc C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usbtmc_app.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/video_capture/CMakeLists.txt b/examples/device/video_capture/CMakeLists.txt index 90788fa60..1f9b851ff 100644 --- a/examples/device/video_capture/CMakeLists.txt +++ b/examples/device/video_capture/CMakeLists.txt @@ -2,38 +2,35 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(video_capture C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) if (FORCE_READONLY) -target_compile_definitions(${PROJECT} PRIVATE +target_compile_definitions(${PROJECT_NAME} PRIVATE CFG_EXAMPLE_VIDEO_READONLY ) endif() # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/video_capture_2ch/CMakeLists.txt b/examples/device/video_capture_2ch/CMakeLists.txt index 90788fa60..cb1785d1f 100644 --- a/examples/device/video_capture_2ch/CMakeLists.txt +++ b/examples/device/video_capture_2ch/CMakeLists.txt @@ -2,38 +2,35 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(video_capture_2ch C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) if (FORCE_READONLY) -target_compile_definitions(${PROJECT} PRIVATE +target_compile_definitions(${PROJECT_NAME} PRIVATE CFG_EXAMPLE_VIDEO_READONLY ) endif() # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/device/webusb_serial/CMakeLists.txt b/examples/device/webusb_serial/CMakeLists.txt index ced98a909..3b214e7c9 100644 --- a/examples/device/webusb_serial/CMakeLists.txt +++ b/examples/device/webusb_serial/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(webusb_serial C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt index 6ae5b5766..38c678cf2 100644 --- a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt +++ b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt @@ -2,34 +2,31 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(host_hid_to_device_cdc C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_dual_usb_example(${PROJECT} noos) +family_configure_dual_usb_example(${PROJECT_NAME} noos) # due to warnings from Pico-PIO-USB if (FAMILY STREQUAL rp2040) - target_compile_options(${PROJECT} PUBLIC + target_compile_options(${PROJECT_NAME} PUBLIC -Wno-error=shadow -Wno-error=cast-align -Wno-error=cast-qual diff --git a/examples/dual/host_info_to_device_cdc/CMakeLists.txt b/examples/dual/host_info_to_device_cdc/CMakeLists.txt index ad3c5ddf0..87b5336f1 100644 --- a/examples/dual/host_info_to_device_cdc/CMakeLists.txt +++ b/examples/dual/host_info_to_device_cdc/CMakeLists.txt @@ -2,39 +2,36 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(host_info_to_device_cdc C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_dual_usb_example(${PROJECT} ${RTOS}) +family_configure_dual_usb_example(${PROJECT_NAME} ${RTOS}) # due to warnings from Pico-PIO-USB if (FAMILY STREQUAL rp2040) - target_compile_options(${PROJECT} PUBLIC + target_compile_options(${PROJECT_NAME} PUBLIC -Wno-error=shadow -Wno-error=cast-align -Wno-error=cast-qual diff --git a/examples/host/bare_api/CMakeLists.txt b/examples/host/bare_api/CMakeLists.txt index 0efe84b60..4993f93b9 100644 --- a/examples/host/bare_api/CMakeLists.txt +++ b/examples/host/bare_api/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(bare_api C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT} noos) +family_configure_host_example(${PROJECT_NAME} noos) diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index e8928cda5..3098c37fa 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -2,23 +2,20 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(cdc_msc_hid C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c @@ -26,10 +23,10 @@ target_sources(${PROJECT} PUBLIC ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT} noos) +family_configure_host_example(${PROJECT_NAME} noos) diff --git a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt index 78b2784fe..3ceefb3f4 100644 --- a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt +++ b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt @@ -2,23 +2,20 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(cdc_msc_hid_freertos C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c @@ -26,10 +23,10 @@ target_sources(${PROJECT} PUBLIC ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT} freertos) +family_configure_host_example(${PROJECT_NAME} freertos) diff --git a/examples/host/device_info/CMakeLists.txt b/examples/host/device_info/CMakeLists.txt index 33953233d..9b96a8af8 100644 --- a/examples/host/device_info/CMakeLists.txt +++ b/examples/host/device_info/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(device_info C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT} noos) +family_configure_host_example(${PROJECT_NAME} noos) diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt index fb5faf210..287e9fb7f 100644 --- a/examples/host/hid_controller/CMakeLists.txt +++ b/examples/host/hid_controller/CMakeLists.txt @@ -2,32 +2,29 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(hid_controller C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT} noos) +family_configure_host_example(${PROJECT_NAME} noos) diff --git a/examples/host/midi_rx/CMakeLists.txt b/examples/host/midi_rx/CMakeLists.txt index 33953233d..62bb89e95 100644 --- a/examples/host/midi_rx/CMakeLists.txt +++ b/examples/host/midi_rx/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(midi_rx C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT} noos) +family_configure_host_example(${PROJECT_NAME} noos) diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index e9c15b7c1..21703030c 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -2,23 +2,20 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(msc_file_explorer C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c ${TOP}/lib/fatfs/source/ff.c @@ -34,7 +31,7 @@ if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") endif () # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ${TOP}/lib/fatfs/source ${TOP}/lib/embedded-cli @@ -42,4 +39,4 @@ target_include_directories(${PROJECT} PUBLIC # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT} noos) +family_configure_host_example(${PROJECT_NAME} noos) diff --git a/examples/typec/power_delivery/CMakeLists.txt b/examples/typec/power_delivery/CMakeLists.txt index 837b4996a..728221eb4 100644 --- a/examples/typec/power_delivery/CMakeLists.txt +++ b/examples/typec/power_delivery/CMakeLists.txt @@ -2,31 +2,28 @@ cmake_minimum_required(VERSION 3.20) 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} C CXX ASM) +project(power_delivery C CXX ASM) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) # Espressif has its own cmake build system if(FAMILY STREQUAL "espressif") return() endif() -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ) # Example include -target_include_directories(${PROJECT} PUBLIC +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 5eadcdaa9..baa8422fe 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -207,11 +207,6 @@ function(family_add_subdirectory DIR) endif() endfunction() -function(family_get_project_name OUTPUT_NAME DIR) - get_filename_component(SHORT_NAME ${DIR} NAME) - set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE) -endfunction() - function(family_initialize_project PROJECT DIR) # set output suffix to .elf (skip espressif and rp2040) if(NOT FAMILY STREQUAL "espressif" AND NOT FAMILY STREQUAL "rp2040") diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 390d6072c..1602e35eb 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -296,7 +296,7 @@ function(family_configure_host_example TARGET RTOS) # Pico-PIO-USB does not compile with all pico-sdk supported compilers, so check before enabling it is_compiler_supported_by_pico_pio_usb(PICO_PIO_USB_COMPILER_SUPPORTED) if (PICO_PIO_USB_COMPILER_SUPPORTED) - family_add_pico_pio_usb(${PROJECT}) + family_add_pico_pio_usb(${TARGET}) endif() endif() diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 470a8a18b..ba5b4afd1 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -117,7 +117,16 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 } } + #ifndef CFG_TUSB_DEBUG_PRINTF + // not found return the key value in hex if no custom printf is defined + static char not_found[11]; + if (snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long)key) <= 0) { + not_found[0] = 0; + } + return not_found; + #else return "NotFound"; + #endif } #endif // CFG_TUSB_DEBUG diff --git a/test/fuzz/device/cdc/CMakeLists.txt b/test/fuzz/device/cdc/CMakeLists.txt index c60f292b9..85094cfb1 100644 --- a/test/fuzz/device/cdc/CMakeLists.txt +++ b/test/fuzz/device/cdc/CMakeLists.txt @@ -2,28 +2,25 @@ cmake_minimum_required(VERSION 3.5) 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(cdc) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${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 +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/test/fuzz/device/msc/CMakeLists.txt b/test/fuzz/device/msc/CMakeLists.txt index 8bff217cb..6eb6c8c46 100644 --- a/test/fuzz/device/msc/CMakeLists.txt +++ b/test/fuzz/device/msc/CMakeLists.txt @@ -2,28 +2,25 @@ cmake_minimum_required(VERSION 3.5) 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(msc) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${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 +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) diff --git a/test/fuzz/device/net/CMakeLists.txt b/test/fuzz/device/net/CMakeLists.txt index 8bff217cb..84e92ad2f 100644 --- a/test/fuzz/device/net/CMakeLists.txt +++ b/test/fuzz/device/net/CMakeLists.txt @@ -2,28 +2,25 @@ cmake_minimum_required(VERSION 3.5) 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(net) # Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) -add_executable(${PROJECT}) +add_executable(${PROJECT_NAME}) # Example source -target_sources(${PROJECT} PUBLIC +target_sources(${PROJECT_NAME} PUBLIC ${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 +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_device_example(${PROJECT} noos) +family_configure_device_example(${PROJECT_NAME} noos) -- cgit v1.3.1 From 185757ed413fc7bdc65cf494a6079cfed049f98e Mon Sep 17 00:00:00 2001 From: James Smith <{ID}+{username}@users.noreply.github.com> Date: Sat, 20 Dec 2025 13:27:29 -0700 Subject: Added tud_vendor_write_clear() which forcefully clears TX buffer --- examples/device/webusb_serial/src/main.c | 1 + src/class/vendor/vendor_device.c | 6 ++++++ src/class/vendor/vendor_device.h | 7 +++++++ src/common/tusb_fifo.c | 16 ++++++++++++++++ src/common/tusb_fifo.h | 1 + src/common/tusb_private.h | 4 ++++ 6 files changed, 35 insertions(+) (limited to 'src') diff --git a/examples/device/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c index 50794bdba..155768b76 100644 --- a/examples/device/webusb_serial/src/main.c +++ b/examples/device/webusb_serial/src/main.c @@ -196,6 +196,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ tud_vendor_write_str("\r\nWebUSB interface connected\r\n"); tud_vendor_write_flush(); } else { + tud_vendor_write_clear(); // anything left in the buffer is now thrown out blink_interval_ms = BLINK_MOUNTED; } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 9972911e0..ced3c0d71 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -160,6 +160,12 @@ uint32_t tud_vendor_n_write_available(uint8_t idx) { vendord_interface_t *p_itf = &_vendord_itf[idx]; return tu_edpt_stream_write_available(&p_itf->stream.tx); } + +uint32_t tud_vendor_n_write_clear(uint8_t idx) { + TU_VERIFY(idx < CFG_TUD_VENDOR, 0); + vendord_interface_t *p_itf = &_vendord_itf[idx]; + return tu_edpt_stream_count_and_clear(&p_itf->stream.tx); +} #endif //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index d59c885d2..878d7aee0 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -91,6 +91,9 @@ uint32_t tud_vendor_n_write_flush(uint8_t idx); // Return number of bytes available for writing in TX FIFO uint32_t tud_vendor_n_write_available(uint8_t idx); + +// Clear the write buffer and return the number of elements cleared +uint32_t tud_vendor_n_write_clear(uint8_t idx); #endif // Write a null-terminated string to TX FIFO @@ -148,6 +151,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_flush(void) { TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) { return tud_vendor_n_write_available(0); } + +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_clear(void) { + return tud_vendor_n_write_clear(0); +} #endif // backward compatible diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e97b6ccce..28086be0b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -95,6 +95,22 @@ void tu_fifo_clear(tu_fifo_t *f) { ff_unlock(f->mutex_rd); } +// synchronously count then clear fifo, returning the count +uint16_t tu_fifo_count_and_clear(tu_fifo_t *f) { + ff_lock(f->mutex_wr); + ff_lock(f->mutex_rd); + + uint16_t cnt = tu_fifo_count(f); + + f->rd_idx = 0; + f->wr_idx = 0; + + ff_unlock(f->mutex_wr); + ff_unlock(f->mutex_rd); + + return cnt; +} + // Change the fifo overwritable mode void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { if (f->overwritable == overwritable) { diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 2e2a0db6f..75eeded01 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -159,6 +159,7 @@ typedef enum { bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); void tu_fifo_clear(tu_fifo_t *f); +uint16_t tu_fifo_count_and_clear(tu_fifo_t *f); #if OSAL_MUTEX_REQUIRED TU_ATTR_ALWAYS_INLINE static inline diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 10e12c2af..0c1709d49 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -144,6 +144,10 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_clear(tu_edpt_stream_t * tu_fifo_clear(&s->ff); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_stream_count_and_clear(tu_edpt_stream_t *s) { + return tu_fifo_count_and_clear(&s->ff); +} + TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_empty(tu_edpt_stream_t *s) { return tu_fifo_empty(&s->ff); } -- cgit v1.3.1 From b7463bad87456303c0b68bda120a300b343f45fa Mon Sep 17 00:00:00 2001 From: James Smith <{ID}+{username}@users.noreply.github.com> Date: Sun, 21 Dec 2025 06:41:57 -0700 Subject: Removed tu_fifo_count_and_clear --- src/class/vendor/vendor_device.c | 4 +++- src/common/tusb_fifo.c | 16 ---------------- src/common/tusb_fifo.h | 1 - src/common/tusb_private.h | 4 ---- 4 files changed, 3 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index ced3c0d71..762cbeebc 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -164,7 +164,9 @@ uint32_t tud_vendor_n_write_available(uint8_t idx) { uint32_t tud_vendor_n_write_clear(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_count_and_clear(&p_itf->stream.tx); + uint32_t cnt = tu_edpt_stream_read_available(&p_itf->stream.tx); + tu_edpt_stream_clear(&p_itf->stream.tx); + return cnt; } #endif diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 28086be0b..e97b6ccce 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -95,22 +95,6 @@ void tu_fifo_clear(tu_fifo_t *f) { ff_unlock(f->mutex_rd); } -// synchronously count then clear fifo, returning the count -uint16_t tu_fifo_count_and_clear(tu_fifo_t *f) { - ff_lock(f->mutex_wr); - ff_lock(f->mutex_rd); - - uint16_t cnt = tu_fifo_count(f); - - f->rd_idx = 0; - f->wr_idx = 0; - - ff_unlock(f->mutex_wr); - ff_unlock(f->mutex_rd); - - return cnt; -} - // Change the fifo overwritable mode void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { if (f->overwritable == overwritable) { diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 75eeded01..2e2a0db6f 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -159,7 +159,6 @@ typedef enum { bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); void tu_fifo_clear(tu_fifo_t *f); -uint16_t tu_fifo_count_and_clear(tu_fifo_t *f); #if OSAL_MUTEX_REQUIRED TU_ATTR_ALWAYS_INLINE static inline diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 0c1709d49..10e12c2af 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -144,10 +144,6 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_clear(tu_edpt_stream_t * tu_fifo_clear(&s->ff); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_stream_count_and_clear(tu_edpt_stream_t *s) { - return tu_fifo_count_and_clear(&s->ff); -} - TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_empty(tu_edpt_stream_t *s) { return tu_fifo_empty(&s->ff); } -- cgit v1.3.1 From b53739dee47ae21a21eaa74e9ae6d17d0def32c8 Mon Sep 17 00:00:00 2001 From: James Smith <{ID}+{username}@users.noreply.github.com> Date: Sun, 21 Dec 2025 09:06:05 -0700 Subject: Change return of tud_vendor_n_write_clear from uint32_t to bool --- src/class/vendor/vendor_device.c | 5 ++--- src/class/vendor/vendor_device.h | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 762cbeebc..b8e6fec6f 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -161,12 +161,11 @@ uint32_t tud_vendor_n_write_available(uint8_t idx) { return tu_edpt_stream_write_available(&p_itf->stream.tx); } -uint32_t tud_vendor_n_write_clear(uint8_t idx) { +bool tud_vendor_n_write_clear(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - uint32_t cnt = tu_edpt_stream_read_available(&p_itf->stream.tx); tu_edpt_stream_clear(&p_itf->stream.tx); - return cnt; + return true; } #endif diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 878d7aee0..c3de4c49d 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -92,8 +92,8 @@ uint32_t tud_vendor_n_write_flush(uint8_t idx); // Return number of bytes available for writing in TX FIFO uint32_t tud_vendor_n_write_available(uint8_t idx); -// Clear the write buffer and return the number of elements cleared -uint32_t tud_vendor_n_write_clear(uint8_t idx); +// Clear the transmit FIFO +bool tud_vendor_n_write_clear(uint8_t idx); #endif // Write a null-terminated string to TX FIFO @@ -152,7 +152,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) { return tud_vendor_n_write_available(0); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_clear(void) { +TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_write_clear(void) { return tud_vendor_n_write_clear(0); } #endif -- cgit v1.3.1 From b3dd0a113adefd1493dbd1417ece346528951b1d Mon Sep 17 00:00:00 2001 From: Cédric Berger Date: Fri, 26 Dec 2025 17:25:25 +0100 Subject: Do not randomly include stm32h7xx.h Enable D-Cache unless we're compiling for the M4 core of a dual-core H7 mcu by directly testing CORE_CM4 --- src/common/tusb_mcu.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 55f7e0b7c..ebe486e40 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -245,13 +245,12 @@ #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 #elif TU_CHECK_MCU(OPT_MCU_STM32H7) - #include "stm32h7xx.h" #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 #define TUP_DCD_ENDPOINT_MAX 9 - #if __CORTEX_M == 7 + #ifndef CORE_CM4 // Enable dcache if DMA is enabled #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE -- cgit v1.3.1 From d77f1e8eb6f53cdb55987165b36e301daf1f9828 Mon Sep 17 00:00:00 2001 From: Cédric Berger Date: Fri, 26 Dec 2025 17:27:05 +0100 Subject: Prevent unused-variable warning in dcd_host.c 'idx' is not used if CFG_TUH_CDC_LINE_CODING_ON_ENUM is not defined. --- src/class/cdc/cdc_host.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 32f6827b0..f19c4a327 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -828,7 +828,9 @@ static bool set_line_state_on_enum(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { ENUM_SET_LINE_CONTROL, ENUM_SET_LINE_COMPLETE, }; + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM const uint8_t idx = get_idx_by_ptr(p_cdc); + #endif const uintptr_t state = xfer->user_data; switch (state) { -- cgit v1.3.1 From 4e4398898040118969421dc236ec8f453f9b503d Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Dec 2025 18:09:54 +0700 Subject: tusb_fifo remove item_size make it fifo of bytes --- src/class/audio/audio_device.c | 12 +-- src/common/tusb_fifo.c | 139 +++++++++++++++------------------- src/common/tusb_fifo.h | 39 +++++----- src/common/tusb_verify.h | 10 ++- src/osal/osal_none.h | 16 ++-- src/osal/osal_pico.h | 54 +++++++------ src/portable/synopsys/dwc2/dcd_dwc2.c | 17 ++--- src/tusb.c | 2 +- src/tusb_option.h | 1 + test/unit-test/project.yml | 1 + test/unit-test/test/test_fifo.c | 36 +-------- 11 files changed, 140 insertions(+), 187 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 55eba81dd..be0224811 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -674,17 +674,17 @@ void audiod_init(void) { switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 case 0: - tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 case 1: - tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 case 2: - tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, true); break; #endif } @@ -716,17 +716,17 @@ void audiod_init(void) { switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 case 0: - tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 case 1: - tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 case 2: - tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, true); break; #endif } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 450c31f57..7822b7aae 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -59,7 +59,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ff_unlock(osal_mutex_t mutex) { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, bool overwritable) { // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable // only if overflow happens once (important for unsupervised DMA applications) @@ -72,7 +72,6 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si f->buffer = (uint8_t *)buffer; f->depth = depth; - f->item_size = (uint16_t)(item_size & 0x7FFFu); f->overwritable = overwritable; f->rd_idx = 0u; f->wr_idx = 0u; @@ -130,7 +129,10 @@ enum { }; // Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_fixed_addr(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len) { +static void ff_push_access_mode(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len, + uint8_t data_stride, uint8_t addr_stride) { + (void)data_stride; + (void)addr_stride; // Reading full available 16/32-bit data from const app address uint16_t n_items = len / sizeof(fixed_access_item_t); while (n_items--) { @@ -167,86 +169,70 @@ static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8 #endif // send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, - tu_fifo_access_mode_t copy_mode) { - const uint16_t lin_count = f->depth - wr_ptr; - const uint16_t wrap_count = n - lin_count; - - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; - - // current buffer of fifo - uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size); - - switch (copy_mode) { - case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { - // Linear only - memcpy(ff_buf, app_buf, n * f->item_size); +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride, + uint8_t addr_stride) { + uint16_t lin_bytes = f->depth - wr_ptr; + uint16_t wrap_bytes = n - lin_bytes; + uint8_t *ff_buf = f->buffer + wr_ptr; + +#if CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + if (data_stride > 1) { + const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; + if (n <= lin_bytes) { + // Linear only + ff_push_access_mode(ff_buf, reg_rx, n, data_stride, addr_stride); + } else { + // Wrap around + + // Write full words to linear part of buffer + uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; + ff_push_access_mode(ff_buf, reg_rx, lin_nitems_bytes, data_stride, addr_stride); + ff_buf += lin_nitems_bytes; + + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; + if (rem > 0) { + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); + const fixed_access_item_t tmp = *reg_rx; + tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); + + wrap_bytes -= remrem; + ff_buf = f->buffer + remrem; // wrap around } else { - // Wrap around - memcpy(ff_buf, app_buf, lin_bytes); // linear part - memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + ff_buf = f->buffer; // wrap around to beginning } - break; -#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - case TU_FIFO_FIXED_ADDR_RW32: { - const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; - if (n <= lin_count) { - // Linear only - ff_push_fixed_addr(ff_buf, reg_rx, n * f->item_size); - } else { - // Wrap around - - // Write full words to linear part of buffer - uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; - ff_push_fixed_addr(ff_buf, reg_rx, lin_nitems_bytes); - ff_buf += lin_nitems_bytes; - - // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; - if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); - const fixed_access_item_t tmp = *reg_rx; - tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); - - wrap_bytes -= remrem; - ff_buf = f->buffer + remrem; // wrap around - } else { - ff_buf = f->buffer; // wrap around to beginning - } - - // Write data wrapped part - if (wrap_bytes > 0) { - ff_push_fixed_addr(ff_buf, reg_rx, wrap_bytes); - } + // Write data wrapped part + if (wrap_bytes > 0) { + ff_push_access_mode(ff_buf, reg_rx, wrap_bytes, data_stride, addr_stride); } - break; } + } else #endif - - default: - break; // unknown mode + { + // single byte access + if (n <= lin_bytes) { + // Linear only + memcpy(ff_buf, app_buf, n); + } else { + // Wrap around + memcpy(ff_buf, app_buf, lin_bytes); // linear part + memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + } } } // get n items from fifo WITHOUT updating read pointer static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_access_mode_t copy_mode) { - const uint16_t lin_count = f->depth - rd_ptr; - const uint16_t wrap_count = n - lin_count; // only used if wrapped - - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; - - // current buffer of fifo - const uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size); + uint16_t lin_bytes = f->depth - rd_ptr; + uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped + const uint8_t *ff_buf = f->buffer + rd_ptr; switch (copy_mode) { case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - memcpy(app_buf, ff_buf, n * f->item_size); + memcpy(app_buf, ff_buf, n); } else { // Wrap around memcpy(app_buf, ff_buf, lin_bytes); // linear part @@ -258,9 +244,9 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd case TU_FIFO_FIXED_ADDR_RW32: { volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf; - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - ff_pull_fixed_addr(reg_tx, ff_buf, n * f->item_size); + ff_pull_fixed_addr(reg_tx, ff_buf, n); } else { // Wrap around case @@ -389,7 +375,8 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_f } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride) { if (n == 0) { return 0; } @@ -415,8 +402,8 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (access_mode == TU_FIFO_INC_ADDR_RW8) { - buf8 += (n - f->depth) * f->item_size; + if (data_stride == TU_FIFO_INC_ADDR_RW8) { + buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could // accidentally discard data. @@ -451,7 +438,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - ff_push_n(f, buf8, n, wr_ptr, access_mode); + ff_push_n(f, buf8, n, wr_ptr, data_stride, addr_stride); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); @@ -491,7 +478,7 @@ static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_ } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size); + memcpy(buf, f->buffer + rd_ptr, 1); return true; } @@ -526,7 +513,7 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) { ret = false; } else { const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - memcpy(f->buffer + (wr_ptr * f->item_size), data, f->item_size); + memcpy(f->buffer + wr_ptr, data, 1); f->wr_idx = advance_index(f->depth, wr_idx, 1); ret = true; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f58cc3fcb..b48cf4cea 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -58,6 +58,9 @@ extern "C" { #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0 #endif +#ifndef CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 0 +#endif /* Write/Read "pointer" is in the range of: 0 .. depth - 1, and is used to get the fifo data. * Write/Read "index" is always in the range of: 0 .. 2*depth-1 @@ -118,13 +121,9 @@ extern "C" { typedef struct { uint8_t *buffer; // buffer pointer uint16_t depth; // max items + bool overwritable; // ovwerwritable when full - struct TU_ATTR_PACKED { - uint16_t item_size : 15; // size of each item - bool overwritable : 1; // ovwerwritable when full - }; - - volatile uint16_t wr_idx; // write index + volatile uint16_t wr_idx; // write index TODO maybe can drop volatile volatile uint16_t rd_idx; // read index #if OSAL_MUTEX_REQUIRED @@ -141,17 +140,16 @@ typedef struct { } linear, wrapped; } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ - { \ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ +#define TU_FIFO_INIT(_buffer, _depth, _overwritable) \ + { \ + .buffer = _buffer, \ + .depth = _depth, \ + .overwritable = _overwritable, \ } -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) +#define TU_FIFO_DEF(_name, _depth, _overwritable) \ + uint8_t _name##_buf[_depth]; \ + tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _overwritable) // Write modes intended to allow special read and write functions to be able to // copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others @@ -163,7 +161,7 @@ typedef enum { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, bool overwritable); void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); void tu_fifo_clear(tu_fifo_t *f); @@ -223,14 +221,11 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_INC_ADDR_RW8); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n_fixed_addr(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_FIXED_ADDR_RW32); + return tu_fifo_write_n_access_mode(f, data, n, 1, 1); } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 587554e7f..c9e06361c 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -96,10 +96,12 @@ * - TU_VERIFY_1ARGS : return false if failed * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define TU_VERIFY_DEFINE(_cond, _ret) \ - do { \ - if (!(_cond)) { return _ret; } \ - } while(0) +#define TU_VERIFY_DEFINE(_cond, _ret) \ + do { \ + if (!(_cond)) { \ + return _ret; \ + } \ + } while (0) #define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) #define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret) diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index aa6111a16..6ab18ace8 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -157,18 +157,18 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd typedef struct { void (* interrupt_set)(bool enabled); + uint16_t item_size; tu_fifo_t ff; } osal_queue_def_t; typedef osal_queue_def_t* osal_queue_t; // _int_set is used as mutex in OS NONE (disable/enable USB ISR) -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .interrupt_set = _int_set, \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ + uint8_t _name##_buf[_depth * sizeof(_type)]; \ + osal_queue_def_t _name = {.interrupt_set = _int_set, \ + .item_size = sizeof(_type), \ + .ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)} TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); @@ -184,7 +184,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v (void) msec; // not used, always behave as msec = 0 qhdl->interrupt_set(false); - const bool success = tu_fifo_read(&qhdl->ff, data); + const bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size); qhdl->interrupt_set(true); return success; @@ -195,7 +195,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void qhdl->interrupt_set(false); } - const bool success = tu_fifo_write(&qhdl->ff, data); + const bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size); if (!in_isr) { qhdl->interrupt_set(true); diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index f5385071a..79b728e9a 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -47,40 +47,39 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { // Spinlock API //--------------------------------------------------------------------+ typedef critical_section_t osal_spinlock_t; // pico implement critical section with spinlock -#define OSAL_SPINLOCK_DEF(_name, _int_set) \ - osal_spinlock_t _name +#define OSAL_SPINLOCK_DEF(_name, _int_set) osal_spinlock_t _name TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { critical_section_init(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + (void)in_isr; critical_section_enter_blocking(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + (void)in_isr; critical_section_exit(ctx); } //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ -typedef struct semaphore osal_semaphore_def_t, * osal_semaphore_t; +typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) { sem_init(semdef, 0, 255); return semdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) { - (void) semd_hdl; + (void)semd_hdl; return true; // nothing to do } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - (void) in_isr; + (void)in_isr; return sem_release(sem_hdl); } @@ -96,15 +95,15 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s // MUTEX API // Within tinyusb, mutex is never used in ISR context //--------------------------------------------------------------------+ -typedef struct mutex osal_mutex_def_t, * osal_mutex_t; +typedef struct mutex osal_mutex_def_t, *osal_mutex_t; -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { mutex_init(mdef); return mdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) { - (void) mutex_hdl; + (void)mutex_hdl; return true; // nothing to do } @@ -123,46 +122,45 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd #include "common/tusb_fifo.h" typedef struct { - tu_fifo_t ff; + uint16_t item_size; + tu_fifo_t ff; struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section } osal_queue_def_t; -typedef osal_queue_def_t* osal_queue_t; +typedef osal_queue_def_t *osal_queue_t; // role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ + uint8_t _name##_buf[_depth * sizeof(_type)]; \ + osal_queue_def_t _name = {.item_size = sizeof(_type), .ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)} -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { critical_section_init(&qdef->critsec); - (void) tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; + tu_fifo_clear(&qdef->ff); + return (osal_queue_t)qdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { - osal_queue_def_t* qdef = (osal_queue_def_t*) qhdl; + osal_queue_def_t *qdef = (osal_queue_def_t *)qhdl; critical_section_deinit(&qdef->critsec); return true; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { - (void) msec; // not used, always behave as msec = 0 +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) { + (void)msec; // not used, always behave as msec = 0 critical_section_enter_blocking(&qhdl->critsec); - bool success = tu_fifo_read(&qhdl->ff, data); + bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size); critical_section_exit(&qhdl->critsec); return success; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { - (void) in_isr; +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, const void *data, bool in_isr) { + (void)in_isr; critical_section_enter_blocking(&qhdl->critsec); - bool success = tu_fifo_write(&qhdl->ff, data); + bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size); critical_section_exit(&qhdl->critsec); return success; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ba40498e6..aacef691f 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -345,10 +345,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2_dep_t* const epin = &dwc2->ep[0][epnum]; - xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); +static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { + dwc2_dep_t *const epin = &dwc2->ep[0][epnum]; + xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; const uint16_t remain_packets = tsiz.packet_count; @@ -438,7 +437,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin dep->diepctl = depctl.value; // enable endpoint if (dir == TUSB_DIR_IN && total_bytes != 0) { - const uint16_t xferred_bytes = epin_write_tx_fifo(rhport, epnum); + const uint16_t xferred_bytes = epin_write_tx_fifo(dwc2, epnum); // Enable TXFE interrupt if there are still data to be sent // EP0 only sends one packet at a time, so no need to check for EP0 @@ -689,9 +688,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // into the USB buffer! bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) { (void) is_isr; - // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); @@ -893,7 +889,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32, + 0); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; @@ -967,7 +964,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep // - 64 bytes or // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) if (diepint_bm.txfifo_empty && tu_bit_test(dwc2->diepempmsk, epnum)) { - epin_write_tx_fifo(rhport, epnum); + epin_write_tx_fifo(dwc2, epnum); // Turn off TXFE if all bytes are written. dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; diff --git a/src/tusb.c b/src/tusb.c index 8117c3e3e..ed254a10b 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -316,7 +316,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove #endif s->is_host = is_host; - tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); + tu_fifo_config(&s->ff, ff_buf, ff_bufsize, overwritable); #if OSAL_MUTEX_REQUIRED if (ff_buf != NULL && ff_bufsize > 0) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 1dc920d84..de54d33d8 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -307,6 +307,7 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 1 #endif #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index 3968faaef..d7646ca7f 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -129,6 +129,7 @@ :test: - _UNITY_TEST_ - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32 + - CFG_TUSB_FIFO_MULTI_BYTES_ACCESS=1 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index 35bbeaa62..d0e3c2d37 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -32,7 +32,7 @@ #define FIFO_SIZE 64 uint8_t tu_ff_buf[FIFO_SIZE * sizeof(uint8_t)]; -tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, uint8_t, false); +tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, false); tu_fifo_t *ff = &tu_ff; tu_fifo_buffer_info_t info; @@ -68,34 +68,6 @@ void test_normal(void) { } } -void test_item_size(void) { - uint8_t ff4_buf[FIFO_SIZE * sizeof(uint32_t)]; - tu_fifo_t ff4 = TU_FIFO_INIT(ff4_buf, FIFO_SIZE, uint32_t, false); - - uint32_t data4[2 * FIFO_SIZE]; - for (uint32_t i = 0; i < sizeof(data4) / 4; i++) { - data4[i] = i; - } - - // fill up fifo - tu_fifo_write_n(&ff4, data4, FIFO_SIZE); - - uint32_t rd_buf4[FIFO_SIZE]; - uint16_t rd_count; - - // read 0 -> 4 - rd_count = tu_fifo_read_n(&ff4, rd_buf4, 5); - TEST_ASSERT_EQUAL(5, rd_count); - TEST_ASSERT_EQUAL_UINT32_ARRAY(data4, rd_buf4, rd_count); // 0 -> 4 - - tu_fifo_write_n(&ff4, data4 + FIFO_SIZE, 5); - - // read all 5 -> 68 - rd_count = tu_fifo_read_n(&ff4, rd_buf4, FIFO_SIZE); - TEST_ASSERT_EQUAL(FIFO_SIZE, rd_count); - TEST_ASSERT_EQUAL_UINT32_ARRAY(data4 + 5, rd_buf4, rd_count); // 5 -> 68 -} - void test_read_n(void) { uint16_t rd_count; @@ -362,7 +334,7 @@ void test_rd_idx_wrap(void) { uint8_t buf[10]; uint8_t dst[10]; - tu_fifo_config(&ff10, buf, 10, 1, 1); + tu_fifo_config(&ff10, buf, 10, 1); uint16_t n; @@ -431,7 +403,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -453,7 +425,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); -- cgit v1.3.1 From d61ed922206148081afa70803ad717858bc5b756 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 01:07:52 +0700 Subject: re-branding fixed address fifo read/write to stride mode --- src/common/tusb_fifo.c | 205 +++++++++++++++---------------- src/common/tusb_fifo.h | 62 ++++------ src/portable/microchip/samg/dcd_samg.c | 4 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 +- src/portable/synopsys/dwc2/dcd_dwc2.c | 5 +- src/tusb_option.h | 3 +- test/unit-test/project.yml | 4 +- test/unit-test/test/test_fifo.c | 8 +- 8 files changed, 142 insertions(+), 153 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 7822b7aae..a347fbee3 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -113,87 +113,92 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // Pull & Push // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ -#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - #if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 32 - #define fixed_unaligned_write tu_unaligned_write32 - #define fixed_unaligned_read tu_unaligned_read32 -typedef uint32_t fixed_access_item_t; - #elif CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 16 - #define fixed_unaligned_write tu_unaligned_write16 - #define fixed_unaligned_read tu_unaligned_read16 -typedef uint16_t fixed_access_item_t; +#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 + #define stride_unaligned_write tu_unaligned_write32 + #define stride_unaligned_read tu_unaligned_read32 +typedef uint32_t stride_item_t; + #elif CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 2 + #define stride_unaligned_write tu_unaligned_write16 + #define stride_unaligned_read tu_unaligned_read16 +typedef uint16_t stride_item_t; #endif enum { - FIXED_ACCESS_REMAINDER_MASK = sizeof(fixed_access_item_t) - 1u + STRIDE_REMAIN_MASK = sizeof(stride_item_t) - 1u }; // Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_access_mode(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len, - uint8_t data_stride, uint8_t addr_stride) { - (void)data_stride; - (void)addr_stride; - // Reading full available 16/32-bit data from const app address - uint16_t n_items = len / sizeof(fixed_access_item_t); +static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, uint16_t len) { + // Reading full available 16/32-bit src and write to fifo + uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; while (n_items--) { - const fixed_access_item_t tmp = *reg_rx; - fixed_unaligned_write(ff_buf, tmp); - ff_buf += sizeof(fixed_access_item_t); + const stride_item_t tmp = *src; + stride_unaligned_write(ff_buf, tmp); + ff_buf += sizeof(stride_item_t); + + #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE + src = (const volatile uint8_t *)src + addr_stride; + #endif } - // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) from const app address - const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK; + // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) + const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { - const fixed_access_item_t tmp = *reg_rx; + const stride_item_t tmp = *src; memcpy(ff_buf, &tmp, bytes_rem); } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8_t *ff_buf, uint16_t len) { - // Write full available 32 bit words to const address - uint16_t n_itmes = len / sizeof(fixed_access_item_t); - while (n_itmes--) { - *reg_tx = fixed_unaligned_read(ff_buf); - ff_buf += sizeof(fixed_access_item_t); +static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, uint16_t len) { + // Write full available 16/32 bit words to dest + uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; + while (n_items--) { + *dest = stride_unaligned_read(ff_buf); + ff_buf += sizeof(stride_item_t); + + #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE + dest = (const volatile uint8_t *)dest + addr_stride; + #endif } // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) - const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK; + const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { - fixed_access_item_t tmp = 0u; + stride_item_t tmp = 0u; memcpy(&tmp, ff_buf, bytes_rem); - *reg_tx = tmp; + *dest = tmp; } } #endif // send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride, - uint8_t addr_stride) { +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, bool stride_mode) { + (void)stride_mode; uint16_t lin_bytes = f->depth - wr_ptr; uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; -#if CFG_TUSB_FIFO_MULTI_BYTES_ACCESS - if (data_stride > 1) { - const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; +#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + if (stride_mode) { + const volatile stride_item_t *stride_src = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { - // Linear only - ff_push_access_mode(ff_buf, reg_rx, n, data_stride, addr_stride); + // Linear only case + ff_push_stride(ff_buf, stride_src, n); } else { - // Wrap around + // Wrap around case // Write full words to linear part of buffer - uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; - ff_push_access_mode(ff_buf, reg_rx, lin_nitems_bytes, data_stride, addr_stride); + uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; + ff_push_stride(ff_buf, stride_src, lin_nitems_bytes); ff_buf += lin_nitems_bytes; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; + const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); - const fixed_access_item_t tmp = *reg_rx; + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); + const stride_item_t tmp = *stride_src; tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); wrap_bytes -= remrem; @@ -204,7 +209,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 // Write data wrapped part if (wrap_bytes > 0) { - ff_push_access_mode(ff_buf, reg_rx, wrap_bytes, data_stride, addr_stride); + ff_push_stride(ff_buf, stride_src, wrap_bytes); } } } else @@ -212,10 +217,10 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 { // single byte access if (n <= lin_bytes) { - // Linear only + // Linear only case memcpy(ff_buf, app_buf, n); } else { - // Wrap around + // Wrap around case memcpy(ff_buf, app_buf, lin_bytes); // linear part memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part } @@ -223,63 +228,58 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 } // get n items from fifo WITHOUT updating read pointer -static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_access_mode_t copy_mode) { +static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, bool stride_mode) { + (void)stride_mode; uint16_t lin_bytes = f->depth - rd_ptr; uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; - switch (copy_mode) { - case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_bytes) { - // Linear only - memcpy(app_buf, ff_buf, n); - } else { - // Wrap around - memcpy(app_buf, ff_buf, lin_bytes); // linear part - memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part - } - break; +#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + if (stride_mode) { + volatile stride_item_t *stride_dst = (volatile stride_item_t *)app_buf; + + if (n <= lin_bytes) { + // Linear only case + ff_pull_stride(stride_dst, ff_buf, n); + } else { + // Wrap around case + + // Read full words from linear part + uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; + ff_pull_stride(stride_dst, ff_buf, lin_nitems_bytes); + ff_buf += lin_nitems_bytes; + + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; + if (rem > 0) { + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); + const stride_item_t scatter = (stride_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); -#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - case TU_FIFO_FIXED_ADDR_RW32: { - volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf; + *stride_dst = scatter; - if (n <= lin_bytes) { - // Linear only - ff_pull_fixed_addr(reg_tx, ff_buf, n); + wrap_bytes -= remrem; + ff_buf = f->buffer + remrem; // wrap around } else { - // Wrap around case - - // Read full words from linear part - uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; - ff_pull_fixed_addr(reg_tx, ff_buf, lin_nitems_bytes); - ff_buf += lin_nitems_bytes; - - // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; - if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); - const fixed_access_item_t scatter = (fixed_access_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); - - *reg_tx = scatter; - - wrap_bytes -= remrem; - ff_buf = f->buffer + remrem; // wrap around - } else { - ff_buf = f->buffer; // wrap around to beginning - } - - // Read data wrapped part - if (wrap_bytes > 0) { - ff_pull_fixed_addr(reg_tx, ff_buf, wrap_bytes); - } + ff_buf = f->buffer; // wrap around to beginning + } + + // Read data wrapped part + if (wrap_bytes > 0) { + ff_pull_stride(stride_dst, ff_buf, wrap_bytes); } - break; } + } else #endif - - default: - break; // unknown mode + { + // single byte access + if (n <= lin_bytes) { + // Linear only + memcpy(app_buf, ff_buf, n); + } else { + // Wrap around + memcpy(app_buf, ff_buf, lin_bytes); // linear part + memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part + } } } @@ -332,7 +332,7 @@ static uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { // Works on local copies of w and r // Must be protected by read mutex since in case of an overflow read pointer gets modified uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - tu_fifo_access_mode_t access_mode) { + bool stride_mode) { uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); if (count == 0) { return 0; // nothing to peek @@ -349,7 +349,7 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - ff_pull_n(f, p_buffer, n, rd_ptr, access_mode); + ff_pull_n(f, p_buffer, n, rd_ptr, stride_mode); return n; } @@ -357,17 +357,17 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui // Read n items without removing it from the FIFO, correct read pointer if overflowed uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { ff_lock(f->mutex_rd); - const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8); + const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, false); ff_unlock(f->mutex_rd); return ret; } // Read n items from fifo with access mode -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, bool stride_mode) { ff_lock(f->mutex_rd); // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); + n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, stride_mode); f->rd_idx = advance_index(f->depth, f->rd_idx, n); ff_unlock(f->mutex_rd); @@ -375,8 +375,7 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_f } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, - uint8_t addr_stride) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, bool stride_mode) { if (n == 0) { return 0; } @@ -402,7 +401,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (data_stride == TU_FIFO_INC_ADDR_RW8) { + if (!stride_mode) { buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could @@ -438,7 +437,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - ff_push_n(f, buf8, n, wr_ptr, data_stride, addr_stride); + ff_push_n(f, buf8, n, wr_ptr, stride_mode); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b48cf4cea..7623d4c4f 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -32,35 +32,31 @@ extern "C" { #endif -// Due to the use of unmasked pointers, this FIFO does not suffer from losing -// one item slice. Furthermore, write and read operations are completely -// decoupled as write and read functions do not modify a common state. Henceforth, -// writing or reading from the FIFO within an ISR is safe as long as no other -// process (thread or ISR) interferes. -// Also, this FIFO is ready to be used in combination with a DMA as the write and -// read pointers can be updated from within a DMA ISR. Overflows are detectable -// within a certain number (see tu_fifo_overflow()). - #include "common/tusb_common.h" #include "osal/osal.h" -// mutex is only needed for RTOS -// for OS None, we don't get preempted +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ +// mutex is only needed for RTOS. For OS None, we don't get preempted #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED -#if CFG_TUD_EDPT_DEDICATED_HWFIFO || CFG_TUH_EDPT_DEDICATED_HWFIFO - #ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 32 - #endif +#ifndef CFG_TUSB_FIFO_ACCESS_DATA_STRIDE + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 0 #endif -#ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0 +#ifndef CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 #endif -#ifndef CFG_TUSB_FIFO_MULTI_BYTES_ACCESS - #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 0 -#endif +// Due to the use of unmasked pointers, this FIFO does not suffer from losing +// one item slice. Furthermore, write and read operations are completely +// decoupled as write and read functions do not modify a common state. Henceforth, +// writing or reading from the FIFO within an ISR is safe as long as no other +// process (thread or ISR) interferes. +// Also, this FIFO is ready to be used in combination with a DMA as the write and +// read pointers can be updated from within a DMA ISR. Overflows are detectable +// within a certain number (see tu_fifo_overflow()). /* Write/Read "pointer" is in the range of: 0 .. depth - 1, and is used to get the fifo data. * Write/Read "index" is always in the range of: 0 .. 2*depth-1 @@ -122,6 +118,7 @@ typedef struct { uint8_t *buffer; // buffer pointer uint16_t depth; // max items bool overwritable; // ovwerwritable when full + // 1 byte padding here volatile uint16_t wr_idx; // write index TODO maybe can drop volatile volatile uint16_t rd_idx; // read index @@ -151,12 +148,10 @@ typedef struct { uint8_t _name##_buf[_depth]; \ tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _overwritable) -// Write modes intended to allow special read and write functions to be able to -// copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others -typedef enum { - TU_FIFO_INC_ADDR_RW8, // increased address read/write by bytes - normal (default) mode - TU_FIFO_FIXED_ADDR_RW32, // fixed address read/write by 2/4 bytes (items). -} tu_fifo_access_mode_t; +// Moving data from tusb_fifo <-> USB hardware FIFOs e.g. STM32s need to use a special stride mode which reads/writes +// data in 2/4 byte chunks from/to a fixed address (USB FIFO register) instead of incrementing the address. For this use +// read/write access_mode with stride_mode = true. The STRIPE DATA and ADDR stride must be configured with +// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE //--------------------------------------------------------------------+ // Setup API @@ -196,7 +191,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); // peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo //--------------------------------------------------------------------+ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - tu_fifo_access_mode_t access_mode); + bool stride_mode); bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); @@ -204,14 +199,10 @@ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); // Read API // peek() + advance read index //--------------------------------------------------------------------+ -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, bool stride_mode); bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n_fixed_addr(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_FIXED_ADDR_RW32); + return tu_fifo_read_n_access_mode(f, buffer, n, false); } // discard first n items from fifo i.e advance read pointer by n with mutex @@ -221,11 +212,10 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, - uint8_t addr_stride); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, bool stride_mode); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, 1, 1); + return tu_fifo_write_n_access_mode(f, data, n, false); } //--------------------------------------------------------------------+ diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 1faac2aa8..4115eecc5 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -437,7 +437,7 @@ void dcd_int_handler(uint8_t rhport) // write to EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo if (xfer->ff) { - tu_fifo_read_n_access_mode(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len, true); } else #endif @@ -471,7 +471,7 @@ void dcd_int_handler(uint8_t rhport) // Read from EP fifo #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len, true); } else #endif diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 91b876718..ca17d6251 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -194,7 +194,7 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transferred as 32-bit */ #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_read_n_access_mode(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now, true); } else #endif @@ -696,7 +696,7 @@ void dcd_int_handler(uint8_t rhport) /* copy the data from the PC to the previously provided buffer */ #if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far), TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far), true); } else #endif diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index aacef691f..8c97eaa2f 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_access_mode(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_read_n_access_mode(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, true); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,8 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32, - 0); + tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, true); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; diff --git a/src/tusb_option.h b/src/tusb_option.h index de54d33d8..a0f4e7057 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -307,7 +307,8 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 1 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address #endif #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index d7646ca7f..ea20c5f72 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -128,8 +128,8 @@ :defines: :test: - _UNITY_TEST_ - - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32 - - CFG_TUSB_FIFO_MULTI_BYTES_ACCESS=1 + - CFG_TUSB_FIFO_ACCESS_DATA_STRIDE=4 + - CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE=0 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index d0e3c2d37..453930a2f 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -403,7 +403,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, true); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -425,7 +425,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, true); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -445,7 +445,7 @@ void test_read_n_fixed_addr_rw32_nowrap(void) { tu_fifo_write_n(ff, pattern, 8); uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, true); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(8 - n, tu_fifo_count(ff)); @@ -469,7 +469,7 @@ void test_read_n_fixed_addr_rw32_wrapped(void) { } uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, true); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); -- cgit v1.3.1 From f20ad05d71919dd5656aa7f92b9e27582744348a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 16:26:24 +0700 Subject: update tu_fifo to work with fsdev hwfifo with increased address 16/32bit --- README.rst | 14 +- src/common/tusb_fifo.c | 10 +- src/common/tusb_fifo.h | 6 + src/common/tusb_mcu.h | 145 ++++++++++---------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 12 +- src/portable/st/stm32_fsdev/fsdev_at32.h | 1 - src/portable/st/stm32_fsdev/fsdev_ch32.h | 1 - src/portable/st/stm32_fsdev/fsdev_stm32.h | 186 ++++++++++++-------------- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +- src/tusb_option.h | 16 ++- test/unit-test/project.yml | 1 + 11 files changed, 205 insertions(+), 191 deletions(-) (limited to 'src') diff --git a/README.rst b/README.rst index da1f49fcd..4ab991bf5 100644 --- a/README.rst +++ b/README.rst @@ -139,7 +139,7 @@ Supported CPUs | | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | | | MAX78002 | | | | | | +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ -| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | Packet SRAM 512 | +| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | 512 USB RAM | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ | | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ @@ -221,25 +221,25 @@ Supported CPUs +--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+ | ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ -| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 512 | +| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | 512 USB RAM | | | +------------------------+--------+------+-----------+------------------------+--------------------+ | | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ | | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | 2KB USB RAM | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | 1KB USB RAM | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ -| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | 1KB USB RAM | | | +------------------------+--------+------+-----------+------------------------+--------------------+ | | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ | | N6 | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+--------------------+ -| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB | +| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | 1KB USB RAM | | +----+------------------------+--------+------+-----------+------------------------+--------------------+ -| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB | +| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | 2KB USB RAM | | | +------------------------+--------+------+-----------+------------------------+--------------------+ | | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | | | +------------------------+--------+------+-----------+------------------------+--------------------+ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a347fbee3..bc4ee180c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -113,7 +113,7 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // Pull & Push // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ -#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE +#if CFG_TUD_EDPT_DEDICATED_HWFIFO #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 #define stride_unaligned_write tu_unaligned_write32 #define stride_unaligned_read tu_unaligned_read32 @@ -138,7 +138,7 @@ static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, u ff_buf += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - src = (const volatile uint8_t *)src + addr_stride; + src = (const volatile stride_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } @@ -159,7 +159,7 @@ static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, ff_buf += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - dest = (const volatile uint8_t *)dest + addr_stride; + dest = (volatile stride_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } @@ -180,7 +180,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; -#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE +#if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { const volatile stride_item_t *stride_src = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { @@ -234,7 +234,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; -#if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE +#if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { volatile stride_item_t *stride_dst = (volatile stride_item_t *)app_buf; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 7623d4c4f..53c5f6e56 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -204,6 +204,9 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { return tu_fifo_read_n_access_mode(f, buffer, n, false); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_to_hwfifo(tu_fifo_t *f, void *buffer, uint16_t n) { + return tu_fifo_read_n_access_mode(f, buffer, n, true); +} // discard first n items from fifo i.e advance read pointer by n with mutex // return number of discarded items @@ -217,6 +220,9 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { return tu_fifo_write_n_access_mode(f, data, n, false); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_from_hwfifo(tu_fifo_t *f, const void *data, uint16_t n) { + return tu_fifo_write_n_access_mode(f, data, n, true); +} //--------------------------------------------------------------------+ // Internal Helper Local diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1e773bf96..f525a5a3d 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -176,10 +176,15 @@ //--------------------------------------------------------------------+ // ST //--------------------------------------------------------------------+ +#elif TU_CHECK_MCU(OPT_MCU_STM32C0) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u + #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32F1) // - F102, F103 use fsdev @@ -195,7 +200,7 @@ defined(STM32F103xE) || defined(STM32F103xG) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 512u #else #error "Unsupported STM32F1 mcu" #endif @@ -210,7 +215,16 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32F3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + + #if defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ + defined(STM32F373xC) + #define FSDEV_PMA_SIZE 512u + #elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ + defined(STM32F303xD) || defined(STM32F303xE) + #define FSDEV_PMA_SIZE 1024u + #else + #error "Unsupported STM32F3 mcu" + #endif #elif TU_CHECK_MCU(OPT_MCU_STM32F4) #define TUP_USBIP_DWC2 @@ -236,6 +250,26 @@ #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 +#elif TU_CHECK_MCU(OPT_MCU_STM32G0) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u + +#elif TU_CHECK_MCU(OPT_MCU_STM32G4) + // Device controller + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 1024u + + // TypeC controller + #define TUP_USBIP_TYPEC_STM32 + #define TUP_TYPEC_RHPORTS_NUM 1 + +#elif TU_CHECK_MCU(OPT_MCU_STM32H5) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u + #elif TU_CHECK_MCU(OPT_MCU_STM32H7) #include "stm32h7xx.h" #define TUP_USBIP_DWC2 @@ -250,35 +284,30 @@ #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 #endif -#elif TU_CHECK_MCU(OPT_MCU_STM32H5) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_STM32 -#elif TU_CHECK_MCU(OPT_MCU_STM32G4) - // Device controller - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 + // FS has 6, HS has 9 + #define TUP_DCD_ENDPOINT_MAX 9 - // TypeC controller - #define TUP_USBIP_TYPEC_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_TYPEC_RHPORTS_NUM 1 + // MCU with on-chip HS Phy + #define TUP_RHPORT_HIGHSPEED 1 -#elif TU_CHECK_MCU(OPT_MCU_STM32G0) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + // Enable dcache if DMA is enabled + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 -#elif TU_CHECK_MCU(OPT_MCU_STM32C0) +#elif TU_CHECK_MCU(OPT_MCU_STM32L0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u -#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) +#elif TU_CHECK_MCU(OPT_MCU_STM32L1) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_STM32L4) // - L4x2, L4x3 use fsdev @@ -295,28 +324,32 @@ defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u #else #error "Unsupported STM32L4 mcu" #endif -#elif TU_CHECK_MCU(OPT_MCU_STM32WB) +#elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE (1024u) -#elif TU_CHECK_MCU(OPT_MCU_STM32WBA) - #define TUP_USBIP_DWC2 - #define TUP_USBIP_DWC2_STM32 - #define TUP_DCD_ENDPOINT_MAX 9 - #define TUP_RHPORT_HIGHSPEED 1 +#elif TU_CHECK_MCU(OPT_MCU_STM32U0) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 1024u + +#elif TU_CHECK_MCU(OPT_MCU_STM32U3) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32U5) + // U535/545 use fsdev #if defined(STM32U535xx) || defined(STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - + #define FSDEV_PMA_SIZE 2048u #else #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 @@ -331,35 +364,16 @@ #endif #endif -#elif TU_CHECK_MCU(OPT_MCU_STM32L5) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32U0) +#elif TU_CHECK_MCU(OPT_MCU_STM32WB) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 1024u -#elif TU_CHECK_MCU(OPT_MCU_STM32U3) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) +#elif TU_CHECK_MCU(OPT_MCU_STM32WBA) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - - // FS has 6, HS has 9 - #define TUP_DCD_ENDPOINT_MAX 9 - - // MCU with on-chip HS Phy - #define TUP_RHPORT_HIGHSPEED 1 - - // Enable dcache if DMA is enabled - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE - #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 //--------------------------------------------------------------------+ // Sony @@ -566,6 +580,7 @@ #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_CH32 + #define FSDEV_PMA_SIZE 512u // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) @@ -611,15 +626,10 @@ //--------------------------------------------------------------------+ // ArteryTek //--------------------------------------------------------------------+ -#elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407) +#elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407, OPT_MCU_AT32F413) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_AT32F413) - #define TUP_USBIP_FSDEV - #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_AT32F415) #define TUP_USBIP_DWC2 @@ -655,10 +665,7 @@ #endif -//--------------------------------------------------------------------+ // External USB controller -//--------------------------------------------------------------------+ - #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4 * (CFG_TUH_DEVICE_MAX - 1)) @@ -670,6 +677,10 @@ // Default Values //--------------------------------------------------------------------+ +#if defined(TUP_USBIP_FSDEV) + #define TUP_DCD_ENDPOINT_MAX 8 +#endif + #ifndef TUP_MCU_MULTIPLE_CORE #define TUP_MCU_MULTIPLE_CORE 0 #endif diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 087639d4b..0c6f58cfb 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -319,11 +319,13 @@ static void handle_ctr_rx(uint32_t ep_id) { } else { buf_id = BTABLE_BUF_RX; } - uint16_t const rx_count = btable_get_count(ep_id, buf_id); + const uint16_t rx_count = btable_get_count(ep_id, buf_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); if (xfer->ff) { - fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); + // fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); + tu_fifo_write_from_hwfifo(xfer->ff, (void *)pma_buf, rx_count); } else { fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } @@ -720,7 +722,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); if (xfer->ff) { - fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); + // fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); + tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); } else { fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } @@ -740,7 +744,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { (void) rhport; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_idx = xfer->ep_idx; if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index 6877dc131..e75430396 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -35,7 +35,6 @@ #endif -#define FSDEV_PMA_SIZE (512u) #define FSDEV_USE_SBUF_ISO 0 #define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL) #define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL) diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index ee0057cb4..37ea7808e 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -53,7 +53,6 @@ #pragma GCC diagnostic pop #endif -#define FSDEV_PMA_SIZE (512u) #define FSDEV_USE_SBUF_ISO 0 #define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL) #define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL) diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 4b7d3d301..85ca88f1c 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -32,10 +32,23 @@ #ifndef TUSB_FSDEV_STM32_H #define TUSB_FSDEV_STM32_H -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 +#if CFG_TUSB_MCU == OPT_MCU_STM32C0 + #include "stm32c0xx.h" + #define FSDEV_HAS_SBUF_ISO 1 + #define USB USB_DRD_FS + #define USB_EP_CTR_RX USB_CHEP_VTRX + #define USB_EP_CTR_TX USB_CHEP_VTTX + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #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_STM32F0 #include "stm32f0xx.h" - #define FSDEV_PMA_SIZE (1024u) - #define FSDEV_REG_BASE USB_BASE + #define FSDEV_REG_BASE USB_BASE #define FSDEV_HAS_SBUF_ISO 0 // F0x2 models are crystal-less // All have internal D+ pull-up @@ -44,29 +57,24 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 #include "stm32f1xx.h" - #define FSDEV_PMA_SIZE (512u) #define FSDEV_HAS_SBUF_ISO 0 // NO internal Pull-ups // *B, and *C: 2 x 16 bits/word // F1 names this differently from the rest - #define USB_CNTR_LPMODE USB_CNTR_LP_MODE + #define USB_CNTR_LPMODE USB_CNTR_LP_MODE -#elif defined(STM32F302xB) || defined(STM32F302xC) || \ - defined(STM32F303xB) || defined(STM32F303xC) || \ - defined(STM32F373xC) +#elif defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ + defined(STM32F373xC) #include "stm32f3xx.h" - #define FSDEV_PMA_SIZE (512u) #define FSDEV_HAS_SBUF_ISO 0 // NO internal Pull-ups // *B, and *C: 1 x 16 bits/word // PMA dedicated to USB (no sharing with CAN) -#elif defined(STM32F302x6) || defined(STM32F302x8) || \ - defined(STM32F302xD) || defined(STM32F302xE) || \ - defined(STM32F303xD) || defined(STM32F303xE) +#elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ + defined(STM32F303xD) || defined(STM32F303xE) #include "stm32f3xx.h" - #define FSDEV_PMA_SIZE (1024u) #define FSDEV_HAS_SBUF_ISO 0 // NO internal Pull-ups // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support @@ -74,28 +82,32 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32L0 #include "stm32l0xx.h" - #define FSDEV_PMA_SIZE (1024u) #define FSDEV_HAS_SBUF_ISO 0 #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 #include "stm32l1xx.h" - #define FSDEV_PMA_SIZE (512u) #define FSDEV_HAS_SBUF_ISO 0 -#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 - #include "stm32g4xx.h" - #define FSDEV_PMA_SIZE (1024u) +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + #include "stm32l4xx.h" #define FSDEV_HAS_SBUF_ISO 0 +#elif CFG_TUSB_MCU == OPT_MCU_STM32L5 + #include "stm32l5xx.h" + #define FSDEV_HAS_SBUF_ISO 0 + + #ifndef USB_PMAADDR + #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) + #endif + #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #include "stm32g0xx.h" - #define FSDEV_PMA_SIZE (2048u) - #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS + #define FSDEV_HAS_SBUF_ISO 1 + #define USB USB_DRD_FS - #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_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 @@ -110,78 +122,20 @@ #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 + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN -#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - #include "stm32c0xx.h" - #define FSDEV_PMA_SIZE (2048u) - #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS - #define USB_EP_CTR_RX USB_CHEP_VTRX - #define USB_EP_CTR_TX USB_CHEP_VTTX - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #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_STM32G4 + #include "stm32g4xx.h" + #define FSDEV_HAS_SBUF_ISO 0 #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 #include "stm32h5xx.h" - #define FSDEV_PMA_SIZE (2048u) - #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS - - #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_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN - -#elif CFG_TUSB_MCU == OPT_MCU_STM32WB - #include "stm32wbxx.h" - #define FSDEV_PMA_SIZE (1024u) - #define FSDEV_HAS_SBUF_ISO 0 - /* ST provided header has incorrect value of USB_PMAADDR */ - #define FSDEV_PMA_BASE USB1_PMAADDR - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - #define FSDEV_PMA_SIZE (1024u) - #define FSDEV_HAS_SBUF_ISO 0 - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L5 - #include "stm32l5xx.h" - #define FSDEV_PMA_SIZE (1024u) - #define FSDEV_HAS_SBUF_ISO 0 - - #ifndef USB_PMAADDR - #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) - #endif - -#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #include "stm32u5xx.h" - #define FSDEV_PMA_SIZE (2048u) #define FSDEV_HAS_SBUF_ISO 1 - #define USB USB_DRD_FS + #define USB USB_DRD_FS - #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_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 @@ -200,7 +154,6 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 #include "stm32u0xx.h" - #define FSDEV_PMA_SIZE (1024u) #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS @@ -226,10 +179,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 #include "stm32u3xx.h" - #define FSDEV_PMA_SIZE (2048u) #define FSDEV_BUS_32BIT #define FSDEV_HAS_SBUF_ISO 1 // This is assumed to work but has not been tested... - #define USB USB_DRD_FS + #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX @@ -240,15 +192,45 @@ #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_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 + #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_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_STM32U5 + #include "stm32u5xx.h" + #define FSDEV_HAS_SBUF_ISO 1 + #define USB USB_DRD_FS + + #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_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32WB + #include "stm32wbxx.h" + #define FSDEV_HAS_SBUF_ISO 0 + /* ST provided header has incorrect value of USB_PMAADDR */ + #define FSDEV_PMA_BASE USB1_PMAADDR #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 8c97eaa2f..02523d0d2 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_access_mode(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes, true); + tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,7 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, true); + tu_fifo_write_from_hwfifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; diff --git a/src/tusb_option.h b/src/tusb_option.h index a0f4e7057..6129a9532 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -307,13 +307,14 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address #endif #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUH_EDPT_DEDICATED_HWFIFO 1 #endif + + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address #endif //------------- ChipIdea -------------// @@ -354,6 +355,17 @@ //------------ FSDEV --------------// #if defined(TUP_USBIP_FSDEV) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + + #if FSDEV_PMA_SIZE == 512 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #elif FSDEV_PMA_SIZE == 1024 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 2 // 16-bit address increase + #elif FSDEV_PMA_SIZE == 2048 + #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32-bit data + #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #endif #endif //------------ MUSB --------------// diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index ea20c5f72..bf7cb5115 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -128,6 +128,7 @@ :defines: :test: - _UNITY_TEST_ + - CFG_TUD_EDPT_DEDICATED_HWFIFO=1 - CFG_TUSB_FIFO_ACCESS_DATA_STRIDE=4 - CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE=0 :release: [] -- cgit v1.3.1 From 9b5c7761cc6ea816cf35f330cb269030256be7ca Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 17:45:20 +0700 Subject: add separate tu_hwifo_*() with data from buffer/software fifo. Remove duplicated packet write/read for fsdev --- src/common/tusb_fifo.c | 43 ++++++----- src/common/tusb_fifo.h | 26 +++++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 16 ++-- src/portable/st/stm32_fsdev/fsdev_common.c | 106 -------------------------- src/portable/st/stm32_fsdev/fsdev_common.h | 6 -- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +- 6 files changed, 53 insertions(+), 148 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index bc4ee180c..a46bee955 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -128,14 +128,15 @@ enum { STRIDE_REMAIN_MASK = sizeof(stride_item_t) - 1u }; -// Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, uint16_t len) { - // Reading full available 16/32-bit src and write to fifo +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { + const volatile stride_item_t *src = (const volatile stride_item_t *)hwfifo; + + // Reading full available 16/32-bit hwfifo and write to fifo uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; while (n_items--) { const stride_item_t tmp = *src; - stride_unaligned_write(ff_buf, tmp); - ff_buf += sizeof(stride_item_t); + stride_unaligned_write(dest, tmp); + dest += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE src = (const volatile stride_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); @@ -146,17 +147,19 @@ static void ff_push_stride(uint8_t *ff_buf, const volatile stride_item_t *src, u const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { const stride_item_t tmp = *src; - memcpy(ff_buf, &tmp, bytes_rem); + memcpy(dest, &tmp, bytes_rem); } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, uint16_t len) { +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { + volatile stride_item_t *dest = (volatile stride_item_t *)hwfifo; + // Write full available 16/32 bit words to dest uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; while (n_items--) { - *dest = stride_unaligned_read(ff_buf); - ff_buf += sizeof(stride_item_t); + *dest = stride_unaligned_read(src); + src += sizeof(stride_item_t); #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE dest = (volatile stride_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); @@ -167,7 +170,7 @@ static void ff_pull_stride(volatile stride_item_t *dest, const uint8_t *ff_buf, const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; if (bytes_rem) { stride_item_t tmp = 0u; - memcpy(&tmp, ff_buf, bytes_rem); + memcpy(&tmp, src, bytes_rem); *dest = tmp; } } @@ -182,23 +185,23 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { - const volatile stride_item_t *stride_src = (const volatile stride_item_t *)app_buf; + const volatile stride_item_t *hwfifo = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case - ff_push_stride(ff_buf, stride_src, n); + tu_hwfifo_read(hwfifo, ff_buf, n); } else { // Wrap around case // Write full words to linear part of buffer uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; - ff_push_stride(ff_buf, stride_src, lin_nitems_bytes); + tu_hwfifo_read(hwfifo, ff_buf, lin_nitems_bytes); ff_buf += lin_nitems_bytes; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); - const stride_item_t tmp = *stride_src; + const stride_item_t tmp = *hwfifo; tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); wrap_bytes -= remrem; @@ -209,7 +212,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 // Write data wrapped part if (wrap_bytes > 0) { - ff_push_stride(ff_buf, stride_src, wrap_bytes); + tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes); } } } else @@ -236,17 +239,17 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd #if CFG_TUD_EDPT_DEDICATED_HWFIFO if (stride_mode) { - volatile stride_item_t *stride_dst = (volatile stride_item_t *)app_buf; + volatile stride_item_t *hwfifo = (volatile stride_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case - ff_pull_stride(stride_dst, ff_buf, n); + tu_hwfifo_write(hwfifo, ff_buf, n); } else { // Wrap around case // Read full words from linear part uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; - ff_pull_stride(stride_dst, ff_buf, lin_nitems_bytes); + tu_hwfifo_write(hwfifo, ff_buf, lin_nitems_bytes); ff_buf += lin_nitems_bytes; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -255,7 +258,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); const stride_item_t scatter = (stride_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); - *stride_dst = scatter; + *hwfifo = scatter; wrap_bytes -= remrem; ff_buf = f->buffer + remrem; // wrap around @@ -265,7 +268,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd // Read data wrapped part if (wrap_bytes > 0) { - ff_pull_stride(stride_dst, ff_buf, wrap_bytes); + tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes); } } } else diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 53c5f6e56..f28f54749 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -204,9 +204,6 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { return tu_fifo_read_n_access_mode(f, buffer, n, false); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_to_hwfifo(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, true); -} // discard first n items from fifo i.e advance read pointer by n with mutex // return number of discarded items @@ -220,10 +217,29 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { return tu_fifo_write_n_access_mode(f, data, n, false); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_from_hwfifo(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, true); + +//--------------------------------------------------------------------+ +// Hardware FIFO API +// Special hardware FIFO/Buffer to hold USB data, usually requires certain access method these can be configured with +// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE (data width) and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE (address increment) +// Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) +//--------------------------------------------------------------------+ +#if CFG_TUD_EDPT_DEDICATED_HWFIFO +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { + return tu_fifo_read_n_access_mode(f, hwfifo, n, true); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(tu_fifo_t *f, const void *hwfifo, uint16_t n) { + return tu_fifo_write_n_access_mode(f, hwfifo, n, true); +} + +// read from hwfifo to buffer +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len); + +// write to hwfifo from buffer +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len); +#endif + //--------------------------------------------------------------------+ // Internal Helper Local // work on local copies of read/write indices in order to only access them once for re-entrancy diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0c6f58cfb..cc2626383 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -321,13 +321,12 @@ static void handle_ctr_rx(uint32_t ep_id) { } const uint16_t rx_count = btable_get_count(ep_id, buf_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); if (xfer->ff) { - // fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); - tu_fifo_write_from_hwfifo(xfer->ff, (void *)pma_buf, rx_count); + tu_hwfifo_read_to_fifo(xfer->ff, (void *)pma_buf, rx_count); } else { - fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); + tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count); } xfer->queued_len += rx_count; @@ -719,14 +718,13 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } else { buf_id = BTABLE_BUF_TX; } - uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); + uint16_t addr_ptr = (uint16_t)btable_get_addr(ep_ix, buf_id); + fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); if (xfer->ff) { - // fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len); - fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); - tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); + tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); } else { - fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len); } xfer->queued_len += len; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 5d60ad9a2..19f36b492 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -136,112 +136,6 @@ bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbyte return true; } -// Write to PMA from FIFO -bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { - if (wNBytes == 0) { - return true; - } - - // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - tu_fifo_buffer_info_t info; - tu_fifo_get_read_info(ff, &info); - - uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len); - uint16_t const cnt_total = cnt_lin + cnt_wrap; - - // 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 aligned - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t const *src8 = (uint8_t const*) info.linear.ptr; - - // write even linear part - fsdev_write_packet_memory(dst, src8, lin_even); - dst += lin_even; - src8 += lin_even; - - if (lin_odd == 0) { - src8 = (uint8_t const*) info.wrapped.ptr; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp = 0; - uint16_t i; - for(i = 0; i < lin_odd; i++) { - temp |= *src8++ << (i * 8); - } - - src8 = (uint8_t const*) info.wrapped.ptr; - for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - temp |= *src8++ << (i * 8); - } - - fsdev_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); - dst += FSDEV_BUS_SIZE; - } - - // write the rest of the wrapped part - fsdev_write_packet_memory(dst, src8, cnt_wrap); - - tu_fifo_advance_read_pointer(ff, cnt_total); - return true; -} - -// Read from PMA to FIFO -bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { - if (wNBytes == 0) { - return true; - } - - // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - // Check for first linear part - tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - - uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len); - uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len); - uint16_t cnt_total = cnt_lin + cnt_wrap; - - // 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 aligned - - uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); - uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); - uint8_t *dst8 = (uint8_t *) info.linear.ptr; - - // read even linear part - fsdev_read_packet_memory(dst8, src, lin_even); - dst8 += lin_even; - src += lin_even; - - if (lin_odd == 0) { - dst8 = (uint8_t *) info.wrapped.ptr; - } else { - // Combine last linear bytes + first wrapped bytes to form fsdev bus width data - fsdev_bus_t temp; - fsdev_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); - src += FSDEV_BUS_SIZE; - - uint16_t i; - for (i = 0; i < lin_odd; i++) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - - dst8 = (uint8_t *) info.wrapped.ptr; - for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - // read the rest of the wrapped part - fsdev_read_packet_memory(dst8, src, cnt_wrap); - - tu_fifo_advance_write_pointer(ff, cnt_total); - return true; -} - //--------------------------------------------------------------------+ // BTable Helper //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 0c67ee0c7..4715f438f 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -337,12 +337,6 @@ bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_ // - Uses unaligned for RAM (since M0 cannot access unaligned address) bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); -// Write to PMA from FIFO -bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); - -// Read from PMA to FIFO -bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); - #ifdef __cplusplus } #endif diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 02523d0d2..ea952dbcc 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_to_hwfifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); + tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,7 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_from_hwfifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); + tu_hwfifo_read_to_fifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; -- cgit v1.3.1 From 111247337c3911691acd7d218362460a6c0a2572 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Dec 2025 18:01:50 +0700 Subject: replace PMA buffer packet read/write by using tu_hwfifo API --- src/common/tusb_fifo.c | 6 +-- src/common/tusb_fifo.h | 4 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/stm32_fsdev/fsdev_common.c | 67 --------------------------- src/portable/st/stm32_fsdev/fsdev_common.h | 14 ------ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 16 +++---- 6 files changed, 15 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a46bee955..8be137628 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -113,7 +113,7 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // Pull & Push // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ -#if CFG_TUD_EDPT_DEDICATED_HWFIFO +#if CFG_TUSB_FIFO_HWFIFO_API #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 #define stride_unaligned_write tu_unaligned_write32 #define stride_unaligned_read tu_unaligned_read32 @@ -183,7 +183,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; -#if CFG_TUD_EDPT_DEDICATED_HWFIFO +#if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { const volatile stride_item_t *hwfifo = (const volatile stride_item_t *)app_buf; if (n <= lin_bytes) { @@ -237,7 +237,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; -#if CFG_TUD_EDPT_DEDICATED_HWFIFO +#if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { volatile stride_item_t *hwfifo = (volatile stride_item_t *)app_buf; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f28f54749..b17f6a1d6 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -41,6 +41,8 @@ extern "C" { // mutex is only needed for RTOS. For OS None, we don't get preempted #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED +#define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO) + #ifndef CFG_TUSB_FIFO_ACCESS_DATA_STRIDE #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 0 #endif @@ -224,7 +226,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const // CFG_TUSB_FIFO_ACCESS_DATA_STRIDE (data width) and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ -#if CFG_TUD_EDPT_DEDICATED_HWFIFO TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { return tu_fifo_read_n_access_mode(f, hwfifo, n, true); } @@ -233,6 +234,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(tu_fifo_t *f return tu_fifo_write_n_access_mode(f, hwfifo, n, true); } +#if CFG_TUSB_FIFO_HWFIFO_API // read from hwfifo to buffer void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len); diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cc2626383..dae921049 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -285,7 +285,7 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - fsdev_read_packet_memory(setup_packet, rx_addr, rx_count); + tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c index 19f36b492..4f127ae86 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.c +++ b/src/portable/st/stm32_fsdev/fsdev_common.c @@ -69,73 +69,6 @@ void fsdev_deinit(void) { } } - -//--------------------------------------------------------------------+ -// PMA read/write -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - if (nbytes == 0) { - return true; - } - uint32_t n_write = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); - const uint8_t *src8 = src; - - while (n_write--) { - pma_buf->value = fsdevbus_unaligned_read(src8); - src8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = 0; - for(uint16_t i = 0; i < odd; i++) { - temp |= *src8++ << (i * 8); - } - pma_buf->value = temp; - } - - return true; -} - -// Read from packet memory area (PMA) to user memory. -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - if (nbytes == 0) { - return true; - } - uint32_t n_read = nbytes / FSDEV_BUS_SIZE; - - fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); - uint8_t *dst8 = (uint8_t *)dst; - - while (n_read--) { - fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); - dst8 += FSDEV_BUS_SIZE; - pma_buf++; - } - - // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); - if (odd) { - fsdev_bus_t temp = pma_buf->value; - while (odd--) { - *dst8++ = (uint8_t) (temp & 0xfful); - temp >>= 8; - } - } - - return true; -} - //--------------------------------------------------------------------+ // BTable Helper //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 4715f438f..69440aa32 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -323,20 +323,6 @@ uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_bloc // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); -//--------------------------------------------------------------------+ -// PMA (Packet Memory Area) Access -//--------------------------------------------------------------------+ - -// Write to packet memory area (PMA) from user memory -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); - -// Read from packet memory area (PMA) to user memory. -// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT -// - Uses unaligned for RAM (since M0 cannot access unaligned address) -bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); - #ifdef __cplusplus } #endif diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index da9c6961c..480e460cb 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -303,10 +303,12 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos; uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0)); - if (ep_id == TUSB_INDEX_INVALID_8) return; + if (ep_id == TUSB_INDEX_INVALID_8) { + return; + } - hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - hcd_channel_t* channel = &_hcd_data.channel[ch_id]; + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + hcd_channel_t *channel = &_hcd_data.channel[ch_id]; if (dir == TUSB_DIR_OUT) { // OUT/TX direction @@ -314,7 +316,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // More data to send uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); @@ -329,8 +331,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // IN/RX direction uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - - fsdev_read_packet_memory(edpt->buffer + edpt->queued_len, pma_addr, rx_count); + tu_hwfifo_read(PMA_BUF_AT(pma_addr), edpt->buffer + edpt->queued_len, rx_count); edpt->queued_len += rx_count; if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) { @@ -841,8 +842,7 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); - - fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; -- cgit v1.3.1 From 009750c747ff1d5a25d976de9161b974eb5f18e7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jan 2026 11:35:09 +0700 Subject: minor refactor --- src/common/tusb_fifo.c | 62 ++++++++++++++++------------------ src/common/tusb_fifo.h | 12 +++---- src/portable/renesas/rusb2/dcd_rusb2.c | 9 +++-- src/tusb_option.h | 19 ++++++----- test/unit-test/project.yml | 4 +-- 5 files changed, 55 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 8be137628..38b00d9d6 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -114,63 +114,61 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ #if CFG_TUSB_FIFO_HWFIFO_API - #if CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 4 + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 4 #define stride_unaligned_write tu_unaligned_write32 #define stride_unaligned_read tu_unaligned_read32 -typedef uint32_t stride_item_t; - #elif CFG_TUSB_FIFO_ACCESS_DATA_STRIDE == 2 +typedef uint32_t hwfifo_item_t; + #elif CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 2 #define stride_unaligned_write tu_unaligned_write16 #define stride_unaligned_read tu_unaligned_read16 -typedef uint16_t stride_item_t; +typedef uint16_t hwfifo_item_t; #endif enum { - STRIDE_REMAIN_MASK = sizeof(stride_item_t) - 1u + STRIDE_REMAIN_MASK = sizeof(hwfifo_item_t) - 1u }; void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { - const volatile stride_item_t *src = (const volatile stride_item_t *)hwfifo; + const volatile hwfifo_item_t *src = (const volatile hwfifo_item_t *)hwfifo; // Reading full available 16/32-bit hwfifo and write to fifo - uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; - while (n_items--) { - const stride_item_t tmp = *src; + while (len >= sizeof(hwfifo_item_t)) { + const hwfifo_item_t tmp = *src; stride_unaligned_write(dest, tmp); - dest += sizeof(stride_item_t); + dest += sizeof(hwfifo_item_t); + len -= sizeof(hwfifo_item_t); - #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - src = (const volatile stride_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE + src = (const volatile hwfifo_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) - const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; - if (bytes_rem) { - const stride_item_t tmp = *src; - memcpy(dest, &tmp, bytes_rem); + if (len > 0) { + const hwfifo_item_t tmp = *src; + memcpy(dest, &tmp, len); } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { - volatile stride_item_t *dest = (volatile stride_item_t *)hwfifo; + volatile hwfifo_item_t *dest = (volatile hwfifo_item_t *)hwfifo; // Write full available 16/32 bit words to dest - uint16_t n_items = len >> (CFG_TUSB_FIFO_ACCESS_DATA_STRIDE >> 1); // len / data_stride; - while (n_items--) { + while (len >= sizeof(hwfifo_item_t)) { *dest = stride_unaligned_read(src); - src += sizeof(stride_item_t); + src += sizeof(hwfifo_item_t); + len -= sizeof(hwfifo_item_t); - #if CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - dest = (volatile stride_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE + dest = (volatile hwfifo_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); #endif } // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) - const uint8_t bytes_rem = len & STRIDE_REMAIN_MASK; - if (bytes_rem) { - stride_item_t tmp = 0u; - memcpy(&tmp, src, bytes_rem); + if (len > 0) { + hwfifo_item_t tmp = 0u; + memcpy(&tmp, src, len); *dest = tmp; } } @@ -185,7 +183,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 #if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { - const volatile stride_item_t *hwfifo = (const volatile stride_item_t *)app_buf; + const volatile hwfifo_item_t *hwfifo = (const volatile hwfifo_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case tu_hwfifo_read(hwfifo, ff_buf, n); @@ -200,8 +198,8 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); - const stride_item_t tmp = *hwfifo; + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(hwfifo_item_t) - rem); + const hwfifo_item_t tmp = *hwfifo; tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); wrap_bytes -= remrem; @@ -239,7 +237,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd #if CFG_TUSB_FIFO_HWFIFO_API if (stride_mode) { - volatile stride_item_t *hwfifo = (volatile stride_item_t *)app_buf; + volatile hwfifo_item_t *hwfifo = (volatile hwfifo_item_t *)app_buf; if (n <= lin_bytes) { // Linear only case @@ -255,8 +253,8 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(stride_item_t) - rem); - const stride_item_t scatter = (stride_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(hwfifo_item_t) - rem); + const hwfifo_item_t scatter = (hwfifo_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); *hwfifo = scatter; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b17f6a1d6..2473a5605 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -43,12 +43,12 @@ extern "C" { #define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO) -#ifndef CFG_TUSB_FIFO_ACCESS_DATA_STRIDE - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 0 +#ifndef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 0 #endif -#ifndef CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 +#ifndef CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #endif // Due to the use of unmasked pointers, this FIFO does not suffer from losing @@ -153,7 +153,7 @@ typedef struct { // Moving data from tusb_fifo <-> USB hardware FIFOs e.g. STM32s need to use a special stride mode which reads/writes // data in 2/4 byte chunks from/to a fixed address (USB FIFO register) instead of incrementing the address. For this use // read/write access_mode with stride_mode = true. The STRIPE DATA and ADDR stride must be configured with -// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE +// CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE //--------------------------------------------------------------------+ // Setup API @@ -223,7 +223,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ // Hardware FIFO API // Special hardware FIFO/Buffer to hold USB data, usually requires certain access method these can be configured with -// CFG_TUSB_FIFO_ACCESS_DATA_STRIDE (data width) and CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE (address increment) +// CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (data width) and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 779c7bc3d..63a6352ac 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -899,7 +899,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ { (void) is_isr; // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); rusb2_reg_t* rusb = RUSB2_REG(rhport); dcd_int_disable(rhport); @@ -912,7 +911,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr); - if (!ctr) return; + if (!ctr) { + return; + } dcd_int_disable(rhport); const uint32_t pid = *ctr & 0x3; *ctr = pid | RUSB2_PIPE_CTR_PID_STALL; @@ -924,7 +925,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { rusb2_reg_t * rusb = RUSB2_REG(rhport); volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr); - if (!ctr) return; + if (!ctr) { + return; + } dcd_int_disable(rhport); *ctr = RUSB2_PIPE_CTR_SQCLR_Msk; diff --git a/src/tusb_option.h b/src/tusb_option.h index 6129a9532..e22cb7525 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -313,8 +313,8 @@ #define CFG_TUH_EDPT_DEDICATED_HWFIFO 1 #endif - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32bit access - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 0 // fixed hwfifo address + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32bit access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo address #endif //------------- ChipIdea -------------// @@ -357,14 +357,14 @@ #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 #if FSDEV_PMA_SIZE == 512 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #elif FSDEV_PMA_SIZE == 1024 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 2 // 16-bit address increase + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 2 // 16-bit address increase #elif FSDEV_PMA_SIZE == 2048 - #define CFG_TUSB_FIFO_ACCESS_DATA_STRIDE 4 // 32-bit data - #define CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE 4 // 32-bit address increase + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #endif #endif @@ -376,6 +376,9 @@ //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE // support odd byte access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #endif //-------------------------------------------------------------------- diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index bf7cb5115..186eacbf0 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -129,8 +129,8 @@ :test: - _UNITY_TEST_ - CFG_TUD_EDPT_DEDICATED_HWFIFO=1 - - CFG_TUSB_FIFO_ACCESS_DATA_STRIDE=4 - - CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE=0 + - CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE=4 + - CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE=0 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. -- cgit v1.3.1 From 9ab605ef0b7402e72f9540d4b54af607d60cfd7a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jan 2026 12:51:05 +0700 Subject: change signature of tu_hwfifo_* to have hwfifo as first parameter --- src/common/tusb_fifo.c | 8 ++++++++ src/common/tusb_fifo.h | 10 ++++++---- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 38b00d9d6..828240b6c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -167,9 +167,17 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) if (len > 0) { + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE + // odd byte access, write byte per byte e.g for rusb2. No address stride needed + volatile uint8_t *dest8 = (volatile uint8_t *)dest; + for (uint16_t i = 0; i < len; ++i) { + *dest8 = src[i]; + } + #else hwfifo_item_t tmp = 0u; memcpy(&tmp, src, len); *dest = tmp; + #endif } } #endif diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 2473a5605..e1ea1126c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -226,12 +226,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const // CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (data width) and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(tu_fifo_t *f, void *hwfifo, uint16_t n) { - return tu_fifo_read_n_access_mode(f, hwfifo, n, true); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, + uint16_t n) { + return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, true); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(tu_fifo_t *f, const void *hwfifo, uint16_t n) { - return tu_fifo_write_n_access_mode(f, hwfifo, n, true); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, + uint16_t n) { + return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, true); } #if CFG_TUSB_FIFO_HWFIFO_API diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dae921049..fe4f649da 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -324,7 +324,7 @@ static void handle_ctr_rx(uint32_t ep_id) { fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); if (xfer->ff) { - tu_hwfifo_read_to_fifo(xfer->ff, (void *)pma_buf, rx_count); + tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count); } else { tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count); } @@ -722,7 +722,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); if (xfer->ff) { - tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)pma_buf, len); + tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len); } else { tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len); } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ea952dbcc..b44b8b56e 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -367,7 +367,7 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_hwfifo_write_from_fifo(xfer->ff, (void *)(uintptr_t)tx_fifo, xact_bytes); + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes); total_bytes_written += xact_bytes; } else { dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); @@ -889,7 +889,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_hwfifo_read_to_fifo(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count); + tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; -- cgit v1.3.1 From 0b638c5d74ed112535556e47e42a088267bbc527 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jan 2026 12:57:24 +0700 Subject: rusb2 use tu_hwfifo API to write usb packet --- src/common/tusb_fifo.c | 18 +++++--- src/portable/renesas/rusb2/dcd_rusb2.c | 82 +++++++++++++++++++--------------- src/tusb_option.h | 8 ++-- 3 files changed, 63 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 828240b6c..fe17f1f2b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -139,14 +139,22 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { len -= sizeof(hwfifo_item_t); #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE - src = (const volatile hwfifo_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + src = (const volatile hwfifo_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE); #endif } - // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) + // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT + // odd byte access, read byte per byte e.g for rusb2. No address stride needed + const volatile uint8_t *src8 = (const volatile uint8_t *)src; + for (uint16_t i = 0; i < len; ++i) { + dest[i] = *src8; + } + #else const hwfifo_item_t tmp = *src; memcpy(dest, &tmp, len); + #endif } } @@ -161,13 +169,13 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { len -= sizeof(hwfifo_item_t); #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE - dest = (volatile hwfifo_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_ACCESS_ADDR_STRIDE); + dest = (volatile hwfifo_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE); #endif } - // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit) + // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // odd byte access, write byte per byte e.g for rusb2. No address stride needed volatile uint8_t *dest8 = (volatile uint8_t *)dest; for (uint16_t i = 0; i < len; ++i) { diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 63a6352ac..6c6406dcf 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -163,7 +163,7 @@ static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) { //--------------------------------------------------------------------+ // Pipe FIFO //--------------------------------------------------------------------+ - +#if 0 // Write data buffer --> hw fifo static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) { @@ -196,18 +196,6 @@ static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo } } -// Read data buffer <-- hw fifo -static void pipe_read_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) -{ - (void) rusb; - - // TODO 16/32-bit access for better performance - - uint8_t *p = (uint8_t*)buf; - volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */ - while (len--) *p++ = *reg; -} - // Write data sw fifo --> hw fifo static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { tu_fifo_buffer_info_t info; @@ -235,8 +223,21 @@ static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_advance_read_pointer(f, cnt_written); } +// Read data buffer <-- hw fifo +static void pipe_read_packet(rusb2_reg_t *rusb, void *buf, volatile void *fifo, unsigned len) { + (void)rusb; + + // TODO 16/32-bit access for better performance + + uint8_t *p = (uint8_t *)buf; + volatile uint8_t *reg = (volatile uint8_t *)fifo; /* byte access is always at base register address */ + while (len--) { + *p++ = *reg; + } +} + // Read data sw fifo <-- hw fifo -static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { +static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { tu_fifo_buffer_info_t info; tu_fifo_get_write_info(f, &info); @@ -252,15 +253,15 @@ static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_advance_write_pointer(f, count); } + #endif //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ -static bool pipe0_xfer_in(rusb2_reg_t* rusb) -{ - pipe_state_t *pipe = &_dcd.pipe[0]; - const unsigned rem = pipe->remaining; +static bool pipe0_xfer_in(rusb2_reg_t *rusb) { + pipe_state_t *pipe = &_dcd.pipe[0]; + const unsigned rem = pipe->remaining; if (!rem) { pipe->buf = NULL; @@ -273,10 +274,13 @@ static bool pipe0_xfer_in(rusb2_reg_t* rusb) if (len) { if (pipe->ff) { - pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); + // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); } else { - pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); - pipe->buf = (uint8_t*)buf + len; + // pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); + // TODO check highspeed for 32-bit access + tu_hwfifo_write(&rusb->CFIFO, buf, len); + pipe->buf = (uint8_t *)buf + len; } } @@ -288,10 +292,9 @@ static bool pipe0_xfer_in(rusb2_reg_t* rusb) return false; } -static bool pipe0_xfer_out(rusb2_reg_t* rusb) -{ - pipe_state_t *pipe = &_dcd.pipe[0]; - const unsigned rem = pipe->remaining; +static bool pipe0_xfer_out(rusb2_reg_t *rusb) { + pipe_state_t *pipe = &_dcd.pipe[0]; + const unsigned rem = pipe->remaining; const uint16_t mps = edpt0_max_packet_size(rusb); const uint16_t vld = rusb->CFIFOCTR_b.DTLN; @@ -300,10 +303,12 @@ static bool pipe0_xfer_out(rusb2_reg_t* rusb) if (len) { if (pipe->ff) { - pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); + // pipe_read_packet_ff(rusb, (tu_fifo_t *)buf, (volatile void *)&rusb->CFIFO, len); + tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); } else { - pipe_read_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); - pipe->buf = (uint8_t*)buf + len; + // pipe_read_packet(rusb, buf, (volatile void *)&rusb->CFIFO, len); + tu_hwfifo_read(&rusb->CFIFO, buf, len); + pipe->buf = (uint8_t *)buf + len; } } @@ -338,9 +343,12 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num) if (len) { if (pipe->ff) { - pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); } else { - pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + // TODO check highspeed for 32-bit access + tu_hwfifo_write(&rusb->D0FIFO, buf, len); pipe->buf = (uint8_t*)buf + len; } } @@ -362,7 +370,7 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) pipe_state_t *pipe = &_dcd.pipe[num]; const uint16_t rem = pipe->remaining; - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT; + rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; const uint16_t mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); @@ -372,9 +380,11 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) if (len) { if (pipe->ff) { - pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); } else { - pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_read(&rusb->D0FIFO, buf, len); pipe->buf = (uint8_t*)buf + len; } } @@ -431,14 +441,14 @@ static void process_status_completion(uint8_t rhport) static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes) { /* configure fifo direction and access unit settings */ - if ( ep_addr ) { + if (ep_addr != 0) { /* IN, 2 bytes */ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {} } else { - /* OUT, a byte */ - rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT; + /* OUT, 2 bytes */ + rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {} } diff --git a/src/tusb_option.h b/src/tusb_option.h index e22cb7525..8e147707a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -375,10 +375,10 @@ //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE // support odd byte access - #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // support odd byte access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #endif //-------------------------------------------------------------------- -- cgit v1.3.1 From 36e8f9d7a184ea5d8ff67331f9a12dd5c809ab30 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Jan 2026 15:55:00 +0700 Subject: support multiple data stride if configured --- src/common/tusb_common.h | 2 +- src/common/tusb_fifo.c | 181 ++++++++++++++++++++++------------------ src/common/tusb_fifo.h | 32 ++++--- test/unit-test/project.yml | 2 +- test/unit-test/test/test_fifo.c | 88 ++++++++++++++++++- 5 files changed, 207 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index d74760608..17cd26cd9 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -348,7 +348,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_scatter_read32(const uint8_t *bu return result; } -// scatter write 4 bytes to two buffers. Parameter are not checked +// scatter write 4 bytes (LE) to two buffers. Parameter are not checked TU_ATTR_ALWAYS_INLINE static inline void tu_scatter_write32(uint32_t value, uint8_t *buf1, uint8_t len1, uint8_t *buf2, uint8_t len2) { for (uint8_t i = 0; i < len1; ++i) { diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index fe17f1f2b..5749f3a68 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -114,119 +114,136 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ #if CFG_TUSB_FIFO_HWFIFO_API - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 4 - #define stride_unaligned_write tu_unaligned_write32 - #define stride_unaligned_read tu_unaligned_read32 -typedef uint32_t hwfifo_item_t; - #elif CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE == 2 - #define stride_unaligned_write tu_unaligned_write16 - #define stride_unaligned_read tu_unaligned_read16 -typedef uint16_t hwfifo_item_t; + + #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE + #define HWFIFO_ADDR_NEXT(_const, _hwfifo) \ + _hwfifo = (_const volatile void *)((uintptr_t)(_hwfifo) + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE) + #else + #define HWFIFO_ADDR_NEXT(_const, _hwfifo) #endif -enum { - STRIDE_REMAIN_MASK = sizeof(hwfifo_item_t) - 1u -}; +static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 + if (data_stride == 4) { + *((volatile uint32_t *)hwfifo) = tu_unaligned_read32(src); + } + #endif + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 + if (data_stride == 2) { + *((volatile uint16_t *)hwfifo) = tu_unaligned_read16(src); + } + #endif +} -void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { - const volatile hwfifo_item_t *src = (const volatile hwfifo_item_t *)hwfifo; +static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 + if (data_stride == 4) { + tu_unaligned_write32(dest, *((const volatile uint32_t *)hwfifo)); + } + #endif + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 + if (data_stride == 2) { + tu_unaligned_write16(dest, *((const volatile uint16_t *)hwfifo)); + } + #endif +} +void tu_hwfifo_read_access_mode(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride) { // Reading full available 16/32-bit hwfifo and write to fifo - while (len >= sizeof(hwfifo_item_t)) { - const hwfifo_item_t tmp = *src; - stride_unaligned_write(dest, tmp); - dest += sizeof(hwfifo_item_t); - len -= sizeof(hwfifo_item_t); + while (len >= data_stride) { + stride_read(hwfifo, dest, data_stride); + dest += data_stride; + len -= data_stride; - #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE - src = (const volatile hwfifo_item_t *)((uintptr_t)src + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE); - #endif + HWFIFO_ADDR_NEXT(const, hwfifo); } // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // odd byte access, read byte per byte e.g for rusb2. No address stride needed - const volatile uint8_t *src8 = (const volatile uint8_t *)src; + const volatile uint8_t *src8 = (const volatile uint8_t *)hwfifo; for (uint16_t i = 0; i < len; ++i) { - dest[i] = *src8; + dest[i] = *(src8 + 3); } #else - const hwfifo_item_t tmp = *src; + uint32_t tmp; + stride_read(hwfifo, &tmp, data_stride); memcpy(dest, &tmp, len); #endif } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { - volatile hwfifo_item_t *dest = (volatile hwfifo_item_t *)hwfifo; - +void tu_hwfifo_write_access_mode(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride) { // Write full available 16/32 bit words to dest - while (len >= sizeof(hwfifo_item_t)) { - *dest = stride_unaligned_read(src); - src += sizeof(hwfifo_item_t); - len -= sizeof(hwfifo_item_t); + while (len >= data_stride) { + stride_write(hwfifo, src, data_stride); + src += data_stride; + len -= data_stride; - #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE - dest = (volatile hwfifo_item_t *)((uintptr_t)dest + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE); - #endif + HWFIFO_ADDR_NEXT(, hwfifo); } // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // odd byte access, write byte per byte e.g for rusb2. No address stride needed - volatile uint8_t *dest8 = (volatile uint8_t *)dest; + volatile uint8_t *dest8 = (volatile uint8_t *)hwfifo; for (uint16_t i = 0; i < len; ++i) { - *dest8 = src[i]; + *(dest8 + 3) = src[i]; } #else - hwfifo_item_t tmp = 0u; + uint32_t tmp = 0u; memcpy(&tmp, src, len); - *dest = tmp; + stride_write(hwfifo, &tmp, data_stride); #endif } } #endif // send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, bool stride_mode) { - (void)stride_mode; +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride) { + (void)data_stride; uint16_t lin_bytes = f->depth - wr_ptr; uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; #if CFG_TUSB_FIFO_HWFIFO_API - if (stride_mode) { - const volatile hwfifo_item_t *hwfifo = (const volatile hwfifo_item_t *)app_buf; + if (data_stride) { + const volatile void *hwfifo = (const volatile void *)app_buf; if (n <= lin_bytes) { // Linear only case - tu_hwfifo_read(hwfifo, ff_buf, n); + tu_hwfifo_read_access_mode(hwfifo, ff_buf, n, data_stride); } else { // Wrap around case // Write full words to linear part of buffer - uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; - tu_hwfifo_read(hwfifo, ff_buf, lin_nitems_bytes); - ff_buf += lin_nitems_bytes; + const uint32_t odd_mask = data_stride - 1; + uint16_t lin_even = lin_bytes & ~odd_mask; + tu_hwfifo_read_access_mode(hwfifo, ff_buf, lin_even, data_stride); + ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; - if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(hwfifo_item_t) - rem); - const hwfifo_item_t tmp = *hwfifo; - tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); - - wrap_bytes -= remrem; - ff_buf = f->buffer + remrem; // wrap around + // combine it with the wrapped part to form a full word for data stride + const uint8_t lin_odd = lin_bytes & odd_mask; + if (lin_odd > 0) { + const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); + uint32_t tmp = 0; + stride_read(hwfifo, &tmp, data_stride); + HWFIFO_ADDR_NEXT(const, hwfifo); + + tu_scatter_write32(tmp, ff_buf, lin_odd, f->buffer, wrap_odd); + + wrap_bytes -= wrap_odd; + ff_buf = f->buffer + wrap_odd; // wrap around } else { - ff_buf = f->buffer; // wrap around to beginning + ff_buf = f->buffer; // wrap around to beginning } // Write data wrapped part if (wrap_bytes > 0) { - tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes); + tu_hwfifo_read_access_mode(hwfifo, ff_buf, wrap_bytes, data_stride); } } } else @@ -245,44 +262,46 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1 } // get n items from fifo WITHOUT updating read pointer -static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, bool stride_mode) { - (void)stride_mode; +static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, uint8_t data_stride) { + (void)data_stride; uint16_t lin_bytes = f->depth - rd_ptr; uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; #if CFG_TUSB_FIFO_HWFIFO_API - if (stride_mode) { - volatile hwfifo_item_t *hwfifo = (volatile hwfifo_item_t *)app_buf; + if (data_stride) { + volatile void *hwfifo = (volatile void *)app_buf; if (n <= lin_bytes) { // Linear only case - tu_hwfifo_write(hwfifo, ff_buf, n); + tu_hwfifo_write_access_mode(hwfifo, ff_buf, n, data_stride); } else { // Wrap around case // Read full words from linear part - uint16_t lin_nitems_bytes = lin_bytes & ~STRIDE_REMAIN_MASK; - tu_hwfifo_write(hwfifo, ff_buf, lin_nitems_bytes); - ff_buf += lin_nitems_bytes; + const uint32_t odd_mask = data_stride - 1; + uint16_t lin_even = lin_bytes & ~odd_mask; + tu_hwfifo_write_access_mode(hwfifo, ff_buf, lin_even, data_stride); + ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & STRIDE_REMAIN_MASK; - if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(hwfifo_item_t) - rem); - const hwfifo_item_t scatter = (hwfifo_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem); + const uint8_t lin_odd = lin_bytes & odd_mask; + if (lin_odd > 0) { + const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); + const uint32_t scatter = tu_scatter_read32(ff_buf, lin_odd, f->buffer, wrap_odd); - *hwfifo = scatter; + stride_write(hwfifo, &scatter, data_stride); + HWFIFO_ADDR_NEXT(, hwfifo); - wrap_bytes -= remrem; - ff_buf = f->buffer + remrem; // wrap around + wrap_bytes -= wrap_odd; + ff_buf = f->buffer + wrap_odd; // wrap around } else { - ff_buf = f->buffer; // wrap around to beginning + ff_buf = f->buffer; // wrap around to beginning } // Read data wrapped part if (wrap_bytes > 0) { - tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes); + tu_hwfifo_write_access_mode(hwfifo, ff_buf, wrap_bytes, data_stride); } } } else @@ -349,7 +368,7 @@ static uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { // Works on local copies of w and r // Must be protected by read mutex since in case of an overflow read pointer gets modified uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - bool stride_mode) { + uint8_t data_stride) { uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); if (count == 0) { return 0; // nothing to peek @@ -366,7 +385,7 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - ff_pull_n(f, p_buffer, n, rd_ptr, stride_mode); + ff_pull_n(f, p_buffer, n, rd_ptr, data_stride); return n; } @@ -374,17 +393,17 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui // Read n items without removing it from the FIFO, correct read pointer if overflowed uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { ff_lock(f->mutex_rd); - const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, false); + const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, 0); ff_unlock(f->mutex_rd); return ret; } // Read n items from fifo with access mode -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, bool stride_mode) { +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint8_t data_stride) { ff_lock(f->mutex_rd); // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, stride_mode); + n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, data_stride); f->rd_idx = advance_index(f->depth, f->rd_idx, n); ff_unlock(f->mutex_rd); @@ -392,7 +411,7 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, bool } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, bool stride_mode) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride) { if (n == 0) { return 0; } @@ -418,7 +437,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (!stride_mode) { + if (!data_stride) { buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could @@ -454,7 +473,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - ff_push_n(f, buf8, n, wr_ptr, stride_mode); + ff_push_n(f, buf8, n, wr_ptr, data_stride); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index e1ea1126c..f2939aec0 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -193,7 +193,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); // peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo //--------------------------------------------------------------------+ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - bool stride_mode); + uint8_t data_stride); bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); @@ -201,10 +201,10 @@ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); // Read API // peek() + advance read index //--------------------------------------------------------------------+ -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, bool stride_mode); +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint8_t data_stride); bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, false); + return tu_fifo_read_n_access_mode(f, buffer, n, 0); } // discard first n items from fifo i.e advance read pointer by n with mutex @@ -214,10 +214,10 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, bool stride_mode); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, false); + return tu_fifo_write_n_access_mode(f, data, n, 0); } //--------------------------------------------------------------------+ @@ -228,20 +228,30 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n) { - return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, true); + return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, uint16_t n) { - return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, true); + return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); } #if CFG_TUSB_FIFO_HWFIFO_API -// read from hwfifo to buffer -void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len); +// read from hwfifo to buffer with access mode +void tu_hwfifo_read_access_mode(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride); -// write to hwfifo from buffer -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len); +// read from hwfifo to buffer with default data stride +TU_ATTR_ALWAYS_INLINE static inline void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { + tu_hwfifo_read_access_mode(hwfifo, dest, len, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); +} + +// write to hwfifo from buffer with access mode +void tu_hwfifo_write_access_mode(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride); + +// write to hwfifo from buffer with default data stride +TU_ATTR_ALWAYS_INLINE static inline void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { + tu_hwfifo_write_access_mode(hwfifo, src, len, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); +} #endif //--------------------------------------------------------------------+ diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index 186eacbf0..be3fc3de0 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -129,7 +129,7 @@ :test: - _UNITY_TEST_ - CFG_TUD_EDPT_DEDICATED_HWFIFO=1 - - CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE=4 + - CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE=6 - CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE=0 :release: [] diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index 453930a2f..6e1c13d6d 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -403,7 +403,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, true); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 4); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -425,7 +425,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, true); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 4); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -445,7 +445,7 @@ void test_read_n_fixed_addr_rw32_nowrap(void) { tu_fifo_write_n(ff, pattern, 8); uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, true); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 4); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(8 - n, tu_fifo_count(ff)); @@ -469,7 +469,7 @@ void test_read_n_fixed_addr_rw32_wrapped(void) { } uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, true); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 4); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); @@ -477,6 +477,86 @@ void test_read_n_fixed_addr_rw32_wrapped(void) { } } +void test_write_n_fixed_addr_rw16_nowrap(void) { + tu_fifo_clear(ff); + + volatile uint16_t reg = 0x1122; + uint8_t expected[6] = {0x22, 0x11, 0x22, 0x11, 0x22, 0x11}; + + for (uint8_t n = 1; n <= 6; n++) { + tu_fifo_clear(ff); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 2); + TEST_ASSERT_EQUAL(n, written); + TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); + + uint8_t out[6] = {0}; + tu_fifo_read_n(ff, out, n); + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, out, n); + } +} + +void test_write_n_fixed_addr_rw16_wrapped(void) { + tu_fifo_clear(ff); + + volatile uint16_t reg = 0xA1B2; + uint8_t expected[6] = {0xB2, 0xA1, 0xB2, 0xA1, 0xB2, 0xA1}; + + for (uint8_t n = 1; n <= 6; n++) { + tu_fifo_clear(ff); + // Position the fifo near the end so writes wrap + ff->wr_idx = FIFO_SIZE - 3; + ff->rd_idx = FIFO_SIZE - 3; + + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 2); + TEST_ASSERT_EQUAL(n, written); + TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); + + uint8_t out[6] = {0}; + tu_fifo_read_n(ff, out, n); + TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, out, n); + } +} + +void test_read_n_fixed_addr_rw16_nowrap(void) { + uint8_t pattern[6] = {0x10, 0x21, 0x32, 0x43, 0x54, 0x65}; + uint16_t reg_expected[6] = {0x0010, 0x2110, 0x0032, 0x4332, 0x0054, 0x6554}; + + for (uint8_t n = 1; n <= 6; n++) { + tu_fifo_clear(ff); + tu_fifo_write_n(ff, pattern, 6); + + uint16_t reg = 0; + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 2); + TEST_ASSERT_EQUAL(n, read_cnt); + TEST_ASSERT_EQUAL(6 - n, tu_fifo_count(ff)); + + TEST_ASSERT_EQUAL_HEX16(reg_expected[n - 1], reg); + } +} + +void test_read_n_fixed_addr_rw16_wrapped(void) { + uint8_t pattern[6] = {0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5}; + uint16_t reg_expected[6] = {0x00F0, 0xE1F0, 0x00D2, 0xC3D2, 0x00B4, 0xA5B4}; + + for (uint8_t n = 1; n <= 6; n++) { + tu_fifo_clear(ff); + ff->rd_idx = FIFO_SIZE - 1; + ff->wr_idx = (uint16_t)(ff->rd_idx + n); + + for (uint8_t i = 0; i < n; i++) { + uint8_t idx = (uint8_t)((ff->rd_idx + i) % FIFO_SIZE); + ff->buffer[idx] = pattern[i]; + } + + uint16_t reg = 0; + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 2); + TEST_ASSERT_EQUAL(n, read_cnt); + TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); + + TEST_ASSERT_EQUAL_HEX16(reg_expected[n - 1], reg); + } +} + void test_get_read_info_advanced_cases(void) { tu_fifo_clear(ff); -- cgit v1.3.1 From b87c2fcc9f68f6e0f5e8add653ee0c67d3467e02 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Jan 2026 23:57:48 +0700 Subject: refactor hwfifo pull/push --- src/common/tusb_common.h | 2 +- src/common/tusb_fifo.c | 219 ++++++++++++++++++++++++++--------------------- src/common/tusb_fifo.h | 16 +--- 3 files changed, 125 insertions(+), 112 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 17cd26cd9..6ac1405f3 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -329,7 +329,7 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_ #endif -// scatter read 4 bytes from two buffers. Parameter are not checked +// scatter read 4 bytes from two buffers (LE). Parameter are not checked TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_scatter_read32(const uint8_t *buf1, uint8_t len1, const uint8_t *buf2, uint8_t len2) { uint32_t result = 0; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 5749f3a68..5988f16d8 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -114,7 +114,6 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { // copy data to/from fifo without updating read/write pointers //--------------------------------------------------------------------+ #if CFG_TUSB_FIFO_HWFIFO_API - #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE #define HWFIFO_ADDR_NEXT(_const, _hwfifo) \ _hwfifo = (_const volatile void *)((uintptr_t)(_hwfifo) + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE) @@ -148,7 +147,7 @@ static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_st #endif } -void tu_hwfifo_read_access_mode(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride) { +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride) { // Reading full available 16/32-bit hwfifo and write to fifo while (len >= data_stride) { stride_read(hwfifo, dest, data_stride); @@ -175,7 +174,7 @@ void tu_hwfifo_read_access_mode(const volatile void *hwfifo, uint8_t *dest, uint } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -void tu_hwfifo_write_access_mode(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride) { +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride) { // Write full available 16/32 bit words to dest while (len >= data_stride) { stride_write(hwfifo, src, data_stride); @@ -200,122 +199,131 @@ void tu_hwfifo_write_access_mode(volatile void *hwfifo, const uint8_t *src, uint #endif } } -#endif -// send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride) { - (void)data_stride; +static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride) { uint16_t lin_bytes = f->depth - wr_ptr; uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; -#if CFG_TUSB_FIFO_HWFIFO_API - if (data_stride) { - const volatile void *hwfifo = (const volatile void *)app_buf; - if (n <= lin_bytes) { - // Linear only case - tu_hwfifo_read_access_mode(hwfifo, ff_buf, n, data_stride); - } else { - // Wrap around case - - // Write full words to linear part of buffer - const uint32_t odd_mask = data_stride - 1; - uint16_t lin_even = lin_bytes & ~odd_mask; - tu_hwfifo_read_access_mode(hwfifo, ff_buf, lin_even, data_stride); - ff_buf += lin_even; - - // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - // combine it with the wrapped part to form a full word for data stride - const uint8_t lin_odd = lin_bytes & odd_mask; - if (lin_odd > 0) { - const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); - uint32_t tmp = 0; - stride_read(hwfifo, &tmp, data_stride); - HWFIFO_ADDR_NEXT(const, hwfifo); - - tu_scatter_write32(tmp, ff_buf, lin_odd, f->buffer, wrap_odd); - - wrap_bytes -= wrap_odd; - ff_buf = f->buffer + wrap_odd; // wrap around - } else { - ff_buf = f->buffer; // wrap around to beginning + const volatile void *hwfifo = (const volatile void *)app_buf; + if (n <= lin_bytes) { + // Linear only case + tu_hwfifo_read(hwfifo, ff_buf, n, data_stride); + } else { + // Wrap around case + + // Write full words to linear part of buffer + const uint32_t odd_mask = data_stride - 1; + uint16_t lin_even = lin_bytes & ~odd_mask; + tu_hwfifo_read(hwfifo, ff_buf, lin_even, data_stride); + ff_buf += lin_even; + + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + // combine it with the wrapped part to form a full word for data stride + const uint8_t lin_odd = lin_bytes & odd_mask; + if (lin_odd > 0) { + const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); + uint8_t buf_temp[4]; + tu_hwfifo_read(hwfifo, buf_temp, lin_odd + wrap_odd, data_stride); + + for (uint8_t i = 0; i < lin_odd; ++i) { + ff_buf[i] = buf_temp[i]; } - - // Write data wrapped part - if (wrap_bytes > 0) { - tu_hwfifo_read_access_mode(hwfifo, ff_buf, wrap_bytes, data_stride); + for (uint8_t i = 0; i < wrap_odd; ++i) { + f->buffer[i] = buf_temp[lin_odd + i]; } - } - } else -#endif - { - // single byte access - if (n <= lin_bytes) { - // Linear only case - memcpy(ff_buf, app_buf, n); + + wrap_bytes -= wrap_odd; + ff_buf = f->buffer + wrap_odd; // wrap around } else { - // Wrap around case - memcpy(ff_buf, app_buf, lin_bytes); // linear part - memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + ff_buf = f->buffer; // wrap around to beginning + } + + // Write data wrapped part + if (wrap_bytes > 0) { + tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes, data_stride); } } } -// get n items from fifo WITHOUT updating read pointer -static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, uint8_t data_stride) { - (void)data_stride; +static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, uint8_t data_stride) { uint16_t lin_bytes = f->depth - rd_ptr; uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; -#if CFG_TUSB_FIFO_HWFIFO_API - if (data_stride) { - volatile void *hwfifo = (volatile void *)app_buf; + volatile void *hwfifo = (volatile void *)app_buf; + + if (n <= lin_bytes) { + // Linear only case + tu_hwfifo_write(hwfifo, ff_buf, n, data_stride); + } else { + // Wrap around case + + // Read full words from linear part + const uint32_t odd_mask = data_stride - 1; + uint16_t lin_even = lin_bytes & ~odd_mask; + tu_hwfifo_write(hwfifo, ff_buf, lin_even, data_stride); + ff_buf += lin_even; + + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t lin_odd = lin_bytes & odd_mask; + if (lin_odd > 0) { + const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); + + uint8_t buf_temp[4]; + for (uint8_t i = 0; i < lin_odd; ++i) { + buf_temp[i] = ff_buf[i]; + } + for (uint8_t i = 0; i < wrap_odd; ++i) { + buf_temp[lin_odd + i] = f->buffer[i]; + } + + tu_hwfifo_write(hwfifo, buf_temp, lin_odd + wrap_odd, data_stride); - if (n <= lin_bytes) { - // Linear only case - tu_hwfifo_write_access_mode(hwfifo, ff_buf, n, data_stride); + wrap_bytes -= wrap_odd; + ff_buf = f->buffer + wrap_odd; // wrap around } else { - // Wrap around case + ff_buf = f->buffer; // wrap around to beginning + } - // Read full words from linear part - const uint32_t odd_mask = data_stride - 1; - uint16_t lin_even = lin_bytes & ~odd_mask; - tu_hwfifo_write_access_mode(hwfifo, ff_buf, lin_even, data_stride); - ff_buf += lin_even; + // Read data wrapped part + if (wrap_bytes > 0) { + tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes, data_stride); + } + } +} +#endif - // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t lin_odd = lin_bytes & odd_mask; - if (lin_odd > 0) { - const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); - const uint32_t scatter = tu_scatter_read32(ff_buf, lin_odd, f->buffer, wrap_odd); +// send n items to fifo WITHOUT updating write pointer +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr) { + uint16_t lin_bytes = f->depth - wr_ptr; + uint16_t wrap_bytes = n - lin_bytes; + uint8_t *ff_buf = f->buffer + wr_ptr; - stride_write(hwfifo, &scatter, data_stride); - HWFIFO_ADDR_NEXT(, hwfifo); + if (n <= lin_bytes) { + // Linear only case + memcpy(ff_buf, app_buf, n); + } else { + // Wrap around case + memcpy(ff_buf, app_buf, lin_bytes); // linear part + memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + } +} - wrap_bytes -= wrap_odd; - ff_buf = f->buffer + wrap_odd; // wrap around - } else { - ff_buf = f->buffer; // wrap around to beginning - } +// get n items from fifo WITHOUT updating read pointer +static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr) { + uint16_t lin_bytes = f->depth - rd_ptr; + uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped + const uint8_t *ff_buf = f->buffer + rd_ptr; - // Read data wrapped part - if (wrap_bytes > 0) { - tu_hwfifo_write_access_mode(hwfifo, ff_buf, wrap_bytes, data_stride); - } - } - } else -#endif - { - // single byte access - if (n <= lin_bytes) { - // Linear only - memcpy(app_buf, ff_buf, n); - } else { - // Wrap around - memcpy(app_buf, ff_buf, lin_bytes); // linear part - memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part - } + // single byte access + if (n <= lin_bytes) { + // Linear only + memcpy(app_buf, ff_buf, n); + } else { + // Wrap around + memcpy(app_buf, ff_buf, lin_bytes); // linear part + memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part } } @@ -385,7 +393,15 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - ff_pull_n(f, p_buffer, n, rd_ptr, data_stride); + +#if CFG_TUSB_FIFO_HWFIFO_API + if (data_stride > 0) { + hwff_pull_n(f, p_buffer, n, rd_ptr, data_stride); + } else +#endif + { + ff_pull_n(f, p_buffer, n, rd_ptr); + } return n; } @@ -473,7 +489,14 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - ff_push_n(f, buf8, n, wr_ptr, data_stride); +#if CFG_TUSB_FIFO_HWFIFO_API + if (data_stride > 0) { + hwff_push_n(f, buf8, n, wr_ptr, data_stride); + } else +#endif + { + ff_push_n(f, buf8, n, wr_ptr); + } f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f2939aec0..d7e5416fd 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -129,7 +129,6 @@ typedef struct { osal_mutex_t mutex_wr; osal_mutex_t mutex_rd; #endif - } tu_fifo_t; typedef struct { @@ -237,21 +236,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volati } #if CFG_TUSB_FIFO_HWFIFO_API -// read from hwfifo to buffer with access mode -void tu_hwfifo_read_access_mode(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride); - -// read from hwfifo to buffer with default data stride -TU_ATTR_ALWAYS_INLINE static inline void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len) { - tu_hwfifo_read_access_mode(hwfifo, dest, len, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); -} +// read from hwfifo to buffer +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride); // write to hwfifo from buffer with access mode -void tu_hwfifo_write_access_mode(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride); +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride); -// write to hwfifo from buffer with default data stride -TU_ATTR_ALWAYS_INLINE static inline void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len) { - tu_hwfifo_write_access_mode(hwfifo, src, len, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); -} #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From c87f0db45978b6b1f11f151bf5c061b926dba245 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 00:34:49 +0700 Subject: add tu_hwfifo_access_t param to hwfifo API --- src/common/tusb_fifo.c | 73 ++++++++++++--------------- src/common/tusb_fifo.h | 30 ++++++----- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 13 +++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 12 +++-- src/portable/synopsys/dwc2/dwc2_common.c | 54 -------------------- src/portable/synopsys/dwc2/hcd_dwc2.c | 6 ++- test/unit-test/CMakeLists.txt | 1 - test/unit-test/test/test_fifo.c | 26 +++++++--- 8 files changed, 87 insertions(+), 128 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 5988f16d8..e34494c84 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -147,8 +147,9 @@ static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_st #endif } -void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride) { +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Reading full available 16/32-bit hwfifo and write to fifo + const uint8_t data_stride = access_mode->data_stride; while (len >= data_stride) { stride_read(hwfifo, dest, data_stride); dest += data_stride; @@ -159,23 +160,16 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, ui // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT - // odd byte access, read byte per byte e.g for rusb2. No address stride needed - const volatile uint8_t *src8 = (const volatile uint8_t *)hwfifo; - for (uint16_t i = 0; i < len; ++i) { - dest[i] = *(src8 + 3); - } - #else uint32_t tmp; stride_read(hwfifo, &tmp, data_stride); memcpy(dest, &tmp, len); - #endif } } // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride) { +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Write full available 16/32 bit words to dest + const uint8_t data_stride = access_mode->data_stride; while (len >= data_stride) { stride_write(hwfifo, src, data_stride); src += data_stride; @@ -186,21 +180,14 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, ui // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { - #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT - // odd byte access, write byte per byte e.g for rusb2. No address stride needed - volatile uint8_t *dest8 = (volatile uint8_t *)hwfifo; - for (uint16_t i = 0; i < len; ++i) { - *(dest8 + 3) = src[i]; - } - #else uint32_t tmp = 0u; memcpy(&tmp, src, len); stride_write(hwfifo, &tmp, data_stride); - #endif } } -static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride) { +static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, + const tu_hwfifo_access_t *access_mode) { uint16_t lin_bytes = f->depth - wr_ptr; uint16_t wrap_bytes = n - lin_bytes; uint8_t *ff_buf = f->buffer + wr_ptr; @@ -208,14 +195,15 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin const volatile void *hwfifo = (const volatile void *)app_buf; if (n <= lin_bytes) { // Linear only case - tu_hwfifo_read(hwfifo, ff_buf, n, data_stride); + tu_hwfifo_read(hwfifo, ff_buf, n, access_mode); } else { // Wrap around case // Write full words to linear part of buffer - const uint32_t odd_mask = data_stride - 1; - uint16_t lin_even = lin_bytes & ~odd_mask; - tu_hwfifo_read(hwfifo, ff_buf, lin_even, data_stride); + const uint8_t data_stride = access_mode->data_stride; + const uint32_t odd_mask = data_stride - 1; + uint16_t lin_even = lin_bytes & ~odd_mask; + tu_hwfifo_read(hwfifo, ff_buf, lin_even, access_mode); ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -224,7 +212,7 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin if (lin_odd > 0) { const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); uint8_t buf_temp[4]; - tu_hwfifo_read(hwfifo, buf_temp, lin_odd + wrap_odd, data_stride); + tu_hwfifo_read(hwfifo, buf_temp, lin_odd + wrap_odd, access_mode); for (uint8_t i = 0; i < lin_odd; ++i) { ff_buf[i] = buf_temp[i]; @@ -241,12 +229,13 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin // Write data wrapped part if (wrap_bytes > 0) { - tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes, data_stride); + tu_hwfifo_read(hwfifo, ff_buf, wrap_bytes, access_mode); } } } -static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, uint8_t data_stride) { +static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, + const tu_hwfifo_access_t *access_mode) { uint16_t lin_bytes = f->depth - rd_ptr; uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped const uint8_t *ff_buf = f->buffer + rd_ptr; @@ -255,14 +244,15 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t if (n <= lin_bytes) { // Linear only case - tu_hwfifo_write(hwfifo, ff_buf, n, data_stride); + tu_hwfifo_write(hwfifo, ff_buf, n, access_mode); } else { // Wrap around case // Read full words from linear part - const uint32_t odd_mask = data_stride - 1; + const uint8_t data_stride = access_mode->data_stride; + const uint32_t odd_mask = data_stride - 1; uint16_t lin_even = lin_bytes & ~odd_mask; - tu_hwfifo_write(hwfifo, ff_buf, lin_even, data_stride); + tu_hwfifo_write(hwfifo, ff_buf, lin_even, access_mode); ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -278,7 +268,7 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t buf_temp[lin_odd + i] = f->buffer[i]; } - tu_hwfifo_write(hwfifo, buf_temp, lin_odd + wrap_odd, data_stride); + tu_hwfifo_write(hwfifo, buf_temp, lin_odd + wrap_odd, access_mode); wrap_bytes -= wrap_odd; ff_buf = f->buffer + wrap_odd; // wrap around @@ -288,7 +278,7 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t // Read data wrapped part if (wrap_bytes > 0) { - tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes, data_stride); + tu_hwfifo_write(hwfifo, ff_buf, wrap_bytes, access_mode); } } } @@ -376,7 +366,7 @@ static uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { // Works on local copies of w and r // Must be protected by read mutex since in case of an overflow read pointer gets modified uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - uint8_t data_stride) { + const tu_hwfifo_access_t *access_mode) { uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); if (count == 0) { return 0; // nothing to peek @@ -395,8 +385,8 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); #if CFG_TUSB_FIFO_HWFIFO_API - if (data_stride > 0) { - hwff_pull_n(f, p_buffer, n, rd_ptr, data_stride); + if (access_mode != NULL) { + hwff_pull_n(f, p_buffer, n, rd_ptr, access_mode); } else #endif { @@ -409,17 +399,17 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui // Read n items without removing it from the FIFO, correct read pointer if overflowed uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { ff_lock(f->mutex_rd); - const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, 0); + const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, NULL); ff_unlock(f->mutex_rd); return ret; } // Read n items from fifo with access mode -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint8_t data_stride) { +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, const tu_hwfifo_access_t *access_mode) { ff_lock(f->mutex_rd); // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, data_stride); + n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); f->rd_idx = advance_index(f->depth, f->rd_idx, n); ff_unlock(f->mutex_rd); @@ -427,7 +417,8 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, + const tu_hwfifo_access_t *access_mode) { if (n == 0) { return 0; } @@ -453,7 +444,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (!data_stride) { + if (access_mode == NULL) { buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could @@ -490,8 +481,8 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); #if CFG_TUSB_FIFO_HWFIFO_API - if (data_stride > 0) { - hwff_push_n(f, buf8, n, wr_ptr, data_stride); + if (access_mode != NULL) { + hwff_push_n(f, buf8, n, wr_ptr, access_mode); } else #endif { diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index d7e5416fd..6fcc7020c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -138,6 +138,12 @@ typedef struct { } linear, wrapped; } tu_fifo_buffer_info_t; +// Access mode for hardware fifo read/write +typedef struct { + uint8_t data_stride; + uintptr_t param; +} tu_hwfifo_access_t; + #define TU_FIFO_INIT(_buffer, _depth, _overwritable) \ { \ .buffer = _buffer, \ @@ -192,7 +198,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); // peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo //--------------------------------------------------------------------+ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, - uint8_t data_stride); + const tu_hwfifo_access_t *access_mode); bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); @@ -200,10 +206,10 @@ uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); // Read API // peek() + advance read index //--------------------------------------------------------------------+ -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, uint8_t data_stride); +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, const tu_hwfifo_access_t *access_mode); bool tu_fifo_read(tu_fifo_t *f, void *buffer); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { - return tu_fifo_read_n_access_mode(f, buffer, n, 0); + return tu_fifo_read_n_access_mode(f, buffer, n, NULL); } // discard first n items from fifo i.e advance read pointer by n with mutex @@ -213,10 +219,10 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const tu_hwfifo_access_t *access_mode); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, 0); + return tu_fifo_write_n_access_mode(f, data, n, NULL); } //--------------------------------------------------------------------+ @@ -225,22 +231,22 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const // CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (data width) and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE (address increment) // Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, - uint16_t n) { - return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n, + const tu_hwfifo_access_t *access_mode) { + return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, access_mode); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, - uint16_t n) { - return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE); + uint16_t n, const tu_hwfifo_access_t *access_mode) { + return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, access_mode); } #if CFG_TUSB_FIFO_HWFIFO_API // read from hwfifo to buffer -void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, uint8_t data_stride); +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode); // write to hwfifo from buffer with access mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, uint8_t data_stride); +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode); #endif diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index fe4f649da..2832611ff 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -285,7 +285,8 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, &access_mode); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); @@ -323,10 +324,11 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count); + tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count, &access_mode); } else { - tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count); + tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count, &access_mode); } xfer->queued_len += rx_count; @@ -721,10 +723,11 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t)btable_get_addr(ep_ix, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len); + tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len, &access_mode); } else { - tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len); + tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len, &access_mode); } xfer->queued_len += len; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index b44b8b56e..2309afd53 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -365,12 +365,13 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { } // Push packet to Tx-FIFO + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; if (xfer->ff) { - volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes); + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, &access_mode); total_bytes_written += xact_bytes; } else { - dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); + tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, &access_mode); xfer->buffer += xact_bytes; total_bytes_written += xact_bytes; } @@ -888,10 +889,11 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff != NULL) { - tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count); + tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count, &access_mode); } else { - dfifo_read_packet(dwc2, xfer->buffer, byte_count); + tu_hwfifo_read(rx_fifo, xfer->buffer, byte_count, &access_mode); xfer->buffer += byte_count; } } diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 980574e12..a7e6188df 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -264,58 +264,4 @@ bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) { // // } -//-------------------------------------------------------------------- -// DFIFO -//-------------------------------------------------------------------- -// Read a single data packet from receive DFIFO -void dfifo_read_packet(dwc2_regs_t* dwc2, uint8_t* dst, uint16_t len) { - const volatile uint32_t* rx_fifo = dwc2->fifo[0]; - - // Reading full available 32 bit words from fifo - uint16_t word_count = len >> 2; - while (word_count--) { - tu_unaligned_write32(dst, *rx_fifo); - dst += 4; - } - - // Read the remaining 1-3 bytes from fifo - const uint8_t bytes_rem = len & 0x03; - if (bytes_rem != 0) { - const uint32_t tmp = *rx_fifo; - dst[0] = tu_u32_byte0(tmp); - if (bytes_rem > 1) { - dst[1] = tu_u32_byte1(tmp); - } - if (bytes_rem > 2) { - dst[2] = tu_u32_byte2(tmp); - } - } -} - -// Write a single data packet to DFIFO -void dfifo_write_packet(dwc2_regs_t* dwc2, uint8_t fifo_num, const uint8_t* src, uint16_t len) { - volatile uint32_t* tx_fifo = dwc2->fifo[fifo_num]; - - // Pushing full available 32 bit words to fifo - uint16_t word_count = len >> 2; - while (word_count--) { - *tx_fifo = tu_unaligned_read32(src); - src += 4; - } - - // Write the remaining 1-3 bytes into fifo - const uint8_t bytes_rem = len & 0x03; - if (bytes_rem) { - uint32_t tmp_word = src[0]; - if (bytes_rem > 1) { - tmp_word |= (src[1] << 8); - } - if (bytes_rem > 2) { - tmp_word |= (src[2] << 16); - } - - *tx_fifo = tmp_word; - } -} - #endif diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index fc748c85f..570b1c14c 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -856,7 +856,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; if (byte_count > 0) { - dfifo_read_packet(dwc2, edpt->buffer + xfer->xferred_bytes, byte_count); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + tu_hwfifo_read(dwc2->fifo[0], edpt->buffer + xfer->xferred_bytes, byte_count, &access_mode); xfer->xferred_bytes += byte_count; xfer->fifo_bytes = byte_count; } @@ -907,7 +908,8 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { return true; } - dfifo_write_packet(dwc2, ch_id, edpt->buffer + xfer->fifo_bytes, xact_bytes); + const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + tu_hwfifo_write(dwc2->fifo[ch_id], edpt->buffer + xfer->fifo_bytes, xact_bytes, &access_mode); xfer->fifo_bytes += xact_bytes; } } diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index 3339361db..b44a91d57 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -113,7 +113,6 @@ add_ceedling_test( ${CEEDLING_WORKDIR}/../../src/common/tusb_fifo.c "" ) -target_compile_definitions(test_fifo PRIVATE CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32) add_ceedling_test( test_usbd diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index 6e1c13d6d..b9279cb25 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -40,6 +40,16 @@ tu_fifo_buffer_info_t info; uint8_t test_data[4096]; uint8_t rd_buf[FIFO_SIZE]; +static const tu_hwfifo_access_t hwfifo_access_32 = { + .data_stride = 4, + .param = 0, +}; + +static const tu_hwfifo_access_t hwfifo_access_16 = { + .data_stride = 2, + .param = 0, +}; + void setUp(void) { tu_fifo_clear(ff); memset(&info, 0, sizeof(tu_fifo_buffer_info_t)); @@ -403,7 +413,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 4); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -425,7 +435,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 4); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -445,7 +455,7 @@ void test_read_n_fixed_addr_rw32_nowrap(void) { tu_fifo_write_n(ff, pattern, 8); uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 4); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(8 - n, tu_fifo_count(ff)); @@ -469,7 +479,7 @@ void test_read_n_fixed_addr_rw32_wrapped(void) { } uint32_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 4); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_32); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); @@ -485,7 +495,7 @@ void test_write_n_fixed_addr_rw16_nowrap(void) { for (uint8_t n = 1; n <= 6; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 2); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -507,7 +517,7 @@ void test_write_n_fixed_addr_rw16_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, 2); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -526,7 +536,7 @@ void test_read_n_fixed_addr_rw16_nowrap(void) { tu_fifo_write_n(ff, pattern, 6); uint16_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 2); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(6 - n, tu_fifo_count(ff)); @@ -549,7 +559,7 @@ void test_read_n_fixed_addr_rw16_wrapped(void) { } uint16_t reg = 0; - uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, 2); + uint16_t read_cnt = tu_fifo_read_n_access_mode(ff, ®, n, &hwfifo_access_16); TEST_ASSERT_EQUAL(n, read_cnt); TEST_ASSERT_EQUAL(0, tu_fifo_count(ff)); -- cgit v1.3.1 From e158a3dd38fccd99169a3e5b8cecf7a1ac45915e Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 12:49:01 +0700 Subject: hwfifo support custom write/read rusb use custom write enable all hil test for ra4m1 --- src/common/tusb_fifo.c | 45 ++++--- src/portable/renesas/rusb2/dcd_rusb2.c | 226 ++++++++++++++++++++++++--------- src/tusb_option.h | 9 +- test/hil/tinyusb.json | 5 +- 4 files changed, 199 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e34494c84..f6963a98d 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -121,6 +121,7 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { #define HWFIFO_ADDR_NEXT(_const, _hwfifo) #endif +#ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 if (data_stride == 4) { @@ -134,6 +135,28 @@ static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_st #endif } +// Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + // Write full available 16/32 bit words to dest + const uint8_t data_stride = access_mode->data_stride; + while (len >= data_stride) { + stride_write(hwfifo, src, data_stride); + src += data_stride; + len -= data_stride; + + HWFIFO_ADDR_NEXT(, hwfifo); + } + + // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit + if (len > 0) { + uint32_t tmp = 0u; + memcpy(&tmp, src, len); + stride_write(hwfifo, &tmp, data_stride); + } +} + #endif + + #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_READ static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 if (data_stride == 4) { @@ -165,26 +188,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co memcpy(dest, &tmp, len); } } - -// Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { - // Write full available 16/32 bit words to dest - const uint8_t data_stride = access_mode->data_stride; - while (len >= data_stride) { - stride_write(hwfifo, src, data_stride); - src += data_stride; - len -= data_stride; - - HWFIFO_ADDR_NEXT(, hwfifo); - } - - // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit - if (len > 0) { - uint32_t tmp = 0u; - memcpy(&tmp, src, len); - stride_write(hwfifo, &tmp, data_stride); - } -} + #endif static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, const tu_hwfifo_access_t *access_mode) { @@ -390,6 +394,7 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui } else #endif { + (void)access_mode; ff_pull_n(f, p_buffer, n, rd_ptr); } diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 6c6406dcf..f8fc7a643 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -57,6 +57,10 @@ enum { PIPE_COUNT = 10, }; +enum { + FIFOSEL_BIGEND = (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0) +}; + typedef struct { void *buf; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ @@ -163,7 +167,8 @@ static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) { //--------------------------------------------------------------------+ // Pipe FIFO //--------------------------------------------------------------------+ -#if 0 +#define USE_HWFIFO 1 + #if !USE_HWFIFO // Write data buffer --> hw fifo static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) { @@ -172,27 +177,48 @@ static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo volatile uint16_t *ff16; volatile uint8_t *ff8; + const uint8_t *buf8 = (const uint8_t *)buf; + // Highspeed FIFO is 32-bit if ( rusb2_is_highspeed_reg(rusb) ) { // TODO 32-bit access for better performance + volatile uint32_t *ff32 = (volatile uint32_t *)fifo; ff16 = (volatile uint16_t*) ((uintptr_t) fifo+2); ff8 = (volatile uint8_t *) ((uintptr_t) fifo+3); - }else { - ff16 = (volatile uint16_t*) fifo; - ff8 = ((volatile uint8_t*) fifo); - } - uint8_t const* buf8 = (uint8_t const*) buf; + while (len >= 4) { + *ff32 = tu_unaligned_read32(buf8); + buf8 += 4; + len -= 4; + } - while (len >= 2) { - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } + if (len >= 2) { + // switch to 16-bit access + rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | + (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } - if (len > 0) { - *ff8 = *buf8; - ++buf8; + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } + } else { + ff16 = (volatile uint16_t*) fifo; + ff8 = ((volatile uint8_t *)fifo); + + while (len >= 2) { + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } + + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } } } @@ -255,6 +281,66 @@ static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void * } #endif +static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { + volatile uint16_t *fifo_sel; + if (hwfifo == (uintptr_t)&rusb->CFIFO) { + fifo_sel = &rusb->CFIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D0FIFO) { + fifo_sel = &rusb->D0FIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D1FIFO) { + fifo_sel = &rusb->D1FIFOSEL; + } else { + return; + } + + *fifo_sel = (*fifo_sel & ~RUSB2_CFIFOSEL_MBW_Msk) | mbw; +} + +// write to hwfifo from buffer with access mode +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + rusb2_reg_t *rusb = (rusb2_reg_t *)access_mode->param; + const uint8_t *buf8 = (const uint8_t *)src; + + volatile uint16_t *ff16; + volatile uint8_t *ff8; + const bool is_highspeed = rusb2_is_highspeed_reg(rusb); + if (is_highspeed) { + ff16 = (volatile uint16_t *)((uintptr_t)hwfifo + 2); + ff8 = (volatile uint8_t *)((uintptr_t)hwfifo + 3); + } else { + ff16 = (volatile uint16_t *)hwfifo; + ff8 = ((volatile uint8_t *)hwfifo); + } + + // 32-bit access for highspeed + if (is_highspeed) { + volatile uint32_t *ff32 = (volatile uint32_t *)hwfifo; + while (len >= 4) { + *ff32 = tu_unaligned_read32(buf8); + buf8 += 4; + len -= 4; + } + + if (len >= 2) { + // switch to 16-bit access + hwfifo_set_mbw(rusb, (uintptr_t)hwfifo, RUSB2_FIFOSEL_MBW_16BIT); + } + } + + // 16-bit access + while (len >= 2) { + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } + + // 8-bit access does not need to change MBW + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } +} + //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ @@ -273,13 +359,12 @@ static bool pipe0_xfer_in(rusb2_reg_t *rusb) { void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; if (pipe->ff) { - // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len); - tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len); - // TODO check highspeed for 32-bit access - tu_hwfifo_write(&rusb->CFIFO, buf, len); + tu_hwfifo_write(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t *)buf + len; } } @@ -302,12 +387,13 @@ static bool pipe0_xfer_out(rusb2_reg_t *rusb) { void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + if (pipe->ff) { - // pipe_read_packet_ff(rusb, (tu_fifo_t *)buf, (volatile void *)&rusb->CFIFO, len); - tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_read_to_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_read_packet(rusb, buf, (volatile void *)&rusb->CFIFO, len); - tu_hwfifo_read(&rusb->CFIFO, buf, len); + tu_hwfifo_read(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t *)buf + len; } } @@ -335,21 +421,27 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num) return true; } - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - const uint16_t mps = edpt_max_packet_size(rusb, num); + const uint16_t fifo_sel = num | FIFOSEL_BIGEND; + const bool is_highspeed = rusb2_is_highspeed_reg(rusb); + if (is_highspeed) { + rusb->D0FIFOSEL = fifo_sel | RUSB2_FIFOSEL_MBW_32BIT; + } else { + rusb->D0FIFOSEL = fifo_sel | RUSB2_FIFOSEL_MBW_16BIT; + } + + const uint16_t mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); - const uint16_t len = tu_min16(rem, mps); - void *buf = pipe->buf; + uint16_t len = tu_min16(rem, mps); + void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; if (pipe->ff) { - // pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); - tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_write_from_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); - // TODO check highspeed for 32-bit access - tu_hwfifo_write(&rusb->D0FIFO, buf, len); - pipe->buf = (uint8_t*)buf + len; + tu_hwfifo_write(&rusb->D0FIFO, buf, len, &access_mode); + pipe->buf = (uint8_t *)buf + len; } } @@ -370,7 +462,14 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) pipe_state_t *pipe = &_dcd.pipe[num]; const uint16_t rem = pipe->remaining; - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; + uint16_t fifo_sel = num | FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + rusb->D0FIFOSEL = fifo_sel; + const uint16_t mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); @@ -379,13 +478,13 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; if (pipe->ff) { - // pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len); - tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len); + tu_hwfifo_read_to_fifo(&rusb->D0FIFO, (tu_fifo_t *)buf, len, &access_mode); } else { - // pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len); - tu_hwfifo_read(&rusb->D0FIFO, buf, len); - pipe->buf = (uint8_t*)buf + len; + tu_hwfifo_read(&rusb->D0FIFO, buf, len, &access_mode); + pipe->buf = (uint8_t *)buf + len; } } @@ -438,28 +537,33 @@ static void process_status_completion(uint8_t rhport) dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true); } -static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes) -{ +static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer, + uint16_t total_bytes) { + uint16_t fifo_sel = FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + /* configure fifo direction and access unit settings */ if (ep_addr != 0) { - /* IN, 2 bytes */ - rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | - (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {} + /* IN, 2 bytes */ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | fifo_sel; + while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) {} } else { /* OUT, 2 bytes */ - rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_16BIT; // RUSB2_FIFOSEL_MBW_8BIT; - while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {} + rusb->CFIFOSEL = fifo_sel; + while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {} } pipe_state_t *pipe = &_dcd.pipe[0]; - pipe->ff = buffer_type; - pipe->length = total_bytes; - pipe->remaining = total_bytes; + pipe->ff = buffer_type; + pipe->length = total_bytes; + pipe->remaining = total_bytes; - if ( total_bytes ) { + if (total_bytes) { pipe->buf = buffer; - if ( ep_addr ) { + if (ep_addr) { /* IN */ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80)); pipe0_xfer_in(rusb); @@ -631,18 +735,20 @@ static void process_set_address(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); const uint16_t addr = rusb->USBADDR_b.USBADDR; - if (!addr) return; + if (!addr) { + return; + } const tusb_control_request_t setup_packet = { #if defined(__CCRX__) .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */ -#else - .bmRequestType = 0, -#endif - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = addr, - .wIndex = 0, - .wLength = 0, + #else + .bmRequestType = 0, + #endif + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = addr, + .wIndex = 0, + .wLength = 0, }; dcd_event_setup_received(rhport, (const uint8_t *) &setup_packet, true); diff --git a/src/tusb_option.h b/src/tusb_option.h index 8e147707a..0abae6116 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -375,10 +375,11 @@ //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE_ODD_BYTE_SUPPORT // support odd byte access - #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 + (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 + #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE // custom write since rusb2 can change access width 32 -> 16 and can write + // odd byte with byte access #endif //-------------------------------------------------------------------- diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 6afcb2186..047d0879c 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -103,8 +103,9 @@ "name": "ra4m1_ek", "uid": "152E163038303131393346E46F26574B", "tests": { - "device": true, "host": false, "dual": false, - "skip": ["device/cdc_msc", "device/cdc_msc_freertos"] + "device": true, + "host": false, + "dual": false }, "comment": "MSC is slow to enumerated #2602", "flasher": { -- cgit v1.3.1 From ea23966aa785a630012097943c70d8121c5139c1 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 15:37:22 +0700 Subject: add default access mode for tu_hwfifo API make it easier for non-custom read/write --- src/common/tusb_fifo.c | 4 ++-- src/common/tusb_fifo.h | 8 ++++++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 13 +++++-------- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 6 +++--- src/portable/synopsys/dwc2/dcd_dwc2.c | 10 ++++------ 5 files changed, 20 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index f6963a98d..362439fb8 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -138,7 +138,7 @@ static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_st // Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Write full available 16/32 bit words to dest - const uint8_t data_stride = access_mode->data_stride; + const uint8_t data_stride = (access_mode != NULL) ? access_mode->data_stride : CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE; while (len >= data_stride) { stride_write(hwfifo, src, data_stride); src += data_stride; @@ -172,7 +172,7 @@ static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_st void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { // Reading full available 16/32-bit hwfifo and write to fifo - const uint8_t data_stride = access_mode->data_stride; + const uint8_t data_stride = (access_mode != NULL) ? access_mode->data_stride : CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE; while (len >= data_stride) { stride_read(hwfifo, dest, data_stride); dest += data_stride; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6fcc7020c..6c653c729 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -233,12 +233,16 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, access_mode); + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, + (access_mode != NULL) ? access_mode : &default_access); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, access_mode); + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, + (access_mode != NULL) ? access_mode : &default_access); } #if CFG_TUSB_FIFO_HWFIFO_API diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 2832611ff..72527a9ec 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -285,8 +285,7 @@ static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; - tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, &access_mode); + tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, NULL); // Clear CTR RX if another setup packet arrived before this, it will be discarded ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); @@ -324,11 +323,10 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count, &access_mode); + tu_hwfifo_read_to_fifo(pma_buf, xfer->ff, rx_count, NULL); } else { - tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count, &access_mode); + tu_hwfifo_read(pma_buf, xfer->buffer + xfer->queued_len, rx_count, NULL); } xfer->queued_len += rx_count; @@ -723,11 +721,10 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t addr_ptr = (uint16_t)btable_get_addr(ep_ix, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(addr_ptr); - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff) { - tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len, &access_mode); + tu_hwfifo_write_from_fifo(pma_buf, xfer->ff, len, NULL); } else { - tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len, &access_mode); + tu_hwfifo_write(pma_buf, &(xfer->buffer[xfer->queued_len]), len, NULL); } xfer->queued_len += len; diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index 480e460cb..f232f7d94 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -316,7 +316,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // More data to send uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX); - tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len, NULL); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false); @@ -331,7 +331,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) { // IN/RX direction uint16_t const rx_count = channel_get_rx_count(ch_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX); - tu_hwfifo_read(PMA_BUF_AT(pma_addr), edpt->buffer + edpt->queued_len, rx_count); + tu_hwfifo_read(PMA_BUF_AT(pma_addr), edpt->buffer + edpt->queued_len, rx_count, NULL); edpt->queued_len += rx_count; if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) { @@ -842,7 +842,7 @@ static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) { if (dir == TUSB_DIR_OUT) { uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size); - tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len); + tu_hwfifo_write(PMA_BUF_AT(pma_addr), &(edpt->buffer[edpt->queued_len]), len, NULL); btable_set_count(ch_id, BTABLE_BUF_TX, len); edpt->queued_len += len; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 2309afd53..4110e1530 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -365,13 +365,12 @@ static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { } // Push packet to Tx-FIFO - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; if (xfer->ff) { - tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, &access_mode); + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, NULL); total_bytes_written += xact_bytes; } else { - tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, &access_mode); + tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, NULL); xfer->buffer += xact_bytes; total_bytes_written += xact_bytes; } @@ -889,11 +888,10 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; if (xfer->ff != NULL) { - tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count, &access_mode); + tu_hwfifo_read_to_fifo(rx_fifo, xfer->ff, byte_count, NULL); } else { - tu_hwfifo_read(rx_fifo, xfer->buffer, byte_count, &access_mode); + tu_hwfifo_read(rx_fifo, xfer->buffer, byte_count, NULL); xfer->buffer += byte_count; } } -- cgit v1.3.1 From 93a1e8093a8abaac799e2aa45ec7dd1239a92196 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 16:37:17 +0700 Subject: rusb2 move tu_hwfifo_write() to rusb2_common.c --- src/portable/renesas/rusb2/dcd_rusb2.c | 105 ++++++++---------------------- src/portable/renesas/rusb2/rusb2_common.c | 63 +++++++++++++++++- 2 files changed, 89 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index f8fc7a643..6722e7a75 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -281,71 +281,12 @@ static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void * } #endif -static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { - volatile uint16_t *fifo_sel; - if (hwfifo == (uintptr_t)&rusb->CFIFO) { - fifo_sel = &rusb->CFIFOSEL; - } else if (hwfifo == (uintptr_t)&rusb->D0FIFO) { - fifo_sel = &rusb->D0FIFOSEL; - } else if (hwfifo == (uintptr_t)&rusb->D1FIFO) { - fifo_sel = &rusb->D1FIFOSEL; - } else { - return; - } - - *fifo_sel = (*fifo_sel & ~RUSB2_CFIFOSEL_MBW_Msk) | mbw; -} - -// write to hwfifo from buffer with access mode -void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { - rusb2_reg_t *rusb = (rusb2_reg_t *)access_mode->param; - const uint8_t *buf8 = (const uint8_t *)src; - - volatile uint16_t *ff16; - volatile uint8_t *ff8; - const bool is_highspeed = rusb2_is_highspeed_reg(rusb); - if (is_highspeed) { - ff16 = (volatile uint16_t *)((uintptr_t)hwfifo + 2); - ff8 = (volatile uint8_t *)((uintptr_t)hwfifo + 3); - } else { - ff16 = (volatile uint16_t *)hwfifo; - ff8 = ((volatile uint8_t *)hwfifo); - } - - // 32-bit access for highspeed - if (is_highspeed) { - volatile uint32_t *ff32 = (volatile uint32_t *)hwfifo; - while (len >= 4) { - *ff32 = tu_unaligned_read32(buf8); - buf8 += 4; - len -= 4; - } - - if (len >= 2) { - // switch to 16-bit access - hwfifo_set_mbw(rusb, (uintptr_t)hwfifo, RUSB2_FIFOSEL_MBW_16BIT); - } - } - - // 16-bit access - while (len >= 2) { - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } - // 8-bit access does not need to change MBW - if (len > 0) { - *ff8 = *buf8; - ++buf8; - } -} //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ - -static bool pipe0_xfer_in(rusb2_reg_t *rusb) { +static bool pipe0_xact_in(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -359,8 +300,20 @@ static bool pipe0_xfer_in(rusb2_reg_t *rusb) { void *buf = pipe->buf; if (len) { - tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), - .param = (uintptr_t)rusb}; + // uint16_t fifo_sel = RUSB2_CFIFOSEL_ISEL_WRITE | FIFOSEL_BIGEND; + tu_hwfifo_access_t access_mode; + access_mode.param = (uintptr_t)rusb; + // + if (rusb2_is_highspeed_reg(rusb)) { + // fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + access_mode.data_stride = 4u; + } else { + // fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + access_mode.data_stride = 2u; + } + // rusb->CFIFOSEL = fifo_sel; + // while (0 == (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) {} + if (pipe->ff) { tu_hwfifo_write_from_fifo(&rusb->CFIFO, (tu_fifo_t *)buf, len, &access_mode); } else { @@ -377,7 +330,7 @@ static bool pipe0_xfer_in(rusb2_reg_t *rusb) { return false; } -static bool pipe0_xfer_out(rusb2_reg_t *rusb) { +static bool pipe0_xact_out(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -539,21 +492,17 @@ static void process_status_completion(uint8_t rhport) static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer, uint16_t total_bytes) { - uint16_t fifo_sel = FIFOSEL_BIGEND; - if (rusb2_is_highspeed_reg(rusb)) { - fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; - } else { - fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; - } + uint16_t fifo_sel = + (rusb2_is_highspeed_reg(rusb) ? RUSB2_FIFOSEL_MBW_32BIT : RUSB2_FIFOSEL_MBW_16BIT) | FIFOSEL_BIGEND; /* configure fifo direction and access unit settings */ if (ep_addr != 0) { - /* IN, 2 bytes */ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | fifo_sel; - while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) {} - } else { - /* OUT, 2 bytes */ - rusb->CFIFOSEL = fifo_sel; - while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {} + // Control IN + fifo_sel |= RUSB2_CFIFOSEL_ISEL_WRITE; + } + rusb->CFIFOSEL = fifo_sel; + while ((rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) != (fifo_sel & RUSB2_CFIFOSEL_ISEL_WRITE)) { + // wait until ISEL_WRITE take effect } pipe_state_t *pipe = &_dcd.pipe[0]; @@ -566,7 +515,7 @@ static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_ad if (ep_addr) { /* IN */ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80)); - pipe0_xfer_in(rusb); + pipe0_xact_in(rusb); } rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF; } else { @@ -639,7 +588,7 @@ static bool process_edpt_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_add static void process_pipe0_bemp(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - bool completed = pipe0_xfer_in(rusb); + bool completed = pipe0_xact_in(rusb); if (completed) { pipe_state_t *pipe = &_dcd.pipe[0]; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), @@ -662,7 +611,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) if (num) { completed = pipe_xfer_out(rusb, num); } else { - completed = pipe0_xfer_out(rusb); + completed = pipe0_xact_out(rusb); } } if (completed) { diff --git a/src/portable/renesas/rusb2/rusb2_common.c b/src/portable/renesas/rusb2/rusb2_common.c index 856f9714f..3ed6f2be1 100644 --- a/src/portable/renesas/rusb2/rusb2_common.c +++ b/src/portable/renesas/rusb2/rusb2_common.c @@ -25,9 +25,10 @@ */ #include "tusb_option.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" #if defined(TUP_USBIP_RUSB2) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) - #include "rusb2_type.h" #if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) @@ -55,4 +56,64 @@ void tusb_rusb2_set_irqnum(uint8_t rhport, int32_t irqnum) { #endif +static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { + volatile uint16_t *fifo_sel; + if (hwfifo == (uintptr_t)&rusb->CFIFO) { + fifo_sel = &rusb->CFIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D0FIFO) { + fifo_sel = &rusb->D0FIFOSEL; + } else if (hwfifo == (uintptr_t)&rusb->D1FIFO) { + fifo_sel = &rusb->D1FIFOSEL; + } else { + return; + } + + *fifo_sel = (*fifo_sel & ~RUSB2_CFIFOSEL_MBW_Msk) | mbw; +} + +// write to hwfifo from buffer with access mode +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + rusb2_reg_t *rusb = (rusb2_reg_t *)access_mode->param; + const uint8_t *buf8 = (const uint8_t *)src; + + volatile uint16_t *ff16; + volatile uint8_t *ff8; + const bool is_highspeed = rusb2_is_highspeed_reg(rusb); + if (is_highspeed) { + ff16 = (volatile uint16_t *)((uintptr_t)hwfifo + 2); + ff8 = (volatile uint8_t *)((uintptr_t)hwfifo + 3); + } else { + ff16 = (volatile uint16_t *)hwfifo; + ff8 = ((volatile uint8_t *)hwfifo); + } + + // 32-bit access for highspeed + if (is_highspeed) { + volatile uint32_t *ff32 = (volatile uint32_t *)hwfifo; + while (len >= 4) { + *ff32 = tu_unaligned_read32(buf8); + buf8 += 4; + len -= 4; + } + + if (len >= 2) { + // switch to 16-bit access + hwfifo_set_mbw(rusb, (uintptr_t)hwfifo, RUSB2_FIFOSEL_MBW_16BIT); + } + } + + // 16-bit access + while (len >= 2) { + *ff16 = tu_unaligned_read16(buf8); + buf8 += 2; + len -= 2; + } + + // 8-bit access does not need to change MBW + if (len > 0) { + *ff8 = *buf8; + ++buf8; + } +} + #endif -- cgit v1.3.1 From d457ea3d3ca6727099211528bc0c415ed12eadff Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 17:52:58 +0700 Subject: fix build with dwc2 --- src/common/tusb_fifo.h | 2 +- src/common/tusb_mcu.h | 8 ---- src/portable/synopsys/dwc2/dcd_dwc2.c | 85 +++++++++++++++++++---------------- src/tusb_option.h | 39 +++++++--------- 4 files changed, 65 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6c653c729..967e6702c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -41,7 +41,7 @@ extern "C" { // mutex is only needed for RTOS. For OS None, we don't get preempted #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED -#define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO) +#define CFG_TUSB_FIFO_HWFIFO_API (CFG_TUD_EDPT_DEDICATED_HWFIFO || CFG_TUH_EDPT_DEDICATED_HWFIFO) #ifndef CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 0 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index f525a5a3d..8dd4078c4 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -429,10 +429,6 @@ #define TUP_MCU_MULTIPLE_CORE 1 #endif - // Disable slave if DMA is enabled - #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE - #elif TU_CHECK_MCU(OPT_MCU_ESP32P4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_ESP32 @@ -445,10 +441,6 @@ #define TUP_MCU_MULTIPLE_CORE 1 - // Disable slave if DMA is enabled - #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE - // Enable dcache if DMA is enabled #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 4110e1530..44f7137f9 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -98,10 +98,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_enabled(dwc2_dep_t* dep) { return (dep->ctl & EPCTL_EPENA) != 0; } -//-------------------------------------------------------------------- -// DMA -//-------------------------------------------------------------------- -#if CFG_TUD_MEM_DCACHE_ENABLE + #if CFG_TUD_DWC2_SLAVE_ENABLE +static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum); + #endif + + //-------------------------------------------------------------------- + // DMA + //-------------------------------------------------------------------- + #if CFG_TUD_MEM_DCACHE_ENABLE bool dcd_dcache_clean(const void* addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return dwc2_dcache_clean(addr, data_size); @@ -345,39 +349,6 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { - dwc2_dep_t *const epin = &dwc2->ep[0][epnum]; - xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); - - dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; - const uint16_t remain_packets = tsiz.packet_count; - - uint16_t total_bytes_written = 0; - // Process every single packet (only whole packets can be written to fifo) - for (uint16_t i = 0; i < remain_packets; i++) { - tsiz.value = epin->tsiz; - const uint16_t remain_bytes = (uint16_t) tsiz.xfer_size; - const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); - - // Check if dtxfsts has enough space available - if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { - break; - } - - // Push packet to Tx-FIFO - volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; - if (xfer->ff) { - tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, NULL); - total_bytes_written += xact_bytes; - } else { - tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, NULL); - xfer->buffer += xact_bytes; - total_bytes_written += xact_bytes; - } - } - return total_bytes_written; -} - // Since this function returns void, it is not possible to return a boolean success message // We must make sure that this function is not called when the EP is disabled // Must be called from critical section @@ -422,6 +393,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin } } + #if CFG_TUD_DWC2_DMA_ENABLE const bool is_dma = dma_device_enabled(dwc2); if(is_dma) { if (dir == TUSB_DIR_IN && total_bytes != 0) { @@ -433,7 +405,10 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin if (epnum == 0) { xfer->buffer += total_bytes; } - } else { + } else + #endif + { + #if CFG_TUD_DWC2_SLAVE_ENABLE dep->diepctl = depctl.value; // enable endpoint if (dir == TUSB_DIR_IN && total_bytes != 0) { @@ -445,6 +420,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin dwc2->diepempmsk |= (1u << epnum); } } + #endif } } @@ -850,6 +826,39 @@ TU_ATTR_ALWAYS_INLINE static inline void print_doepint(uint32_t doepint) { #endif #if CFG_TUD_DWC2_SLAVE_ENABLE +static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { + dwc2_dep_t *const epin = &dwc2->ep[0][epnum]; + xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); + + dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; + const uint16_t remain_packets = tsiz.packet_count; + + uint16_t total_bytes_written = 0; + // Process every single packet (only whole packets can be written to fifo) + for (uint16_t i = 0; i < remain_packets; i++) { + tsiz.value = epin->tsiz; + const uint16_t remain_bytes = (uint16_t)tsiz.xfer_size; + const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); + + // Check if dtxfsts has enough space available + if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { + break; + } + + // Push packet to Tx-FIFO + volatile uint32_t *tx_fifo = dwc2->fifo[epnum]; + if (xfer->ff) { + tu_hwfifo_write_from_fifo(tx_fifo, xfer->ff, xact_bytes, NULL); + total_bytes_written += xact_bytes; + } else { + tu_hwfifo_write(tx_fifo, xfer->buffer, xact_bytes, NULL); + xfer->buffer += xact_bytes; + total_bytes_written += xact_bytes; + } + } + return total_bytes_written; +} + // Process shared receive FIFO, this interrupt is only used in Slave mode static void handle_rxflvl_irq(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); diff --git a/src/tusb_option.h b/src/tusb_option.h index 0abae6116..453dddb7c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -268,16 +268,7 @@ //--------------------------------------------------------------------+ //------------- DWC2 -------------// -// Slave mode for device -#ifndef CFG_TUD_DWC2_SLAVE_ENABLE - #ifndef CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT - #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT 1 - #endif - - #define CFG_TUD_DWC2_SLAVE_ENABLE CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT -#endif - -// DMA for device +// DMA mode for device #ifndef CFG_TUD_DWC2_DMA_ENABLE #ifndef CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #define CFG_TUD_DWC2_DMA_ENABLE_DEFAULT 0 @@ -286,16 +277,16 @@ #define CFG_TUD_DWC2_DMA_ENABLE CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #endif -// Slave mode for host -#ifndef CFG_TUH_DWC2_SLAVE_ENABLE - #ifndef CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT - #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT 1 +// Slave mode for device +#ifndef CFG_TUD_DWC2_SLAVE_ENABLE + #ifndef CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT + #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE // disabled if DMA is enabled #endif - #define CFG_TUH_DWC2_SLAVE_ENABLE CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT + #define CFG_TUD_DWC2_SLAVE_ENABLE CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT #endif -// DMA for host +// DMA mode for host #ifndef CFG_TUH_DWC2_DMA_ENABLE #ifndef CFG_TUH_DWC2_DMA_ENABLE_DEFAULT #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 @@ -304,14 +295,18 @@ #define CFG_TUH_DWC2_DMA_ENABLE CFG_TUH_DWC2_DMA_ENABLE_DEFAULT #endif -#if defined(TUP_USBIP_DWC2) - #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 +// Slave mode for host +#ifndef CFG_TUH_DWC2_SLAVE_ENABLE + #ifndef CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT + #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE // disabled if DMA is enabled #endif - #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE - #define CFG_TUH_EDPT_DEDICATED_HWFIFO 1 - #endif + #define CFG_TUH_DWC2_SLAVE_ENABLE CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT +#endif + +#if defined(TUP_USBIP_DWC2) + #define CFG_TUD_EDPT_DEDICATED_HWFIFO CFG_TUD_DWC2_SLAVE_ENABLE + #define CFG_TUH_EDPT_DEDICATED_HWFIFO CFG_TUH_DWC2_SLAVE_ENABLE #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32bit access #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo address -- cgit v1.3.1 From b93d463afa11a7a24bc43dc7969a287c1d056b27 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 3 Jan 2026 23:54:05 +0700 Subject: fix rusb2 hcd_port_connect_status() using line state, add post root reset delay for stable speed detection --- src/host/usbh.c | 14 ++++++----- src/portable/renesas/rusb2/hcd_rusb2.c | 43 +++++++++------------------------ src/portable/renesas/rusb2/rusb2_type.h | 13 +++++++--- 3 files changed, 28 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index e99d9e977..a725b7c8b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1405,12 +1405,13 @@ static void remove_device_tree(uint8_t rhport, uint8_t hub_addr, uint8_t hub_por // NOTE: due to the shared control buffer, we must complete enumerating // one device before enumerating another one. //--------------------------------------------------------------------+ -enum { // USB 2.0 specs 7.1.7 for timing - ENUM_DEBOUNCING_DELAY_MS = 150, // T(ATTDB) minimum 100 ms for stable connection - ENUM_RESET_ROOT_DELAY_MS = 50, // T(DRSTr) minimum 50 ms for reset from root port - ENUM_RESET_HUB_DELAY_MS = 20, // T(DRST) 10-20 ms for hub reset - ENUM_RESET_RECOVERY_DELAY_MS = 10, // T(RSTRCY) minimum 10 ms for reset recovery - ENUM_SET_ADDRESS_RECOVERY_DELAY_MS = 2, // USB 2.0 Spec 9.2.6.3 min is 2 ms +enum { // USB 2.0 specs 7.1.7 for timing + ENUM_DEBOUNCING_DELAY_MS = 150, // T(ATTDB) minimum 100 ms for stable connection + ENUM_RESET_ROOT_DELAY_MS = 50, // T(DRSTr) minimum 50 ms for reset from root port + ENUM_RESET_ROOT_POST_DELAY_MS = 2, // 2 ms delay after root port reset before getting speed/status + ENUM_RESET_HUB_DELAY_MS = 20, // T(DRST) 10-20 ms for hub reset + ENUM_RESET_RECOVERY_DELAY_MS = 10, // T(RSTRCY) minimum 10 ms for reset recovery + ENUM_SET_ADDRESS_RECOVERY_DELAY_MS = 2, // USB 2.0 Spec 9.2.6.3 min is 2 ms }; enum { @@ -1469,6 +1470,7 @@ static bool enum_new_device(hcd_event_t* event) { hcd_port_reset(dev0_bus->rhport); tusb_time_delay_ms_api(ENUM_RESET_ROOT_DELAY_MS); hcd_port_reset_end(dev0_bus->rhport); + tusb_time_delay_ms_api(ENUM_RESET_ROOT_POST_DELAY_MS); if (!hcd_port_connect_status(dev0_bus->rhport)) { // device unplugged while delaying diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index 6f6d27d0e..d70599f5b 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -76,12 +76,10 @@ typedef struct TU_ATTR_PACKED { TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_ATTR_BIT_FIELD_ORDER_END -typedef struct -{ - bool need_reset; /* The device has not been reset after connection. */ +typedef struct { pipe_state_t pipe[PIPE_COUNT]; - uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */ - uint8_t ctl_mps[5]; /* EP0 max packet size for each device */ + uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */ + uint8_t ctl_mps[5]; /* EP0 max packet size for each device */ } hcd_data_t; //--------------------------------------------------------------------+ @@ -535,13 +533,8 @@ void hcd_int_disable(uint8_t rhport) { rusb2_int_disable(rhport); } -uint32_t hcd_frame_number(uint8_t rhport) -{ - rusb2_reg_t* rusb = RUSB2_REG(rhport); - - /* The device must be reset at least once after connection - * in order to start the frame counter. */ - if (_hcd.need_reset) hcd_port_reset(rhport); +uint32_t hcd_frame_number(uint8_t rhport) { + rusb2_reg_t *rusb = RUSB2_REG(rhport); return rusb->FRMNUM_b.FRNM; } @@ -550,32 +543,18 @@ uint32_t hcd_frame_number(uint8_t rhport) *--------------------------------------------------------------------+*/ bool hcd_port_connect_status(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - return rusb->INTSTS1_b.ATTCH ? true : false; + const uint16_t line_state = rusb->SYSSTS0 & RUSB2_SYSSTS0_LNST_Msk; + return line_state == RUSB2_SYSSTS0_LNST_FS_J || line_state == RUSB2_SYSSTS0_LNST_FS_K; } void hcd_port_reset(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; - while (rusb->DCPCTR_b.PBUSY) {} - - hcd_int_disable(rhport); - rusb->DVSTCTR0_b.UACT = 0; - if (rusb->DCPCTR_b.SUREQ) { - rusb->DCPCTR_b.SUREQCLR = 1; - } - hcd_int_enable(rhport); - - /* Reset should be asserted 10-20ms. */ rusb->DVSTCTR0_b.USBRST = 1; - for (volatile int i = 0; i < 2400000; ++i) {} - rusb->DVSTCTR0_b.USBRST = 0; - - rusb->DVSTCTR0_b.UACT = 1; - _hcd.need_reset = false; } void hcd_port_reset_end(uint8_t rhport) { - (void) rhport; + rusb2_reg_t *rusb = RUSB2_REG(rhport); + rusb->DVSTCTR0_b.USBRST = 0; } tusb_speed_t hcd_port_speed_get(uint8_t rhport) { @@ -584,7 +563,8 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) { case RUSB2_DVSTCTR0_RHST_HS: return TUSB_SPEED_HIGH; case RUSB2_DVSTCTR0_RHST_FS: return TUSB_SPEED_FULL; case RUSB2_DVSTCTR0_RHST_LS: return TUSB_SPEED_LOW; - default: return TUSB_SPEED_INVALID; + default: + return TUSB_SPEED_INVALID; } } @@ -802,7 +782,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { if (is1 & RUSB2_INTSTS1_ATTCH_Msk) { rusb->DVSTCTR0_b.UACT = 1; - _hcd.need_reset = true; rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk; hcd_event_device_attach(rhport, true); } diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h index 71837d03c..cf685ea3c 100644 --- a/src/portable/renesas/rusb2/rusb2_type.h +++ b/src/portable/renesas/rusb2/rusb2_type.h @@ -1669,15 +1669,20 @@ TU_ATTR_BIT_FIELD_ORDER_END /*--------------------------------------------------------------------*/ /* Register Bit Utils */ /*--------------------------------------------------------------------*/ -#define RUSB2_PIPE_CTR_PID_NAK (0U << RUSB2_PIPE_CTR_PID_Pos) /* NAK response */ -#define RUSB2_PIPE_CTR_PID_BUF (1U << RUSB2_PIPE_CTR_PID_Pos) /* BUF response (depends buffer state) */ -#define RUSB2_PIPE_CTR_PID_STALL (2U << RUSB2_PIPE_CTR_PID_Pos) /* STALL response */ -#define RUSB2_PIPE_CTR_PID_STALL2 (3U << RUSB2_PIPE_CTR_PID_Pos) /* Also STALL response */ +#define RUSB2_SYSSTS0_LNST_SE0 (0) +#define RUSB2_SYSSTS0_LNST_FS_J (1u << RUSB2_SYSSTS0_LNST_Pos) /* Full-speed J state */ +#define RUSB2_SYSSTS0_LNST_FS_K (2u << RUSB2_SYSSTS0_LNST_Pos) /* Full-speed K state */ +#define RUSB2_SYSSTS0_LNST_LS_SE1 (3u << RUSB2_SYSSTS0_LNST_Pos) /* Low-speed SE1 state */ #define RUSB2_DVSTCTR0_RHST_LS (1U << RUSB2_DVSTCTR0_RHST_Pos) /* Low-speed connection */ #define RUSB2_DVSTCTR0_RHST_FS (2U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */ #define RUSB2_DVSTCTR0_RHST_HS (3U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */ +#define RUSB2_PIPE_CTR_PID_NAK (0U << RUSB2_PIPE_CTR_PID_Pos) /* NAK response */ +#define RUSB2_PIPE_CTR_PID_BUF (1U << RUSB2_PIPE_CTR_PID_Pos) /* BUF response (depends buffer state) */ +#define RUSB2_PIPE_CTR_PID_STALL (2U << RUSB2_PIPE_CTR_PID_Pos) /* STALL response */ +#define RUSB2_PIPE_CTR_PID_STALL2 (3U << RUSB2_PIPE_CTR_PID_Pos) /* Also STALL response */ + #define RUSB2_DEVADD_USBSPD_LS (1U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Low-speed */ #define RUSB2_DEVADD_USBSPD_FS (2U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Full-speed */ -- cgit v1.3.1 From a9479f5ad96c28747661d9392ac28698f84c7bac Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 4 Jan 2026 01:01:52 +0700 Subject: update hcd rusb2 to use tu_hwfifo read/write --- src/common/tusb_fifo.h | 4 +- src/portable/renesas/rusb2/dcd_rusb2.c | 153 ++---------------------------- src/portable/renesas/rusb2/hcd_rusb2.c | 92 +++++++++--------- src/portable/renesas/rusb2/rusb2_common.c | 25 +++-- src/portable/renesas/rusb2/rusb2_common.h | 58 +++++++++++ src/portable/renesas/rusb2/rusb2_type.h | 7 +- 6 files changed, 125 insertions(+), 214 deletions(-) create mode 100644 src/portable/renesas/rusb2/rusb2_common.h (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 967e6702c..5515ffb91 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -233,14 +233,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE, .param = 0}; return tu_fifo_read_n_access_mode(f, (void *)(uintptr_t)hwfifo, n, (access_mode != NULL) ? access_mode : &default_access); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_read_to_fifo(const volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { - const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; + const tu_hwfifo_access_t default_access = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE, .param = 0}; return tu_fifo_write_n_access_mode(f, (const void *)(uintptr_t)hwfifo, n, (access_mode != NULL) ? access_mode : &default_access); } diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 6722e7a75..e2a51a5ca 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -30,25 +30,7 @@ #if CFG_TUD_ENABLED && defined(TUP_USBIP_RUSB2) #include "device/dcd.h" -#include "rusb2_type.h" - -#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - #include "rusb2_rx.h" -#elif TU_CHECK_MCU(OPT_MCU_RAXXX) - #include "rusb2_ra.h" - #if defined(RENESAS_CORTEX_M23) - #define D0FIFO CFIFO - #define D0FIFOSEL CFIFOSEL - #define D0FIFOSEL_b CFIFOSEL_b - #define D1FIFOSEL CFIFOSEL - #define D1FIFOSEL_b CFIFOSEL_b - #define D0FIFOCTR CFIFOCTR - #define D0FIFOCTR_b CFIFOCTR_b - #endif - -#else - #error "Unsupported MCU" -#endif +#include "rusb2_common.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -57,10 +39,6 @@ enum { PIPE_COUNT = 10, }; -enum { - FIFOSEL_BIGEND = (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0) -}; - typedef struct { void *buf; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ @@ -164,129 +142,10 @@ static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) { while ( !rusb->D0FIFOCTR_b.FRDY ) {} } -//--------------------------------------------------------------------+ -// Pipe FIFO -//--------------------------------------------------------------------+ -#define USE_HWFIFO 1 - #if !USE_HWFIFO -// Write data buffer --> hw fifo -static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len) -{ - (void) rusb; - - volatile uint16_t *ff16; - volatile uint8_t *ff8; - - const uint8_t *buf8 = (const uint8_t *)buf; - - // Highspeed FIFO is 32-bit - if ( rusb2_is_highspeed_reg(rusb) ) { - // TODO 32-bit access for better performance - volatile uint32_t *ff32 = (volatile uint32_t *)fifo; - ff16 = (volatile uint16_t*) ((uintptr_t) fifo+2); - ff8 = (volatile uint8_t *) ((uintptr_t) fifo+3); - - while (len >= 4) { - *ff32 = tu_unaligned_read32(buf8); - buf8 += 4; - len -= 4; - } - - if (len >= 2) { - // switch to 16-bit access - rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | - (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } - - if (len > 0) { - *ff8 = *buf8; - ++buf8; - } - } else { - ff16 = (volatile uint16_t*) fifo; - ff8 = ((volatile uint8_t *)fifo); - - while (len >= 2) { - *ff16 = tu_unaligned_read16(buf8); - buf8 += 2; - len -= 2; - } - - if (len > 0) { - *ff8 = *buf8; - ++buf8; - } - } -} - -// Write data sw fifo --> hw fifo -static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { - tu_fifo_buffer_info_t info; - tu_fifo_get_read_info(f, &info); - - uint16_t cnt_lin = tu_min16(total_len, info.linear.len); - uint16_t cnt_wrap = tu_min16(total_len - cnt_lin, info.wrapped.len); - uint16_t const cnt_written = cnt_lin + cnt_wrap; - - // Ensure only the last write is odd if total_len is odd - if (cnt_wrap == 0) { - pipe_write_packet(rusb, info.linear.ptr, fifo, cnt_lin); - } else { - pipe_write_packet(rusb, info.linear.ptr, fifo, cnt_lin & ~1); - - if (cnt_lin & 1) { - uint8_t glue[2] = {info.linear.ptr[cnt_lin & ~1], info.wrapped.ptr[0]}; - pipe_write_packet(rusb, glue, fifo, 2); - cnt_wrap--; - info.wrapped.ptr++; - } - - pipe_write_packet(rusb, info.wrapped.ptr, fifo, cnt_wrap); - } - tu_fifo_advance_read_pointer(f, cnt_written); -} - -// Read data buffer <-- hw fifo -static void pipe_read_packet(rusb2_reg_t *rusb, void *buf, volatile void *fifo, unsigned len) { - (void)rusb; - - // TODO 16/32-bit access for better performance - - uint8_t *p = (uint8_t *)buf; - volatile uint8_t *reg = (volatile uint8_t *)fifo; /* byte access is always at base register address */ - while (len--) { - *p++ = *reg; - } -} - -// Read data sw fifo <-- hw fifo -static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) { - tu_fifo_buffer_info_t info; - tu_fifo_get_write_info(f, &info); - - uint16_t count = tu_min16(total_len, info.linear.len); - pipe_read_packet(rusb, info.linear.ptr, fifo, count); - - uint16_t rem = total_len - count; - if (rem) { - rem = tu_min16(rem, info.wrapped.len); - pipe_read_packet(rusb, info.wrapped.ptr, fifo, rem); - count += rem; - } - - tu_fifo_advance_write_pointer(f, count); -} - #endif - - - //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ -static bool pipe0_xact_in(rusb2_reg_t *rusb) { +static bool pipe0_xfer_in(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -330,7 +189,7 @@ static bool pipe0_xact_in(rusb2_reg_t *rusb) { return false; } -static bool pipe0_xact_out(rusb2_reg_t *rusb) { +static bool pipe0_xfer_out(rusb2_reg_t *rusb) { pipe_state_t *pipe = &_dcd.pipe[0]; const unsigned rem = pipe->remaining; @@ -515,7 +374,7 @@ static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_ad if (ep_addr) { /* IN */ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80)); - pipe0_xact_in(rusb); + pipe0_xfer_in(rusb); } rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF; } else { @@ -588,7 +447,7 @@ static bool process_edpt_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_add static void process_pipe0_bemp(uint8_t rhport) { rusb2_reg_t* rusb = RUSB2_REG(rhport); - bool completed = pipe0_xact_in(rusb); + bool completed = pipe0_xfer_in(rusb); if (completed) { pipe_state_t *pipe = &_dcd.pipe[0]; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), @@ -611,7 +470,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) if (num) { completed = pipe_xfer_out(rusb, num); } else { - completed = pipe0_xact_out(rusb); + completed = pipe0_xfer_out(rusb); } } if (completed) { diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index d70599f5b..4c3315044 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -31,17 +31,9 @@ #include "host/hcd.h" #include "host/usbh.h" -#include "rusb2_type.h" +#include "rusb2_common.h" -#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - #include "rusb2_rx.h" -#elif TU_CHECK_MCU(OPT_MCU_RAXXX) - #include "rusb2_ra.h" -#else - #error "Unsupported MCU" -#endif - -#define TU_RUSB2_HCD_DBG 2 + #define TU_RUSB2_HCD_DBG 2 //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION @@ -164,29 +156,6 @@ static inline void pipe_wait_for_ready(rusb2_reg_t* rusb, unsigned num) while (!rusb->D0FIFOCTR_b.FRDY) {} } -static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) -{ - // NOTE: unlike DCD, Highspeed 32-bit FIFO does not need to adjust the fifo address - volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; - uintptr_t addr = (uintptr_t)buf; - while (len >= 2) { - reg->u16 = *(const uint16_t *)addr; - addr += 2; - len -= 2; - } - if (len) { - reg->u8 = *(const uint8_t *)addr; - ++addr; - } -} - -static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) -{ - uint8_t *p = (uint8_t*)buf; - volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */ - while (len--) *p++ = *reg; -} - static bool pipe0_xfer_in(rusb2_reg_t* rusb) { pipe_state_t *pipe = &_hcd.pipe[0]; @@ -197,8 +166,12 @@ static bool pipe0_xfer_in(rusb2_reg_t* rusb) const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); void *buf = pipe->buf; if (len) { + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; - pipe_read_packet(buf, (volatile void*)&rusb->CFIFO, len); + // pipe_read_packet(buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_read(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -225,7 +198,11 @@ static bool pipe0_xfer_out(rusb2_reg_t* rusb) const unsigned len = TU_MIN(mps, rem); void *buf = pipe->buf; if (len) { - pipe_write_packet(buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + + // pipe_write_packet(buf, (volatile void*)&rusb->CFIFO, len); + tu_hwfifo_write(&rusb->CFIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -240,14 +217,24 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num) pipe_state_t *pipe = &_hcd.pipe[num]; const unsigned rem = pipe->remaining; - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT; + uint16_t fifo_sel = num | FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + rusb->D0FIFOSEL = fifo_sel; + const unsigned mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); const unsigned vld = rusb->D0FIFOCTR_b.DTLN; const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); void *buf = pipe->buf; if (len) { - pipe_read_packet(buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_read_packet(buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + tu_hwfifo_read(&rusb->D0FIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -273,13 +260,23 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) return true; } - rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); + uint16_t fifo_sel = num | FIFOSEL_BIGEND; + if (rusb2_is_highspeed_reg(rusb)) { + fifo_sel |= RUSB2_FIFOSEL_MBW_32BIT; + } else { + fifo_sel |= RUSB2_FIFOSEL_MBW_16BIT; + } + rusb->D0FIFOSEL = fifo_sel; + const unsigned mps = edpt_max_packet_size(rusb, num); pipe_wait_for_ready(rusb, num); const unsigned len = TU_MIN(rem, mps); void *buf = pipe->buf; if (len) { - pipe_write_packet(buf, (volatile void*)&rusb->D0FIFO, len); + // pipe_write_packet(buf, (volatile void*)&rusb->D0FIFO, len); + tu_hwfifo_access_t access_mode = {.data_stride = (rusb2_is_highspeed_reg(rusb) ? 4u : 2u), + .param = (uintptr_t)rusb}; + tu_hwfifo_write(&rusb->D0FIFO, buf, len, &access_mode); pipe->buf = (uint8_t*)buf + len; } if (len < mps) { @@ -294,18 +291,19 @@ static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num) static bool process_pipe0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen) { (void)dev_addr; - rusb2_reg_t* rusb = RUSB2_REG(rhport); const unsigned dir_in = tu_edpt_dir(ep_addr); + uint16_t fifo_sel = + (rusb2_is_highspeed_reg(rusb) ? RUSB2_FIFOSEL_MBW_32BIT : RUSB2_FIFOSEL_MBW_16BIT) | FIFOSEL_BIGEND; + /* configure fifo direction and access unit settings */ - if (dir_in) { /* IN, a byte */ - rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT; - while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ; - } else { /* OUT, 2 bytes */ - rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT | - (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0); - while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ; + if (dir_in == TUSB_DIR_OUT) { + fifo_sel |= RUSB2_CFIFOSEL_ISEL_WRITE; + } + rusb->CFIFOSEL = fifo_sel; + while ((rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) != (fifo_sel & RUSB2_CFIFOSEL_ISEL_WRITE)) { + // wait until ISEL_WRITE take effect } pipe_state_t *pipe = &_hcd.pipe[0]; diff --git a/src/portable/renesas/rusb2/rusb2_common.c b/src/portable/renesas/rusb2/rusb2_common.c index 3ed6f2be1..8addbe4c6 100644 --- a/src/portable/renesas/rusb2/rusb2_common.c +++ b/src/portable/renesas/rusb2/rusb2_common.c @@ -25,23 +25,21 @@ */ #include "tusb_option.h" -#include "osal/osal.h" -#include "common/tusb_fifo.h" #if defined(TUP_USBIP_RUSB2) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) -#include "rusb2_type.h" + #include "osal/osal.h" + #include "common/tusb_fifo.h" -#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) -#include "rusb2_rx.h" + #include "rusb2_common.h" -#elif TU_CHECK_MCU(OPT_MCU_RAXXX) -#include "rusb2_ra.h" + #if TU_CHECK_MCU(OPT_MCU_RAXXX) + #include "rusb2_ra.h" // USBFS_INT_IRQn and USBHS_USB_INT_RESUME_IRQn are generated by FSP rusb2_controller_t rusb2_controller[] = { - { .reg_base = R_USB_FS0_BASE, .irqnum = USBFS_INT_IRQn }, + {.reg_base = R_USB_FS0_BASE, .irqnum = USBFS_INT_IRQn}, #ifdef RUSB2_SUPPORT_HIGHSPEED - { .reg_base = R_USB_HS0_BASE, .irqnum = USBHS_USB_INT_RESUME_IRQn }, + {.reg_base = R_USB_HS0_BASE, .irqnum = USBHS_USB_INT_RESUME_IRQn}, #endif }; @@ -50,12 +48,11 @@ void tusb_rusb2_set_irqnum(uint8_t rhport, int32_t irqnum); void tusb_rusb2_set_irqnum(uint8_t rhport, int32_t irqnum) { rusb2_controller[rhport].irqnum = irqnum; } + #endif -#else - #error "Unsupported MCU" -#endif - - +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ static void hwfifo_set_mbw(rusb2_reg_t *rusb, uintptr_t hwfifo, uint16_t mbw) { volatile uint16_t *fifo_sel; if (hwfifo == (uintptr_t)&rusb->CFIFO) { diff --git a/src/portable/renesas/rusb2/rusb2_common.h b/src/portable/renesas/rusb2/rusb2_common.h new file mode 100644 index 000000000..6b8c3d7f2 --- /dev/null +++ b/src/portable/renesas/rusb2/rusb2_common.h @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 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. + */ +#pragma once + +#include "common/tusb_common.h" +#include "rusb2_type.h" + +#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) + #include "rusb2_rx.h" +#elif TU_CHECK_MCU(OPT_MCU_RAXXX) + #include "rusb2_ra.h" + + // Hack for D0FIFO definitions on RA Cortex-M23 + #if defined(RENESAS_CORTEX_M23) + #define D0FIFO CFIFO + #define D0FIFOSEL CFIFOSEL + #define D0FIFOSEL_b CFIFOSEL_b + #define D1FIFOSEL CFIFOSEL + #define D1FIFOSEL_b CFIFOSEL_b + #define D0FIFOCTR CFIFOCTR + #define D0FIFOCTR_b CFIFOCTR_b + #endif + +#else + #error "Unsupported MCU" +#endif + + +//--------------------------------------------------------------------+ +// Common +//--------------------------------------------------------------------+ + +enum { + FIFOSEL_BIGEND = (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0) +}; diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h index cf685ea3c..21f116857 100644 --- a/src/portable/renesas/rusb2/rusb2_type.h +++ b/src/portable/renesas/rusb2/rusb2_type.h @@ -41,10 +41,9 @@ extern "C" { #define _ccrx_evenaccess #endif -/*--------------------------------------------------------------------*/ -/* Register Definitions */ -/*--------------------------------------------------------------------*/ - +//--------------------------------------------------------------------+ +// Register Definitions +//--------------------------------------------------------------------+ /* Start of definition of packed structs (used by the CCRX toolchain) */ TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN -- cgit v1.3.1 From 74e59e433db41cc6045e29a4723fc4e72ab9dcde Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 5 Jan 2026 22:50:23 +0700 Subject: fix hwfifo pull/push n with address stride > 0 --- src/common/tusb_fifo.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 362439fb8..ee07f66df 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -115,13 +115,14 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { //--------------------------------------------------------------------+ #if CFG_TUSB_FIFO_HWFIFO_API #if CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE - #define HWFIFO_ADDR_NEXT(_const, _hwfifo) \ - _hwfifo = (_const volatile void *)((uintptr_t)(_hwfifo) + CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE) + #define HWFIFO_ADDR_NEXT_N(_hwfifo, _const, _n) _hwfifo = (_const volatile void *)((uintptr_t)(_hwfifo) + _n) #else - #define HWFIFO_ADDR_NEXT(_const, _hwfifo) + #define HWFIFO_ADDR_NEXT_N(_hwfifo, _const, _n) #endif -#ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE + #define HWFIFO_ADDR_NEXT(_hwfifo, _const) HWFIFO_ADDR_NEXT_N(_hwfifo, _const, CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE) + + #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 if (data_stride == 4) { @@ -143,8 +144,7 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co stride_write(hwfifo, src, data_stride); src += data_stride; len -= data_stride; - - HWFIFO_ADDR_NEXT(, hwfifo); + HWFIFO_ADDR_NEXT(hwfifo, ); } // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit @@ -152,6 +152,7 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co uint32_t tmp = 0u; memcpy(&tmp, src, len); stride_write(hwfifo, &tmp, data_stride); + HWFIFO_ADDR_NEXT(hwfifo, ); } } #endif @@ -177,8 +178,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co stride_read(hwfifo, dest, data_stride); dest += data_stride; len -= data_stride; - - HWFIFO_ADDR_NEXT(const, hwfifo); + HWFIFO_ADDR_NEXT(hwfifo, const); } // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit @@ -186,10 +186,12 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co uint32_t tmp; stride_read(hwfifo, &tmp, data_stride); memcpy(dest, &tmp, len); + HWFIFO_ADDR_NEXT(hwfifo, const); } } #endif +// push to sw fifo from hwfifo static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, const tu_hwfifo_access_t *access_mode) { uint16_t lin_bytes = f->depth - wr_ptr; @@ -208,6 +210,7 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin const uint32_t odd_mask = data_stride - 1; uint16_t lin_even = lin_bytes & ~odd_mask; tu_hwfifo_read(hwfifo, ff_buf, lin_even, access_mode); + HWFIFO_ADDR_NEXT_N(hwfifo, const, lin_even); ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -217,6 +220,7 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin const uint8_t wrap_odd = (uint8_t)tu_min16(wrap_bytes, data_stride - lin_odd); uint8_t buf_temp[4]; tu_hwfifo_read(hwfifo, buf_temp, lin_odd + wrap_odd, access_mode); + HWFIFO_ADDR_NEXT(hwfifo, const); for (uint8_t i = 0; i < lin_odd; ++i) { ff_buf[i] = buf_temp[i]; @@ -238,6 +242,7 @@ static void hwff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uin } } +// pull from sw fifo to hwfifo static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, const tu_hwfifo_access_t *access_mode) { uint16_t lin_bytes = f->depth - rd_ptr; @@ -257,6 +262,7 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t const uint32_t odd_mask = data_stride - 1; uint16_t lin_even = lin_bytes & ~odd_mask; tu_hwfifo_write(hwfifo, ff_buf, lin_even, access_mode); + HWFIFO_ADDR_NEXT_N(hwfifo, , lin_even); ff_buf += lin_even; // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary @@ -273,6 +279,7 @@ static void hwff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t } tu_hwfifo_write(hwfifo, buf_temp, lin_odd + wrap_odd, access_mode); + HWFIFO_ADDR_NEXT(hwfifo, ); wrap_bytes -= wrap_odd; ff_buf = f->buffer + wrap_odd; // wrap around -- cgit v1.3.1 From 20d009daa1f886432d42a2f56ce8edfe62e3b0de Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 5 Jan 2026 23:42:05 +0700 Subject: enable dedidcated hwfifo for musb with odd access with 16-bit and 8-bit --- src/common/tusb_fifo.c | 65 +++++++++++++++++++++++++++----- src/portable/mentor/musb/dcd_musb.c | 74 +++---------------------------------- src/tusb_option.h | 9 ++++- 3 files changed, 69 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index ee07f66df..a92435912 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -123,8 +123,8 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { #define HWFIFO_ADDR_NEXT(_hwfifo, _const) HWFIFO_ADDR_NEXT_N(_hwfifo, _const, CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE) #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE -static void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 +static inline void stride_write(volatile void *hwfifo, const void *src, uint8_t data_stride) { + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 if (data_stride == 4) { *((volatile uint32_t *)hwfifo) = tu_unaligned_read32(src); } @@ -147,6 +147,25 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co HWFIFO_ADDR_NEXT(hwfifo, ); } + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + // 16-bit access is allowed for odd bytes + if (len >= 2) { + *((volatile uint16_t *)hwfifo) = tu_unaligned_read16(src); + src += 2; + len -= 2; + HWFIFO_ADDR_NEXT_N(hwfifo, , 2); + } + #endif + + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS + // 8-bit access is allowed for odd bytes + while (len > 0) { + *((volatile uint8_t *)hwfifo) = *src++; + len--; + HWFIFO_ADDR_NEXT_N(hwfifo, , 1); + } + #else + // Write odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { uint32_t tmp = 0u; @@ -154,21 +173,30 @@ void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, co stride_write(hwfifo, &tmp, data_stride); HWFIFO_ADDR_NEXT(hwfifo, ); } + #endif } #endif #ifndef CFG_TUSB_FIFO_HWFIFO_CUSTOM_READ -static void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 - if (data_stride == 4) { +static inline void stride_read(const volatile void *hwfifo, void *dest, uint8_t data_stride) { + (void)data_stride; // possible unused + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 4 + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE != 4 + if (data_stride == 4) + #endif + { tu_unaligned_write32(dest, *((const volatile uint32_t *)hwfifo)); } - #endif - #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 - if (data_stride == 2) { + #endif + + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE & 2 + #if CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE != 2 + if (data_stride == 2) + #endif + { tu_unaligned_write16(dest, *((const volatile uint16_t *)hwfifo)); } - #endif + #endif } void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { @@ -181,6 +209,24 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co HWFIFO_ADDR_NEXT(hwfifo, const); } + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + // 16-bit access is allowed for odd bytes + if (len >= 2) { + tu_unaligned_write16(dest, *((const volatile uint16_t *)hwfifo)); + dest += 2; + len -= 2; + HWFIFO_ADDR_NEXT_N(hwfifo, const, 2); + } + #endif + + #ifdef CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS + // 8-bit access is allowed for odd bytes + while (len > 0) { + *dest++ = *((const volatile uint8_t *)hwfifo); + len--; + HWFIFO_ADDR_NEXT_N(hwfifo, const, 1); + } + #else // Read odd bytes i.e 1 byte for 16 bit or 1-3 bytes for 32 bit if (len > 0) { uint32_t tmp; @@ -188,6 +234,7 @@ void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, co memcpy(dest, &tmp, len); HWFIFO_ADDR_NEXT(hwfifo, const); } + #endif } #endif diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index ad20d64bd..3827be318 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -170,68 +170,6 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_flush(musb_regs_t* musb, unsigne } } -static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) -{ - volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; - uintptr_t addr = (uintptr_t)buf; - while (len >= 4) { - reg->u32 = *(uint32_t const *)addr; - addr += 4; - len -= 4; - } - if (len >= 2) { - reg->u16 = *(uint16_t const *)addr; - addr += 2; - len -= 2; - } - if (len) { - reg->u8 = *(uint8_t const *)addr; - } -} - -static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) -{ - volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo; - uintptr_t addr = (uintptr_t)buf; - while (len >= 4) { - *(uint32_t *)addr = reg->u32; - addr += 4; - len -= 4; - } - if (len >= 2) { - *(uint16_t *)addr = reg->u16; - addr += 2; - len -= 2; - } - if (len) { - *(uint8_t *)addr = reg->u8; - } -} - -static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir) -{ - static const struct { - void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info); - void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n); - void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len); - } ops[] = { - /* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet}, - /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet}, - }; - tu_fifo_buffer_info_t info; - ops[dir].tu_fifo_get_info(f, &info); - unsigned total_len = len; - len = TU_MIN(total_len, info.linear.len); - ops[dir].pipe_read_write(info.linear.ptr, fifo, len); - unsigned rem = total_len - len; - if (rem) { - len = TU_MIN(rem, info.wrapped.len); - ops[dir].pipe_read_write(info.wrapped.ptr, fifo, len); - rem -= len; - } - ops[dir].tu_fifo_advance(f, total_len - rem); -} - static void process_setup_packet(uint8_t rhport) { musb_regs_t* musb_regs = MUSB_REGS(rhport); @@ -277,9 +215,9 @@ static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr) // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem); if (len) { if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_IN); + tu_hwfifo_write_from_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); } else { - pipe_write_packet(buf, fifo_ptr, len); + tu_hwfifo_write(fifo_ptr, buf, len, NULL); pipe->buf = buf + len; } pipe->remaining = rem - len; @@ -308,9 +246,9 @@ static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr) volatile void *fifo_ptr = &musb_regs->fifo[epnum]; if (len) { if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_OUT); + tu_hwfifo_read_to_fifo(fifo_ptr, (tu_fifo_t *)buf, len, NULL); } else { - pipe_read_packet(buf, fifo_ptr, len); + tu_hwfifo_read(fifo_ptr, buf, len, NULL); pipe->buf = buf + len; } pipe->remaining = rem - len; @@ -378,7 +316,7 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_ const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes); volatile void *fifo_ptr = &musb_regs->fifo[0]; if (dir_in) { - pipe_write_packet(buffer, fifo_ptr, len); + tu_hwfifo_write(fifo_ptr, buffer, len, NULL); _dcd.pipe0.buf = buffer + len; _dcd.pipe0.length = len; @@ -458,7 +396,7 @@ static void process_ep0(uint8_t rhport) const unsigned rem = _dcd.pipe0.remaining; const unsigned len = TU_MIN(TU_MIN(rem, 64), vld); volatile void *fifo_ptr = &musb_regs->fifo[0]; - pipe_read_packet(_dcd.pipe0.buf, fifo_ptr, len); + tu_hwfifo_read(fifo_ptr, _dcd.pipe0.buf, len, NULL); _dcd.pipe0.remaining = rem - len; _dcd.remaining_ctrl -= len; diff --git a/src/tusb_option.h b/src/tusb_option.h index 453dddb7c..87aba6a6c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -365,13 +365,18 @@ //------------ MUSB --------------// #if defined(TUP_USBIP_MUSB) - #define CFG_TUD_EDPT_DEDICATED_HWFIFO 0 // need testing to enable + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32 bit data + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS // allow odd 16bit access + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS // allow odd 8bit access + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo + #endif //------------ RUSB2 --------------// #if defined(TUP_USBIP_RUSB2) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 + (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (2 | (TUD_OPT_HIGH_SPEED ? 4 : 0)) // 16 bit and 32 bit data if highspeed #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 #define CFG_TUSB_FIFO_HWFIFO_CUSTOM_WRITE // custom write since rusb2 can change access width 32 -> 16 and can write // odd byte with byte access -- cgit v1.3.1 From 1c19fc540868d699bd7eedba741108dfabb36c00 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Jan 2026 00:56:33 +0700 Subject: rename FSDEV_PMA_SIZE CFG_TUSB_FSDEV_PMA_SIZE --- src/common/tusb_mcu.h | 36 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 286 +++++++++++++------------- src/portable/st/stm32_fsdev/fsdev_common.h | 108 +++++----- src/portable/st/stm32_fsdev/fsdev_stm32.h | 2 +- src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 6 +- src/tusb_option.h | 6 +- 7 files changed, 217 insertions(+), 229 deletions(-) (limited to 'src') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 8dd4078c4..d546703bc 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -179,12 +179,12 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32C0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32F1) // - F102, F103 use fsdev @@ -200,7 +200,7 @@ defined(STM32F103xE) || defined(STM32F103xG) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #else #error "Unsupported STM32F1 mcu" #endif @@ -218,10 +218,10 @@ #if defined(STM32F302xB) || defined(STM32F302xC) || defined(STM32F303xB) || defined(STM32F303xC) || \ defined(STM32F373xC) - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #elif defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xD) || defined(STM32F302xE) || \ defined(STM32F303xD) || defined(STM32F303xE) - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #else #error "Unsupported STM32F3 mcu" #endif @@ -253,13 +253,13 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32G0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32G4) // Device controller #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u // TypeC controller #define TUP_USBIP_TYPEC_STM32 @@ -268,7 +268,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32H5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32H7) #include "stm32h7xx.h" @@ -302,12 +302,12 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32L0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32L1) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_STM32L4) // - L4x2, L4x3 use fsdev @@ -324,7 +324,7 @@ defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #else #error "Unsupported STM32L4 mcu" #endif @@ -332,24 +332,24 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE (1024u) + #define CFG_TUSB_FSDEV_PMA_SIZE (1024u) #elif TU_CHECK_MCU(OPT_MCU_STM32U0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32U3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #elif TU_CHECK_MCU(OPT_MCU_STM32U5) // U535/545 use fsdev #if defined(STM32U535xx) || defined(STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 2048u + #define CFG_TUSB_FSDEV_PMA_SIZE 2048u #else #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 @@ -367,7 +367,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32WB) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define FSDEV_PMA_SIZE 1024u + #define CFG_TUSB_FSDEV_PMA_SIZE 1024u #elif TU_CHECK_MCU(OPT_MCU_STM32WBA) #define TUP_USBIP_DWC2 @@ -572,7 +572,7 @@ #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_CH32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) @@ -621,7 +621,7 @@ #elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407, OPT_MCU_AT32F413) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define FSDEV_PMA_SIZE 512u + #define CFG_TUSB_FSDEV_PMA_SIZE 512u #elif TU_CHECK_MCU(OPT_MCU_AT32F415) #define TUP_USBIP_DWC2 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 72527a9ec..22a9e4af8 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -108,11 +108,10 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && defined(TUP_USBIP_FSDEV) && \ - !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0) +#if CFG_TUD_ENABLED && defined(TUP_USBIP_FSDEV) && !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0) -#include "device/dcd.h" -#include "fsdev_common.h" + #include "device/dcd.h" + #include "fsdev_common.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -120,25 +119,25 @@ // One of these for every EP IN & OUT, uses a bit of RAM.... typedef struct { - uint8_t *buffer; + uint8_t *buffer; tu_fifo_t *ff; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_packet_size; - uint8_t ep_idx; // index for USB_EPnR register - bool iso_in_sending; // Workaround for ISO IN EP doesn't have interrupt mask + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t ep_idx; // index for USB_EPnR register + bool iso_in_sending; // Workaround for ISO IN EP doesn't have interrupt mask } xfer_ctl_t; // EP allocator typedef struct { uint8_t ep_num; uint8_t ep_type; - bool allocated[2]; + bool allocated[2]; } ep_alloc_t; static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]; static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]; -static uint8_t remoteWakeCountdown; // When wake is requested +static uint8_t remoteWakeCountdown; // When wake is requested //--------------------------------------------------------------------+ // Prototypes @@ -152,12 +151,12 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir); // PMA allocation/access static uint16_t ep_buf_ptr; ///< Points to first free memory location static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf); -static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); +static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); static void edpt0_open(uint8_t rhport); TU_ATTR_ALWAYS_INLINE static inline void edpt0_prepare_setup(void) { - btable_set_rx_bufsize(0, BTABLE_BUF_RX, 8); + btable_set_rx_bufsize(0, BTABLE_BUF_RX, 8); } //--------------------------------------------------------------------+ @@ -171,21 +170,21 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint8_t epnum, uint //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rh_init; fsdev_core_reset(); FSDEV_REG->CNTR = 0; // Enable USB -#if !defined(FSDEV_BUS_32BIT) + #if !defined(FSDEV_BUS_32BIT) // BTABLE register does not exist any more on 32-bit bus devices FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; -#endif + #endif // Enable interrupts for device mode - FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | - USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; + FSDEV_REG->CNTR |= + USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; handle_bus_reset(rhport); @@ -236,8 +235,8 @@ static void handle_bus_reset(uint8_t rhport) { for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // Clear EP allocation status - ep_alloc_status[i].ep_num = 0xFF; - ep_alloc_status[i].ep_type = 0xFF; + ep_alloc_status[i].ep_num = 0xFF; + ep_alloc_status[i].ep_type = 0xFF; ep_alloc_status[i].allocated[0] = false; ep_alloc_status[i].allocated[1] = false; } @@ -245,7 +244,7 @@ static void handle_bus_reset(uint8_t rhport) { // Reset PMA allocation ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; - edpt0_open(rhport); // open control endpoint (both IN & OUT) + edpt0_open(rhport); // open control endpoint (both IN & OUT) FSDEV_REG->DADDR = USB_DADDR_EF; // Enable USB Function } @@ -254,8 +253,8 @@ static void handle_bus_reset(uint8_t rhport) { static void handle_ctr_tx(uint32_t ep_id) { uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); + const uint8_t ep_num = ep_reg & USB_EPADDR_FIELD; + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); if (ep_is_iso(ep_reg)) { // Ignore spurious interrupts that we don't schedule @@ -265,11 +264,11 @@ static void handle_ctr_tx(uint32_t ep_id) { return; } xfer->iso_in_sending = false; -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 uint8_t buf_id = (ep_reg & USB_EP_DTOG_TX) ? 0 : 1; -#else + #else uint8_t buf_id = BTABLE_BUF_TX; -#endif + #endif btable_set_count(ep_id, buf_id, 0); } @@ -282,8 +281,8 @@ static void handle_ctr_tx(uint32_t ep_id) { static void handle_ctr_setup(uint32_t ep_id) { uint16_t rx_count = btable_get_count(ep_id, BTABLE_BUF_RX); - uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); - uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); + uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); + uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); tu_hwfifo_read(PMA_BUF_AT(rx_addr), setup_packet, rx_count, NULL); @@ -292,7 +291,7 @@ static void handle_ctr_setup(uint32_t ep_id) { // Setup packet should always be 8 bytes. If not, we probably missed the packet if (rx_count == 8) { - dcd_event_setup_received(0, (uint8_t*) setup_packet, true); + dcd_event_setup_received(0, (uint8_t *)setup_packet, true); // Hardware should reset EP0 RX/TX to NAK and both toggle to 1 } else { // Missed setup packet !!! @@ -303,24 +302,24 @@ static void handle_ctr_setup(uint32_t ep_id) { // Handle CTR interrupt for the RX/OUT direction static void handle_ctr_rx(uint32_t ep_id) { - uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; - bool const is_iso = ep_is_iso(ep_reg); - xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); + uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + const uint8_t ep_num = ep_reg & USB_EPADDR_FIELD; + const bool is_iso = ep_is_iso(ep_reg); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); uint8_t buf_id; -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = is_iso; -#else + #else bool const dbl_buf = false; -#endif + #endif if (dbl_buf) { buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; } else { buf_id = BTABLE_BUF_RX; } - const uint16_t rx_count = btable_get_count(ep_id, buf_id); - uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); + const uint16_t rx_count = btable_get_count(ep_id, buf_id); + uint16_t pma_addr = (uint16_t)btable_get_addr(ep_id, buf_id); fsdev_pma_buf_t *pma_buf = PMA_BUF_AT(pma_addr); if (xfer->ff) { @@ -344,7 +343,7 @@ static void handle_ctr_rx(uint32_t ep_id) { } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always if (!is_iso) { - uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + const uint16_t cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits @@ -404,18 +403,18 @@ void dcd_int_handler(uint8_t rhport) { // loop to handle all pending CTR interrupts while (FSDEV_REG->ISTR & USB_ISTR_CTR) { // skip DIR bit, and use CTR TX/RX instead, since there is chance we have both TX/RX completed in one interrupt - uint32_t const ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; - uint32_t const ep_reg = ep_read(ep_id); + const uint32_t ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + const uint32_t ep_reg = ep_read(ep_id); if (ep_reg & USB_EP_CTR_RX) { - #ifdef FSDEV_BUS_32BIT + #ifdef FSDEV_BUS_32BIT /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses - * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. - * Workaround: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM + * accesses have completed. If the software responds quickly to the interrupt, the full buffer contents may not be + * correct. Workaround: * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code @@ -426,9 +425,9 @@ void dcd_int_handler(uint8_t rhport) { */ volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) } - #endif + #endif if (ep_reg & USB_EP_SETUP) { handle_ctr_setup(ep_id); // CTR will be clear after copied setup packet @@ -456,14 +455,13 @@ void dcd_int_handler(uint8_t rhport) { // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { +void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) { (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS) { - uint8_t const dev_addr = (uint8_t)request->wValue; - FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { + const uint8_t dev_addr = (uint8_t)request->wValue; + FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); } edpt0_prepare_setup(); @@ -474,15 +472,14 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req * In case of double buffering, high 16bit is the address of 2nd buffer * During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually. */ -static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) -{ - uint8_t blsize, num_block; +static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) { + uint8_t blsize, num_block; uint16_t aligned_len = pma_align_buffer_size(len, &blsize, &num_block); - (void) blsize; - (void) num_block; + (void)blsize; + (void)num_block; uint32_t addr = ep_buf_ptr; - ep_buf_ptr = (uint16_t)(ep_buf_ptr + aligned_len); // increment buffer pointer + ep_buf_ptr = (uint16_t)(ep_buf_ptr + aligned_len); // increment buffer pointer if (dbuf) { addr |= ((uint32_t)ep_buf_ptr) << 16; @@ -490,7 +487,7 @@ static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) } // Verify packet buffer is not overflowed - TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF); + TU_ASSERT(ep_buf_ptr <= CFG_TUSB_FSDEV_PMA_SIZE, 0xFFFF); return addr; } @@ -498,35 +495,32 @@ static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) /*** * Allocate hardware endpoint */ -static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) { + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) { // Check if already allocated - if (ep_alloc_status[i].allocated[dir] && - ep_alloc_status[i].ep_type == ep_type && + if (ep_alloc_status[i].allocated[dir] && ep_alloc_status[i].ep_type == ep_type && ep_alloc_status[i].ep_num == epnum) { return i; } -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = ep_type == TUSB_XFER_ISOCHRONOUS; -#else + #else bool const dbl_buf = false; -#endif + #endif // If EP of current direction is not allocated // For double-buffered mode both directions needs to be free - if (!ep_alloc_status[i].allocated[dir] && - (!dbl_buf || !ep_alloc_status[i].allocated[dir ^ 1])) { + if (!ep_alloc_status[i].allocated[dir] && (!dbl_buf || !ep_alloc_status[i].allocated[dir ^ 1])) { // Check if EP number is the same if (ep_alloc_status[i].ep_num == 0xFF || ep_alloc_status[i].ep_num == epnum) { // One EP pair has to be the same type if (ep_alloc_status[i].ep_type == 0xFF || ep_alloc_status[i].ep_type == ep_type) { - ep_alloc_status[i].ep_num = epnum; - ep_alloc_status[i].ep_type = ep_type; + ep_alloc_status[i].ep_num = epnum; + ep_alloc_status[i].ep_type = ep_type; ep_alloc_status[i].allocated[dir] = true; return i; @@ -540,16 +534,16 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) } void edpt0_open(uint8_t rhport) { - (void) rhport; + (void)rhport; dcd_ep_alloc(0x0, TUSB_XFER_CONTROL); dcd_ep_alloc(0x80, TUSB_XFER_CONTROL); xfer_status[0][0].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; - xfer_status[0][0].ep_idx = 0; + xfer_status[0][0].ep_idx = 0; xfer_status[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; - xfer_status[0][1].ep_idx = 0; + xfer_status[0][1].ep_idx = 0; uint16_t pma_addr0 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); uint16_t pma_addr1 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); @@ -567,13 +561,13 @@ void edpt0_open(uint8_t rhport) { ep_write(0, ep_reg, false); } -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { (void)rhport; - uint8_t const ep_addr = desc_ep->bEndpointAddress; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - const uint16_t packet_size = tu_edpt_packet_size(desc_ep); - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); + const uint8_t ep_addr = desc_ep->bEndpointAddress; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + const uint16_t packet_size = tu_edpt_packet_size(desc_ep); + const uint8_t ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); TU_ASSERT(ep_idx < FSDEV_EP_COUNT); uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; @@ -597,9 +591,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { uint16_t pma_addr = dcd_pma_alloc(packet_size, false); btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); xfer->max_packet_size = packet_size; - xfer->ep_idx = ep_idx; + xfer->ep_idx = ep_idx; ep_change_status(&ep_reg, dir, EP_STAT_NAK); ep_change_dtog(&ep_reg, dir, 0); @@ -623,8 +617,8 @@ void dcd_edpt_close_all(uint8_t rhport) { // Reset endpoint ep_write(i, 0, false); // Clear EP allocation status - ep_alloc_status[i].ep_num = 0xFF; - ep_alloc_status[i].ep_type = 0xFF; + ep_alloc_status[i].ep_num = 0xFF; + ep_alloc_status[i].ep_type = 0xFF; ep_alloc_status[i].allocated[0] = false; ep_alloc_status[i].allocated[1] = false; } @@ -638,46 +632,46 @@ void dcd_edpt_close_all(uint8_t rhport) { bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); + const uint8_t ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); -#if CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP != 0 - uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); + #if CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP != 0 + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); uint16_t pma_addr2 = pma_addr >> 16; -#else - uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, false); + #else + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, false); uint16_t pma_addr2 = pma_addr; -#endif + #endif -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 btable_set_addr(ep_idx, 0, pma_addr); btable_set_addr(ep_idx, 1, pma_addr2); -#else + #else btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); - (void) pma_addr2; -#endif + (void)pma_addr2; + #endif - xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); - xfer->ep_idx = ep_idx; + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer->ep_idx = ep_idx; return true; } -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { (void)rhport; - uint8_t const ep_addr = desc_ep->bEndpointAddress; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); + const uint8_t ep_addr = desc_ep->bEndpointAddress; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_idx = xfer->ep_idx; xfer->max_packet_size = tu_edpt_packet_size(desc_ep); uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_TX | USB_EP_CTR_RX; -#if FSDEV_USE_SBUF_ISO != 0 + #if FSDEV_USE_SBUF_ISO != 0 ep_reg |= USB_EP_KIND; ep_change_status(&ep_reg, dir, EP_STAT_DISABLED); @@ -688,12 +682,12 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) } else { ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); } -#else + #else ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); ep_change_dtog(&ep_reg, dir, 0); ep_change_dtog(&ep_reg, (tusb_dir_t)(1 - dir), 1); -#endif + #endif ep_write(ep_idx, ep_reg, true); @@ -702,17 +696,17 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { - uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR - bool const is_iso = ep_is_iso(ep_reg); + const bool is_iso = ep_is_iso(ep_reg); uint8_t buf_id; -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = is_iso; -#else + #else bool const dbl_buf = false; -#endif + #endif if (dbl_buf) { buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0; } else { @@ -739,9 +733,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { - (void) rhport; + (void)rhport; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); const uint8_t ep_idx = xfer->ep_idx; if (dir == TUSB_DIR_IN) { @@ -752,11 +746,11 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); -#if FSDEV_USE_SBUF_ISO == 0 + #if FSDEV_USE_SBUF_ISO == 0 bool const dbl_buf = ep_is_iso(ep_reg); -#else + #else bool const dbl_buf = false; -#endif + #endif if (dbl_buf) { btable_set_rx_bufsize(ep_idx, 0, cnt); btable_set_rx_bufsize(ep_idx, 1, cnt); @@ -771,29 +765,29 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { - (void) is_isr; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; xfer->queued_len = 0; return edpt_xfer(rhport, ep_num, dir); } -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { - (void) is_isr; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; xfer->queued_len = 0; return edpt_xfer(rhport, ep_num, dir); @@ -801,10 +795,10 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + const uint8_t ep_idx = xfer->ep_idx; uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); @@ -816,10 +810,10 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); - uint8_t const ep_idx = xfer->ep_idx; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + const uint8_t ep_idx = xfer->ep_idx; uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); @@ -839,7 +833,7 @@ void dcd_int_disable(uint8_t rhport) { fsdev_int_disable(rhport); } -#if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) + #if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU) void dcd_connect(uint8_t rhport) { fsdev_connect(rhport); } @@ -847,6 +841,6 @@ void dcd_connect(uint8_t rhport) { void dcd_disconnect(uint8_t rhport) { fsdev_disconnect(rhport); } -#endif + #endif #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 69440aa32..c53e345b0 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -32,11 +32,11 @@ #include "common/tusb_common.h" #if CFG_TUD_ENABLED -#include "device/dcd.h" + #include "device/dcd.h" #endif #if CFG_TUH_ENABLED -#include "host/hcd.h" + #include "host/hcd.h" #endif #if defined(TUP_USBIP_FSDEV_STM32) @@ -56,41 +56,37 @@ extern "C" { // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // Both of these MUST be a multiple of 2, and are in byte units. #ifndef FSDEV_BTABLE_BASE -#define FSDEV_BTABLE_BASE 0U + #define FSDEV_BTABLE_BASE 0U #endif TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); -// FSDEV_PMA_SIZE is PMA buffer size in bytes. +// CFG_TUSB_FSDEV_PMA_SIZE is PMA buffer size in bytes. // - 512-byte devices, access with a stride of two words (use every other 16-bit address) // - 1024-byte devices, access with a stride of one word (use every 16-bit address) // - 2048-byte devices, access with 32-bit address // For purposes of accessing the packet -#if FSDEV_PMA_SIZE == 512 +#if CFG_TUSB_FSDEV_PMA_SIZE == 512 // 1x16 bit / word access scheme #define FSDEV_PMA_STRIDE 2 #define pma_access_scheme TU_ATTR_ALIGNED(4) -#elif FSDEV_PMA_SIZE == 1024 +#elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 // 2x16 bit / word access scheme - #define FSDEV_PMA_STRIDE 1 + #define FSDEV_PMA_STRIDE 1 #define pma_access_scheme -#elif FSDEV_PMA_SIZE == 2048 +#elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 // 32 bit access scheme #define FSDEV_BUS_32BIT - #define FSDEV_PMA_STRIDE 1 + #define FSDEV_PMA_STRIDE 1 #define pma_access_scheme #endif // The fsdev_bus_t type can be used for both register and PMA access necessities #ifdef FSDEV_BUS_32BIT - typedef uint32_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) +typedef uint32_t fsdev_bus_t; #else - typedef uint16_t fsdev_bus_t; - #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) - #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) +typedef uint16_t fsdev_bus_t; #endif enum { @@ -124,77 +120,77 @@ typedef union { } ep32[FSDEV_EP_COUNT][2]; } fsdev_btable_t; -TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); +TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT * 8 * FSDEV_PMA_STRIDE, "size is not correct"); +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT * 8 <= CFG_TUSB_FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); -#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) +#define FSDEV_BTABLE ((volatile fsdev_btable_t *)(FSDEV_PMA_BASE + FSDEV_PMA_STRIDE * (FSDEV_BTABLE_BASE))) typedef struct { volatile pma_access_scheme fsdev_bus_t value; } fsdev_pma_buf_t; -#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t *)(FSDEV_PMA_BASE + FSDEV_PMA_STRIDE * (_addr))) //--------------------------------------------------------------------+ // Registers Typedef //--------------------------------------------------------------------+ // volatile 32-bit aligned -#define _va32 volatile TU_ATTR_ALIGNED(4) +#define _va32 volatile TU_ATTR_ALIGNED(4) typedef struct { struct { _va32 fsdev_bus_t reg; - }ep[FSDEV_EP_COUNT]; - - _va32 uint32_t RESERVED7[8]; // Reserved - _va32 fsdev_bus_t CNTR; // 40: Control register - _va32 fsdev_bus_t ISTR; // 44: Interrupt status register - _va32 fsdev_bus_t FNR; // 48: Frame number register - _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) + } ep[FSDEV_EP_COUNT]; + + _va32 uint32_t RESERVED7[8]; // Reserved + _va32 fsdev_bus_t CNTR; // 40: Control register + _va32 fsdev_bus_t ISTR; // 44: Interrupt status register + _va32 fsdev_bus_t FNR; // 48: Frame number register + _va32 fsdev_bus_t DADDR; // 4C: Device address register + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) } fsdev_regs_t; TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); -#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) +#define FSDEV_REG ((fsdev_regs_t *)FSDEV_REG_BASE) #ifndef USB_EPTX_STAT -#define USB_EPTX_STAT 0x0030U + #define USB_EPTX_STAT 0x0030U #endif #ifndef USB_EPRX_STAT -#define USB_EPRX_STAT 0x3000U + #define USB_EPRX_STAT 0x3000U #endif #ifndef USB_EPTX_STAT_Pos -#define USB_EPTX_STAT_Pos 4u + #define USB_EPTX_STAT_Pos 4u #endif #ifndef USB_EP_DTOG_TX_Pos -#define USB_EP_DTOG_TX_Pos 6u + #define USB_EP_DTOG_TX_Pos 6u #endif #ifndef USB_EP_CTR_TX_Pos -#define USB_EP_CTR_TX_Pos 7u + #define USB_EP_CTR_TX_Pos 7u #endif typedef enum { EP_STAT_DISABLED = 0, - EP_STAT_STALL = 1, - EP_STAT_NAK = 2, - EP_STAT_VALID = 3 -}ep_stat_t; + EP_STAT_STALL = 1, + EP_STAT_NAK = 2, + EP_STAT_VALID = 3 +} ep_stat_t; -#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) -#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) //--------------------------------------------------------------------+ // Endpoint Helper @@ -211,7 +207,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value fsdev_int_disable(0); } - FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t)value; if (need_exclusive) { fsdev_int_enable(0); @@ -226,11 +222,11 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb ep_write(ep_id, reg, false); } -TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } @@ -259,11 +255,11 @@ TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb ep_write(ch_id, reg, false); } -TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } -TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } @@ -281,8 +277,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uin TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; @@ -301,12 +297,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, ui TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; - cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; #endif } @@ -318,7 +314,7 @@ void fsdev_core_reset(void); void fsdev_deinit(void); // Aligned buffer size according to hardware -uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block); +uint16_t pma_align_buffer_size(uint16_t size, uint8_t *blsize, uint8_t *num_block); // Set RX buffer size void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount); diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 85ca88f1c..02dba05a6 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -281,7 +281,7 @@ // - Enable double buffering on devices with >1KB Packet Memory Area (PMA) // to improve isochronous transfer reliability and performance // - Disable on devices with limited PMA to conserve memory space - #if FSDEV_PMA_SIZE > 1024u + #if CFG_TUSB_FSDEV_PMA_SIZE > 1024u #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 1 #else #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0 diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c index f232f7d94..acdeccf6d 100644 --- a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c @@ -741,7 +741,7 @@ static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) { uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; addr += channel * TUSB_EPSIZE_BULK_FS * 2 + (dir == TUSB_DIR_IN ? TUSB_EPSIZE_BULK_FS : 0); - TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF); + TU_ASSERT(addr <= CFG_TUSB_FSDEV_PMA_SIZE, 0xFFFF); return addr; } diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 570b1c14c..c40703b09 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -856,8 +856,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; if (byte_count > 0) { - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; - tu_hwfifo_read(dwc2->fifo[0], edpt->buffer + xfer->xferred_bytes, byte_count, &access_mode); + tu_hwfifo_read(dwc2->fifo[0], edpt->buffer + xfer->xferred_bytes, byte_count, NULL); xfer->xferred_bytes += byte_count; xfer->fifo_bytes = byte_count; } @@ -908,8 +907,7 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { return true; } - const tu_hwfifo_access_t access_mode = {.data_stride = CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE}; - tu_hwfifo_write(dwc2->fifo[ch_id], edpt->buffer + xfer->fifo_bytes, xact_bytes, &access_mode); + tu_hwfifo_write(dwc2->fifo[ch_id], edpt->buffer + xfer->fifo_bytes, xact_bytes, NULL); xfer->fifo_bytes += xact_bytes; } } diff --git a/src/tusb_option.h b/src/tusb_option.h index 87aba6a6c..5135ff05b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -351,13 +351,13 @@ #if defined(TUP_USBIP_FSDEV) #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 - #if FSDEV_PMA_SIZE == 512 + #if CFG_TUSB_FSDEV_PMA_SIZE == 512 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase - #elif FSDEV_PMA_SIZE == 1024 + #elif CFG_TUSB_FSDEV_PMA_SIZE == 1024 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 2 // 16-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 2 // 16-bit address increase - #elif FSDEV_PMA_SIZE == 2048 + #elif CFG_TUSB_FSDEV_PMA_SIZE == 2048 #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32-bit data #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 // 32-bit address increase #endif -- cgit v1.3.1 From 2026391b171017a6f07bd0bdfaaa2bcd49a08e34 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Tue, 6 Jan 2026 01:10:39 +0700 Subject: fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/common/tusb_fifo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 5515ffb91..11e1a6069 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -119,7 +119,7 @@ extern "C" { typedef struct { uint8_t *buffer; // buffer pointer uint16_t depth; // max items - bool overwritable; // ovwerwritable when full + bool overwritable; // overwritable when full // 1 byte padding here volatile uint16_t wr_idx; // write index TODO maybe can drop volatile @@ -229,7 +229,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const // Hardware FIFO API // Special hardware FIFO/Buffer to hold USB data, usually requires certain access method these can be configured with // CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE (data width) and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE (address increment) -// Note: these usually has opposiite direction (read/write) to/from our software FIFO (tu_fifo_t) +// Note: these usually has opposite direction (read/write) to/from our software FIFO (tu_fifo_t) //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_hwfifo_write_from_fifo(volatile void *hwfifo, tu_fifo_t *f, uint16_t n, const tu_hwfifo_access_t *access_mode) { -- cgit v1.3.1 From 9de3e108b4d38677c5352786ef038600550598d3 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Tue, 6 Jan 2026 01:11:13 +0700 Subject: fix more typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/common/tusb_fifo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 11e1a6069..86ba59059 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -157,7 +157,7 @@ typedef struct { // Moving data from tusb_fifo <-> USB hardware FIFOs e.g. STM32s need to use a special stride mode which reads/writes // data in 2/4 byte chunks from/to a fixed address (USB FIFO register) instead of incrementing the address. For this use -// read/write access_mode with stride_mode = true. The STRIPE DATA and ADDR stride must be configured with +// read/write access_mode with stride_mode = true. The STRIDE DATA and ADDR stride must be configured with // CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE and CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE //--------------------------------------------------------------------+ -- cgit v1.3.1