diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 2c212a82b..510f82981 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -20,59 +20,56 @@ manufacturer: WCH #include "bsp/board_api.h" #include "board.h" -/* CH32v203 depending on variants can support 2 USB IPs: FSDEV and USBFS. +/* CH32v203 depending on variants can support 2 USB IPs: FSDEV (port0) and USBFS (port1). * By default, we use FSDEV, but you can explicitly select by define: * - CFG_TUD_WCH_USBIP_FSDEV * - CFG_TUD_WCH_USBIP_USBFS */ -// USBFS -__attribute__((interrupt)) __attribute__((used)) -void USBHD_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_USBFS +// Port0: USBD (fsdev) +__attribute__((interrupt)) __attribute__((used)) void USB_LP_CAN1_RX0_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV tud_int_handler(0); #endif - #if defined(CFG_TUH_WCH_USBIP_USBFS) && CFG_TUH_WCH_USBIP_USBFS - tuh_int_handler(0); - #endif } -__attribute__((interrupt)) __attribute__((used)) -void USBHDWakeUp_IRQHandler(void) { +__attribute__((interrupt)) __attribute__((used)) void USB_HP_CAN1_TX_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV + tud_int_handler(0); + #endif + +} + +__attribute__((interrupt)) __attribute__((used)) void USBWakeUp_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV + tud_int_handler(0); + #endif +} + +// Port1: USBFS +__attribute__((interrupt)) __attribute__((used)) void USBHD_IRQHandler(void) { + #if CFG_TUD_ENABLED && CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(1); + #endif + + #if CFG_TUH_ENABLED + tuh_int_handler(1); + #endif +} + +__attribute__((interrupt)) __attribute__((used)) void USBHDWakeUp_IRQHandler(void) { #if CFG_TUD_WCH_USBIP_USBFS tud_int_handler(0); #endif } -// USBD (fsdev) -__attribute__((interrupt)) __attribute__((used)) -void USB_LP_CAN1_RX0_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_FSDEV - tud_int_handler(0); - #endif -} - -__attribute__((interrupt)) __attribute__((used)) -void USB_HP_CAN1_TX_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_FSDEV - tud_int_handler(0); - #endif - -} - -__attribute__((interrupt)) __attribute__((used)) -void USBWakeUp_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_FSDEV - tud_int_handler(0); - #endif -} - - +//--------------------------------------------------------------------+ +// Board API +//--------------------------------------------------------------------+ #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -__attribute__((interrupt)) -void SysTick_Handler(void) { +__attribute__((interrupt)) void SysTick_Handler(void) { SysTick->SR = 0; system_ticks++; } @@ -111,7 +108,7 @@ void board_init(void) { #ifdef UART_DEV UART_CLOCK_EN(); GPIO_InitTypeDef usart_init = { - .GPIO_Pin = UART_TX_PIN, + .GPIO_Pin = UART_TX_PIN | UART_RX_PIN, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_Mode = GPIO_Mode_AF_PP, }; @@ -122,7 +119,7 @@ void board_init(void) { .USART_WordLength = USART_WordLength_8b, .USART_StopBits = USART_StopBits_1, .USART_Parity = USART_Parity_No, - .USART_Mode = USART_Mode_Tx, + .USART_Mode = USART_Mode_Tx | USART_Mode_Rx, .USART_HardwareFlowControl = USART_HardwareFlowControl_None, }; USART_Init(UART_DEV, &usart); @@ -192,9 +189,19 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { } int board_uart_read(uint8_t *buf, int len) { - (void) buf; - (void) len; +#ifdef UART_DEV + int count; + for (count = 0; count < len; count++) { + if (USART_GetFlagStatus(UART_DEV, USART_FLAG_RXNE) == RESET) { + break; + } + buf[count] = USART_ReceiveData(UART_DEV); + } + return count; +#else + (void) buf; (void) len; return 0; +#endif } int board_uart_write(void const *buf, int len) { @@ -210,7 +217,3 @@ int board_uart_write(void const *buf, int len) { return len; } - -//-------------------------------------------------------------------- -// Neopixel -//-------------------------------------------------------------------- diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index 6092abc8d..10044d5b3 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -16,9 +16,12 @@ set(FAMILY_MCUS CH32V20X CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") # Port0 use FSDev, Port1 use USBFS -if (NOT DEFINED PORT) - set(PORT 0) -endif() +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 0) +endif () + +# only port1 support host mode +set(RHPORT_HOST 1) #------------------------------------ # BOARD_TARGET @@ -56,19 +59,16 @@ function(add_board_target BOARD_TARGET) ) target_compile_definitions(${BOARD_TARGET} PUBLIC CH32V20x_${MCU_VARIANT} + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUH_RHPORT=${RHPORT_HOST} ) - if (PORT EQUAL 0) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CFG_TUD_WCH_USBIP_FSDEV=1 - CFG_TUH_WCH_USBIP_USBFS=1 - ) - elseif (PORT EQUAL 1) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CFG_TUD_WCH_USBIP_USBFS=1 - ) + if (RHPORT_DEVICE EQUAL 0) + target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUD_WCH_USBIP_FSDEV=1) + elseif (RHPORT_DEVICE EQUAL 1) + target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUH_WCH_USBIP_USBFS=1) else() - message(FATAL_ERROR "Invalid PORT ${PORT}") + message(FATAL_ERROR "Invalid RHPORT_DEVICE ${RHPORT_DEVICE}") endif() update_board(${BOARD_TARGET}) @@ -133,8 +133,6 @@ function(family_configure_example TARGET RTOS) ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - # Flashing family_add_bin_hex(${TARGET}) family_flash_openocd_wch(${TARGET}) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 2ee2132bf..a08ed79c8 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -503,11 +503,17 @@ #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) - // v20x support both FSDEV (USBD) and USBFS, default to FSDEV + // v20x support both port0 FSDEV (USBD) and port1 USBFS #define TUP_USBIP_WCH_USBFS + + #ifndef CFG_TUH_WCH_USBIP_USBFS + #define CFG_TUH_WCH_USBIP_USBFS 1 + #endif + #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_CH32 + // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) #define CFG_TUD_WCH_USBIP_USBFS 0 #endif diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index f8bf3c889..4a208b9df 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && CFG_TUD_WCH_USBIP_USBHS +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && defined(CFG_TUD_WCH_USBIP_USBHS) && CFG_TUD_WCH_USBIP_USBHS #include "ch32_usbhs_reg.h" #include "device/dcd.h" diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 800390989..d176f40c5 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -37,20 +37,20 @@ #include "ch32v20x.h" #include "ch32v20x_usb.h" -void osal_task_delay(uint32_t msec) { - uint32_t start = board_millis(); - while (board_millis() - start < msec) {} -} - #define USBFS_RX_BUF_LEN 64 #define USBFS_TX_BUF_LEN 64 -__attribute__((aligned(4))) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN]; -__attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; +TU_ATTR_ALIGNED(4) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN]; +TU_ATTR_ALIGNED(4) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; #define USB_XFER_TIMEOUT_MILLIS 100 // #define USB_INTERRUPT_XFER_TIMEOUT_MILLIS 1 -#define PANIC(...) do { printf("%s() L%d: ", __func__, __LINE__); printf("\r\n[PANIC] " __VA_ARGS__); while (true) { } } while (false) +#define PANIC(...) \ + do { \ + printf("%s() L%d: ", __func__, __LINE__); \ + printf("\r\n[PANIC] " __VA_ARGS__); \ + while (true) {} \ + } while (false) #define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__) @@ -70,106 +70,87 @@ __attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; // Endpoint status -typedef struct usb_edpt -{ - // Is this a valid struct - bool configured; +typedef struct usb_edpt { + // Is this a valid struct + bool configured; - uint8_t dev_addr; - uint8_t ep_addr; - uint8_t max_packet_size; + uint8_t dev_addr; + uint8_t ep_addr; + uint8_t max_packet_size; - uint8_t xfer_type; + uint8_t xfer_type; - // Data toggle (0 or not 0) for DATA0/1 - uint8_t data_toggle; + // Data toggle (0 or not 0) for DATA0/1 + uint8_t data_toggle; } usb_edpt_t; - static usb_edpt_t usb_edpt_list[CFG_TUH_DEVICE_MAX * 6] = {}; - typedef struct usb_current_xfer_st { - bool is_busy; - uint8_t dev_addr; - uint8_t ep_addr; - // Xfer started time in millis for timeout - uint32_t start_ms; - uint8_t* buffer; - uint16_t bufferlen; - uint16_t xferred_len; + bool is_busy; + uint8_t dev_addr; + uint8_t ep_addr; + // Xfer started time in millis for timeout + uint32_t start_ms; + uint8_t *buffer; + uint16_t bufferlen; + uint16_t xferred_len; } usb_current_xfer_t; static volatile usb_current_xfer_t usb_current_xfer_info = {}; - -static usb_edpt_t* get_edpt_record(uint8_t dev_addr, uint8_t ep_addr) -{ - for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) - { - usb_edpt_t* cur = &usb_edpt_list[i]; - if (cur->configured && cur->dev_addr == dev_addr && cur->ep_addr == ep_addr) - { - return cur; - } +static usb_edpt_t *get_edpt_record(uint8_t dev_addr, uint8_t ep_addr) { + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) { + usb_edpt_t *cur = &usb_edpt_list[i]; + if (cur->configured && cur->dev_addr == dev_addr && cur->ep_addr == ep_addr) { + return cur; } - return NULL; + } + return NULL; } -static usb_edpt_t* get_empty_record_slot(void) -{ - for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) - { - if (!usb_edpt_list[i].configured) - { - return &usb_edpt_list[i]; - } +static usb_edpt_t *get_empty_record_slot(void) { + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) { + if (!usb_edpt_list[i].configured) { + return &usb_edpt_list[i]; } - return NULL; + } + return NULL; } -static usb_edpt_t* add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) -{ - usb_edpt_t* slot = get_empty_record_slot(); - if (slot == NULL) { - PANIC("add_edpt_record(0x%02x, 0x%02x, ...) no slot for new record\r\n", dev_addr, ep_addr); - } - TU_ASSERT(slot != NULL, NULL); +static usb_edpt_t *add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) { + usb_edpt_t *slot = get_empty_record_slot(); + if (slot == NULL) { + PANIC("add_edpt_record(0x%02x, 0x%02x, ...) no slot for new record\r\n", dev_addr, ep_addr); + } + TU_ASSERT(slot != NULL, NULL); - slot->dev_addr = dev_addr; - slot->ep_addr = ep_addr; - slot->max_packet_size = max_packet_size; - slot->xfer_type = xfer_type; - slot->data_toggle = 0; + slot->dev_addr = dev_addr; + slot->ep_addr = ep_addr; + slot->max_packet_size = max_packet_size; + slot->xfer_type = xfer_type; + slot->data_toggle = 0; - slot->configured = true; + slot->configured = true; - return slot; + return slot; } -static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) -{ - usb_edpt_t* ret = get_edpt_record(dev_addr, ep_addr); - if (ret != NULL) - { - return ret; - } - else - { - return add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type); - } +static usb_edpt_t *get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) { + usb_edpt_t *ret = get_edpt_record(dev_addr, ep_addr); + if (ret != NULL) { + return ret; + } else { + return add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type); + } } - -static void remove_edpt_record_for_device(uint8_t dev_addr) -{ - for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) - { - if (usb_edpt_list[i].configured && usb_edpt_list[i].dev_addr == dev_addr) - { - usb_edpt_list[i].configured = false; - } +static void remove_edpt_record_for_device(uint8_t dev_addr) { + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) { + if (usb_edpt_list[i].configured && usb_edpt_list[i].dev_addr == dev_addr) { + usb_edpt_list[i].configured = false; } + } } // static void dump_edpt_record_list() { @@ -183,544 +164,462 @@ static void remove_edpt_record_for_device(uint8_t dev_addr) // } // } - static bool interrupt_enabled = false; /** Enable or disable USBFS Host function */ -static void hardware_init_host(bool enabled) -{ - // Reset USBOTG module - USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL; +static void hardware_init_host(bool enabled) { + // Reset USBOTG module + USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL; - osal_task_delay(1); + tusb_time_delay_ms_api(1); + USBOTG_H_FS->BASE_CTRL = 0; + + if (!enabled) { + // Disable all feature USBOTG_H_FS->BASE_CTRL = 0; - - if (!enabled) - { - // Disable all feature - USBOTG_H_FS->BASE_CTRL = 0; - } - else - { - // Enable USB Host features - // NVIC_DisableIRQ(USBFS_IRQn); - hcd_int_disable(0); - USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; - USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN; - USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf; - USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf; - // USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT; - USBOTG_H_FS->INT_EN = USBFS_UIE_DETECT; - } + } else { + // Enable USB Host features + // NVIC_DisableIRQ(USBFS_IRQn); + hcd_int_disable(0); + USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; + USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN; + USBOTG_H_FS->HOST_RX_DMA = (uint32_t) USBFS_RX_Buf; + USBOTG_H_FS->HOST_TX_DMA = (uint32_t) USBFS_TX_Buf; + // USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT; + USBOTG_H_FS->INT_EN = USBFS_UIE_DETECT; + } } -static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) -{ - LOG_CH32_USBFSH("hardware_start_xfer(pid=%s(0x%02x), ep_addr=0x%02x, toggle=%d)\r\n", - pid == USB_PID_IN ? "IN" : pid == USB_PID_OUT ? "OUT" : pid == USB_PID_SETUP ? "SETUP" : "(other)", - pid, ep_addr, data_toggle); +static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) { + LOG_CH32_USBFSH("hardware_start_xfer(pid=%s(0x%02x), ep_addr=0x%02x, toggle=%d)\r\n", + pid == USB_PID_IN ? "IN" : pid == USB_PID_OUT ? "OUT" + : pid == USB_PID_SETUP ? "SETUP" + : "(other)", + pid, ep_addr, data_toggle); - // if (pid == USB_PID_IN) - // { // FIXME: long delay needed (at release build) about 30msec - // loopdelay(SystemCoreClock / 1000 * 30); - // } + // if (pid == USB_PID_IN) + // { // FIXME: long delay needed (at release build) about 30msec + // loopdelay(SystemCoreClock / 1000 * 30); + // } - uint8_t pid_edpt = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0f); - USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; - USBOTG_H_FS->HOST_RX_CTRL = (data_toggle != 0) ? USBFS_UH_R_TOG : 0; - USBOTG_H_FS->HOST_EP_PID = pid_edpt; - USBOTG_H_FS->INT_EN |= USBFS_UIE_TRANSFER; - USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; - return true; + uint8_t pid_edpt = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0f); + USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; + USBOTG_H_FS->HOST_RX_CTRL = (data_toggle != 0) ? USBFS_UH_R_TOG : 0; + USBOTG_H_FS->HOST_EP_PID = pid_edpt; + USBOTG_H_FS->INT_EN |= USBFS_UIE_TRANSFER; + USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; + return true; } /** Set device address to communicate */ -static void hardware_update_device_address(uint8_t dev_addr) -{ - // Keep the bit of GP_BIT. Other 7bits are actual device address. - USBOTG_H_FS->DEV_ADDR = (USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | (dev_addr & USBFS_USB_ADDR_MASK); +static void hardware_update_device_address(uint8_t dev_addr) { + // Keep the bit of GP_BIT. Other 7bits are actual device address. + USBOTG_H_FS->DEV_ADDR = (USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | (dev_addr & USBFS_USB_ADDR_MASK); } /** Set port speed */ -static void hardware_update_port_speed(tusb_speed_t speed) -{ - LOG_CH32_USBFSH("hardware_update_port_speed(%s)\r\n", speed == TUSB_SPEED_FULL ? "Full" : speed == TUSB_SPEED_LOW ? "Low" : "(invalid)"); - switch (speed) { +static void hardware_update_port_speed(tusb_speed_t speed) { + LOG_CH32_USBFSH("hardware_update_port_speed(%s)\r\n", speed == TUSB_SPEED_FULL ? "Full" : speed == TUSB_SPEED_LOW ? "Low" + : "(invalid)"); + switch (speed) { case TUSB_SPEED_LOW: - USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED; - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED; - USBOTG_H_FS->HOST_SETUP |= USBFS_UH_PRE_PID_EN; - return; + USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED; + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_PRE_PID_EN; + return; case TUSB_SPEED_FULL: - USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED; - USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; - USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN; - return; + USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED; + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; + USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN; + return; default: - PANIC("hardware_update_port_speed(%d)\r\n", speed); - } + PANIC("hardware_update_port_speed(%d)\r\n", speed); + } } - static void hardware_set_port_address_speed(uint8_t dev_addr) { - hardware_update_device_address(dev_addr); - tusb_speed_t rhport_speed = hcd_port_speed_get(0); - tusb_speed_t dev_speed = tuh_speed_get(dev_addr); - hardware_update_port_speed(dev_speed); - if (rhport_speed == TUSB_SPEED_FULL && dev_speed == TUSB_SPEED_LOW) { - USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; - } + hardware_update_device_address(dev_addr); + tusb_speed_t rhport_speed = hcd_port_speed_get(0); + tusb_speed_t dev_speed = tuh_speed_get(dev_addr); + hardware_update_port_speed(dev_speed); + if (rhport_speed == TUSB_SPEED_FULL && dev_speed == TUSB_SPEED_LOW) { + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; + } } - -static bool hardware_device_attached(void) -{ - return USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH; +static bool hardware_device_attached(void) { + return USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH; } - //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) -{ - (void)rhport; - (void)rh_init; - hardware_init_host(true); +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void) rhport; + (void) rh_init; + hardware_init_host(true); - return true; + return true; } -bool hcd_deinit(uint8_t rhport) -{ - (void)rhport; - hardware_init_host(false); +bool hcd_deinit(uint8_t rhport) { + (void) rhport; + hardware_init_host(false); - return true; + return true; } - static bool int_state_for_portreset = false; -void hcd_port_reset(uint8_t rhport) -{ - (void)rhport; - LOG_CH32_USBFSH("hcd_port_reset()\r\n"); - int_state_for_portreset = interrupt_enabled; - // NVIC_DisableIRQ(USBFS_IRQn); - hcd_int_disable(rhport); - hardware_update_device_address(0x00); +void hcd_port_reset(uint8_t rhport) { + (void) rhport; + LOG_CH32_USBFSH("hcd_port_reset()\r\n"); + int_state_for_portreset = interrupt_enabled; + // NVIC_DisableIRQ(USBFS_IRQn); + hcd_int_disable(rhport); + hardware_update_device_address(0x00); - // USBOTG_H_FS->HOST_SETUP = 0x00; + // USBOTG_H_FS->HOST_SETUP = 0x00; - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; - return; + return; } -void hcd_port_reset_end(uint8_t rhport) -{ - (void)rhport; - LOG_CH32_USBFSH("hcd_port_reset_end()\r\n"); +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; + LOG_CH32_USBFSH("hcd_port_reset_end()\r\n"); - USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; - osal_task_delay(2); + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; + tusb_time_delay_ms_api(2); - if ((USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN) == 0) - { - if (hcd_port_speed_get(0) == TUSB_SPEED_LOW) - { - hardware_update_port_speed(TUSB_SPEED_LOW); - } + if ((USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN) == 0) { + if (hcd_port_speed_get(0) == TUSB_SPEED_LOW) { + hardware_update_port_speed(TUSB_SPEED_LOW); } + } - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; - USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; - // Suppress the attached event - USBOTG_H_FS->INT_FG |= USBFS_UIF_DETECT; + // Suppress the attached event + USBOTG_H_FS->INT_FG |= USBFS_UIF_DETECT; - if (int_state_for_portreset) { - hcd_int_enable(rhport); - } - - return; + if (int_state_for_portreset) { + hcd_int_enable(rhport); + } } -bool hcd_port_connect_status(uint8_t rhport) -{ - (void)rhport; +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; - return hardware_device_attached(); + return hardware_device_attached(); } -tusb_speed_t hcd_port_speed_get(uint8_t rhport) -{ - (void)rhport; - if (USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL) - { - return TUSB_SPEED_LOW; - } - else - { - return TUSB_SPEED_FULL; - } +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + if (USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL) { + return TUSB_SPEED_LOW; + } else { + return TUSB_SPEED_FULL; + } } // Close all opened endpoint belong to this device -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; - LOG_CH32_USBFSH("hcd_device_close(%d, 0x%02x)\r\n", rhport, dev_addr); - remove_edpt_record_for_device(dev_addr); +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + LOG_CH32_USBFSH("hcd_device_close(%d, 0x%02x)\r\n", rhport, dev_addr); + remove_edpt_record_for_device(dev_addr); +} +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + + return board_millis(); +} + +void hcd_int_enable(uint8_t rhport) { + (void) rhport; + NVIC_EnableIRQ(USBFS_IRQn); + interrupt_enabled = true; +} + +void hcd_int_disable(uint8_t rhport) { + (void) rhport; + NVIC_DisableIRQ(USBFS_IRQn); + interrupt_enabled = false; +} + +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void) rhport; + (void) in_isr; + + if (USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT) { + // Clear the flag + USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; + // Read the detection state + bool attached = hardware_device_attached(); + LOG_CH32_USBFSH("hcd_int_handler() attached = %d\r\n", attached ? 1 : 0); + if (attached) { + hcd_event_device_attach(rhport, true); + } else { + hcd_event_device_remove(rhport, true); + } return; -} + } -uint32_t hcd_frame_number(uint8_t rhport) -{ - (void)rhport; + if (USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) { + // Disable transfer interrupt + USBOTG_H_FS->INT_EN &= ~USBFS_UIE_TRANSFER; + // Clear the flag + // USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; + // Copy PID and Endpoint + uint8_t pid_edpt = USBOTG_H_FS->HOST_EP_PID; + uint8_t status = USBOTG_H_FS->INT_ST; + uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR & USBFS_USB_ADDR_MASK; + // Clear register to stop transfer + // USBOTG_H_FS->HOST_EP_PID = 0x00; - return board_millis(); -} + LOG_CH32_USBFSH("hcd_int_handler() pid_edpt=0x%02x\r\n", pid_edpt); -void hcd_int_enable(uint8_t rhport) -{ - (void)rhport; - NVIC_EnableIRQ(USBFS_IRQn); - interrupt_enabled = true; + uint8_t request_pid = pid_edpt >> 4; + uint8_t response_pid = status & USBFS_UIS_H_RES_MASK; + uint8_t ep_addr = pid_edpt & 0x0f; + if (request_pid == USB_PID_IN) { + ep_addr |= 0x80; + } - return; -} + usb_edpt_t *edpt_info = get_edpt_record(dev_addr, ep_addr); + if (edpt_info == NULL) { + PANIC("\r\nget_edpt_record(0x%02x, 0x%02x) returned NULL in USBHD_IRQHandler\r\n", dev_addr, ep_addr); + } -void hcd_int_disable(uint8_t rhport) -{ - (void)rhport; - NVIC_DisableIRQ(USBFS_IRQn); - interrupt_enabled = false; + if (status & USBFS_UIS_TOG_OK) { + edpt_info->data_toggle ^= 0x01; - return; -} - -void hcd_int_handler(uint8_t rhport, bool in_isr) -{ - (void)rhport; - (void)in_isr; - - if (USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT) - { - // Clear the flag - USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; - // Read the detection state - bool attached = hardware_device_attached(); - LOG_CH32_USBFSH("hcd_int_handler() attached = %d\r\n", attached ? 1 : 0); - if (attached) - { - hcd_event_device_attach(rhport, true); + switch (request_pid) { + case USB_PID_SETUP: + case USB_PID_OUT: { + uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN; + usb_current_xfer_info.bufferlen -= tx_len; + usb_current_xfer_info.xferred_len += tx_len; + if (usb_current_xfer_info.bufferlen == 0) { + LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.xferred_len); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.xferred_len, XFER_RESULT_SUCCESS, true); + return; + } else { + LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); + usb_current_xfer_info.buffer += tx_len; + uint16_t copylen = USBFS_TX_BUF_LEN; + if (copylen > usb_current_xfer_info.bufferlen) { + copylen = usb_current_xfer_info.bufferlen; + } + memcpy(USBFS_TX_Buf, usb_current_xfer_info.buffer, copylen); + hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + return; + } } - else - { - hcd_event_device_remove(rhport, true); + case USB_PID_IN: { + uint16_t received_len = USBOTG_H_FS->RX_LEN; + usb_current_xfer_info.xferred_len += received_len; + uint16_t xferred_len = usb_current_xfer_info.xferred_len; + LOG_CH32_USBFSH("Read %d bytes\r\n", received_len); + // if (received_len > 0 && (usb_current_xfer_info.buffer == NULL || usb_current_xfer_info.bufferlen == 0)) { + // PANIC("Data received but buffer not set\r\n"); + // } + memcpy(usb_current_xfer_info.buffer, USBFS_RX_Buf, received_len); + usb_current_xfer_info.buffer += received_len; + if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.bufferlen)) { + // USB device sent all data. + LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); + return; + } else { + // USB device may send more data. + LOG_CH32_USBFSH("Read more data\r\n"); + hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); + return; + } + } + default: { + PANIC("Unknown PID: 0x%02x\n", request_pid); + } + } + } else { + if (response_pid == USB_PID_STALL) { + LOG_CH32_USBFSH("STALL response\r\n"); + hcd_edpt_clear_stall(0, dev_addr, ep_addr); + edpt_info->data_toggle = 0; + hardware_start_xfer(request_pid, ep_addr, 0); + return; + } else if (response_pid == USB_PID_NAK) { + LOG_CH32_USBFSH("NAK reposense\r\n"); + uint32_t elapsed_time = board_millis() - usb_current_xfer_info.start_ms; + if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT) { + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); + } else if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) { + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + } else { + hardware_start_xfer(request_pid, ep_addr, edpt_info->data_toggle); } return; + } else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1) { + LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + return; + } else { + LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + return; + } } - - if (USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) - { - // Disable transfer interrupt - USBOTG_H_FS->INT_EN &= ~USBFS_UIE_TRANSFER; - // Clear the flag - // USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; - // Copy PID and Endpoint - uint8_t pid_edpt = USBOTG_H_FS->HOST_EP_PID; - uint8_t status = USBOTG_H_FS->INT_ST; - uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR & USBFS_USB_ADDR_MASK; - // Clear register to stop transfer - // USBOTG_H_FS->HOST_EP_PID = 0x00; - - LOG_CH32_USBFSH("hcd_int_handler() pid_edpt=0x%02x\r\n", pid_edpt); - - uint8_t request_pid = pid_edpt >> 4; - uint8_t response_pid = status & USBFS_UIS_H_RES_MASK; - uint8_t ep_addr = pid_edpt & 0x0f; - if (request_pid == USB_PID_IN) - { - ep_addr |= 0x80; - } - - usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); - if (edpt_info == NULL) - { - PANIC("\r\nget_edpt_record(0x%02x, 0x%02x) returned NULL in USBHD_IRQHandler\r\n", dev_addr, ep_addr); - } - - if (status & USBFS_UIS_TOG_OK) - { - edpt_info->data_toggle ^= 0x01; - - switch (request_pid) - { - case USB_PID_SETUP: - case USB_PID_OUT: - { - uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN; - usb_current_xfer_info.bufferlen -= tx_len; - usb_current_xfer_info.xferred_len += tx_len; - if (usb_current_xfer_info.bufferlen == 0) - { - LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.xferred_len); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.xferred_len, XFER_RESULT_SUCCESS, true); - return; - } - else - { - LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); - usb_current_xfer_info.buffer += tx_len; - uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > usb_current_xfer_info.bufferlen) - { - copylen = usb_current_xfer_info.bufferlen; - } - memcpy(USBFS_TX_Buf, usb_current_xfer_info.buffer, copylen); - hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); - return; - } - } - case USB_PID_IN: - { - uint16_t received_len = USBOTG_H_FS->RX_LEN; - usb_current_xfer_info.xferred_len += received_len; - uint16_t xferred_len = usb_current_xfer_info.xferred_len; - LOG_CH32_USBFSH("Read %d bytes\r\n", received_len); - // if (received_len > 0 && (usb_current_xfer_info.buffer == NULL || usb_current_xfer_info.bufferlen == 0)) { - // PANIC("Data received but buffer not set\r\n"); - // } - memcpy(usb_current_xfer_info.buffer, USBFS_RX_Buf, received_len); - usb_current_xfer_info.buffer += received_len; - if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.bufferlen)) - { - // USB device sent all data. - LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); - return; - } - else - { - // USB device may send more data. - LOG_CH32_USBFSH("Read more data\r\n"); - hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); - return; - } - } - default: - { - PANIC("Unknown PID: 0x%02x\n", request_pid); - } - } - } - else - { - if (response_pid == USB_PID_STALL) - { - LOG_CH32_USBFSH("STALL response\r\n"); - hcd_edpt_clear_stall(0, dev_addr, ep_addr); - edpt_info->data_toggle = 0; - hardware_start_xfer(request_pid, ep_addr, 0); - return; - } - else if (response_pid == USB_PID_NAK) - { - LOG_CH32_USBFSH("NAK reposense\r\n"); - uint32_t elapsed_time = board_millis() - usb_current_xfer_info.start_ms; - if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT) - { - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); - } - else if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) - { - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); - } - else - { - hardware_start_xfer(request_pid, ep_addr, edpt_info->data_toggle); - } - return; - } - else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1) - { - LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); - return; - } - else - { - LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); - return; - } - } - } + } } //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void)rhport; - uint8_t ep_addr = ep_desc->bEndpointAddress; - uint8_t ep_num = tu_edpt_number(ep_addr); - uint16_t max_packet_size = ep_desc->wMaxPacketSize; - uint8_t xfer_type = ep_desc->bmAttributes.xfer; - LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d,xfer_type=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size, xfer_type); +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc) { + (void) rhport; + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint8_t ep_num = tu_edpt_number(ep_addr); + uint16_t max_packet_size = ep_desc->wMaxPacketSize; + uint8_t xfer_type = ep_desc->bmAttributes.xfer; + LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d,xfer_type=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size, xfer_type); - if (ep_num == 0x00) - { - TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); - TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); - } - else - { - TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); - } + if (ep_num == 0x00) { + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); + } else { + TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); + } + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; - USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; + hardware_set_port_address_speed(dev_addr); - hardware_set_port_address_speed(dev_addr); - - return true; + return true; } -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ - (void)rhport; +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { + (void) rhport; - LOG_CH32_USBFSH("hcd_edpt_xfer(%d, 0x%02x, 0x%02x, ...)\r\n", rhport, dev_addr, ep_addr); + LOG_CH32_USBFSH("hcd_edpt_xfer(%d, 0x%02x, 0x%02x, ...)\r\n", rhport, dev_addr, ep_addr); - while (usb_current_xfer_info.is_busy) { } + while (usb_current_xfer_info.is_busy) {} + usb_current_xfer_info.is_busy = true; - usb_current_xfer_info.is_busy = true; + usb_edpt_t *edpt_info = get_edpt_record(dev_addr, ep_addr); + if (edpt_info == NULL) { + PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); + } - usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); - if (edpt_info == NULL) - { - PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); - } - - hardware_set_port_address_speed(dev_addr); - - usb_current_xfer_info.dev_addr = dev_addr; - usb_current_xfer_info.ep_addr = ep_addr; - usb_current_xfer_info.buffer = buffer; - usb_current_xfer_info.bufferlen = buflen; - usb_current_xfer_info.start_ms = board_millis(); - usb_current_xfer_info.xferred_len = 0; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); - return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); - } - else - { - LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); - uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > buflen) - { - copylen = buflen; - } - USBOTG_H_FS->HOST_TX_LEN = copylen; - memcpy(USBFS_TX_Buf, buffer, copylen); - return hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + hardware_set_port_address_speed(dev_addr); + + usb_current_xfer_info.dev_addr = dev_addr; + usb_current_xfer_info.ep_addr = ep_addr; + usb_current_xfer_info.buffer = buffer; + usb_current_xfer_info.bufferlen = buflen; + usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.xferred_len = 0; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); + return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); + } else { + LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); + uint16_t copylen = USBFS_TX_BUF_LEN; + if (copylen > buflen) { + copylen = buflen; } + USBOTG_H_FS->HOST_TX_LEN = copylen; + memcpy(USBFS_TX_Buf, buffer, copylen); + return hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + } } -bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - (void) rhport; - (void) dev_addr; - (void) ep_addr; +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; - return false; + return false; } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void)rhport; - - while (usb_current_xfer_info.is_busy) { } +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; - usb_current_xfer_info.is_busy = true; + while (usb_current_xfer_info.is_busy) {} - LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet); + usb_current_xfer_info.is_busy = true; - hardware_set_port_address_speed(dev_addr); + LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet); - usb_edpt_t* edpt_info_tx = get_edpt_record(dev_addr, 0x00); - usb_edpt_t* edpt_info_rx = get_edpt_record(dev_addr, 0x80); - TU_ASSERT(edpt_info_tx != NULL, false); - TU_ASSERT(edpt_info_rx != NULL, false); + hardware_set_port_address_speed(dev_addr); - // Initialize data toggle (SETUP always starts with DATA0) - // Data toggle for OUT is toggled in hcd_int_handler() - edpt_info_tx->data_toggle = 0; - // Data toggle for IN must be set 0x01 manually. - edpt_info_rx->data_toggle = 0x01; - const uint16_t setup_packet_datalen = 8; - memcpy(USBFS_TX_Buf, setup_packet, setup_packet_datalen); - USBOTG_H_FS->HOST_TX_LEN = setup_packet_datalen; - uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00; - usb_current_xfer_info.dev_addr = dev_addr; - usb_current_xfer_info.ep_addr = ep_addr; - usb_current_xfer_info.start_ms = board_millis(); - usb_current_xfer_info.buffer = USBFS_TX_Buf; - usb_current_xfer_info.bufferlen = setup_packet_datalen; - usb_current_xfer_info.xferred_len = 0; + usb_edpt_t *edpt_info_tx = get_edpt_record(dev_addr, 0x00); + usb_edpt_t *edpt_info_rx = get_edpt_record(dev_addr, 0x80); + TU_ASSERT(edpt_info_tx != NULL, false); + TU_ASSERT(edpt_info_rx != NULL, false); - hardware_start_xfer(USB_PID_SETUP, 0, 0); + // Initialize data toggle (SETUP always starts with DATA0) + // Data toggle for OUT is toggled in hcd_int_handler() + edpt_info_tx->data_toggle = 0; + // Data toggle for IN must be set 0x01 manually. + edpt_info_rx->data_toggle = 0x01; + const uint16_t setup_packet_datalen = 8; + memcpy(USBFS_TX_Buf, setup_packet, setup_packet_datalen); + USBOTG_H_FS->HOST_TX_LEN = setup_packet_datalen; + uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00; + usb_current_xfer_info.dev_addr = dev_addr; + usb_current_xfer_info.ep_addr = ep_addr; + usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.buffer = USBFS_TX_Buf; + usb_current_xfer_info.bufferlen = setup_packet_datalen; + usb_current_xfer_info.xferred_len = 0; - return true; + hardware_start_xfer(USB_PID_SETUP, 0, 0); + + return true; } -bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - (void) rhport; - (void) dev_addr; - LOG_CH32_USBFSH("hcd_edpt_clear_stall(rhport=%d, dev_addr=0x%02x, ep_addr=0x%02x)\r\n", rhport, dev_addr, ep_addr); - // PANIC("\r\install\r\n"); - uint8_t edpt_num = tu_edpt_number(ep_addr); - uint8_t setup_request_clear_stall[8] = { - 0x02, 0x01, 0x00, 0x00, edpt_num, 0x00, 0x00, 0x00 - }; - memcpy(USBFS_TX_Buf, setup_request_clear_stall, 8); - USBOTG_H_FS->HOST_TX_LEN = 8; +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + LOG_CH32_USBFSH("hcd_edpt_clear_stall(rhport=%d, dev_addr=0x%02x, ep_addr=0x%02x)\r\n", rhport, dev_addr, ep_addr); + // PANIC("\r\install\r\n"); + uint8_t edpt_num = tu_edpt_number(ep_addr); + uint8_t setup_request_clear_stall[8] = { + 0x02, 0x01, 0x00, 0x00, edpt_num, 0x00, 0x00, 0x00 + }; + memcpy(USBFS_TX_Buf, setup_request_clear_stall, 8); + USBOTG_H_FS->HOST_TX_LEN = 8; - bool prev_int_state = interrupt_enabled; - hcd_int_disable(0); + bool prev_int_state = interrupt_enabled; + hcd_int_disable(0); - USBOTG_H_FS->HOST_EP_PID = (USB_PID_SETUP << 4) | 0x00; - USBOTG_H_FS->INT_FG |= USBFS_UIF_TRANSFER; - while ((USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) == 0) { } - USBOTG_H_FS->HOST_EP_PID = 0; - uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; - (void)response_pid; - LOG_CH32_USBFSH("hcd_edpt_clear_stall() response pid=0x%02x\r\n", response_pid); + USBOTG_H_FS->HOST_EP_PID = (USB_PID_SETUP << 4) | 0x00; + USBOTG_H_FS->INT_FG |= USBFS_UIF_TRANSFER; + while ((USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) == 0) {} + USBOTG_H_FS->HOST_EP_PID = 0; + uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; + (void) response_pid; + LOG_CH32_USBFSH("hcd_edpt_clear_stall() response pid=0x%02x\r\n", response_pid); - if (prev_int_state) { + if (prev_int_state) { hcd_int_enable(0); - } + } - return true; + return true; } #endif