From d1c9bb663d1f10741b324a3405c0148efd743a9c Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Mon, 12 Sep 2022 11:42:35 +0800 Subject: [PATCH] update hpm host ehci glue --- CMakeLists.txt | 10 +- README.md | 2 +- README_zh.md | 2 +- demo/hpm/usb_device/src/usb_config.h | 86 ++- demo/hpm/usb_host/ram.icf | 2 +- demo/hpm/usb_host/src/main.c | 5 +- demo/hpm/usb_host/src/usb_config.h | 86 ++- port/ehci/usb_glue_hpm.c | 102 ++++ port/hpm/usb_hc_hpm.c | 850 --------------------------- 9 files changed, 195 insertions(+), 950 deletions(-) create mode 100644 port/ehci/usb_glue_hpm.c delete mode 100644 port/hpm/usb_hc_hpm.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f975ac1b..3ab0aec2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,11 +9,12 @@ sdk_inc(class/audio) sdk_inc(class/video) sdk_inc(class/hub) +sdk_compile_definitions(-DCONFIG_USB_ALIGN_SIZE=64) + if(CONFIG_CHERRYUSB_DEVICE) sdk_src(core/usbd_core.c) sdk_src(port/hpm/usb_dc_hpm.c) -sdk_compile_definitions(-DCONFIG_USB_HS -DCONFIG_USB_ALIGN_SIZE=64) -#sdk_compile_definitions(-DCONFIG_USB_DCACHE_ENABLE) +sdk_compile_definitions(-DCONFIG_USB_HS) if(CONFIG_CHERRYUSB_DEVICE_CDC) sdk_src(class/cdc/usbd_cdc.c) endif() @@ -40,9 +41,10 @@ endif() elseif(CONFIG_CHERRYUSB_HOST) sdk_src(core/usbh_core.c) -sdk_src(port/hpm/usb_hc_hpm.c) +sdk_src(class/hub/usbh_hub.c) +sdk_src(port/ehci/usb_hc_ehci.c) +sdk_src(port/ehci/usb_glue_hpm.c) sdk_src(osal/usb_osal_freertos.c) -sdk_compile_definitions(-DCONFIG_USB_ALIGN_SIZE=64) sdk_src(class/cdc/usbh_cdc_acm.c) sdk_src(class/msc/usbh_msc.c) sdk_src(class/hid/usbh_hid.c) diff --git a/README.md b/README.md index 621bdf0b..d00b9254 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ Note: After version 0.4.1, the dcd drivers have been refactored and some reposit |ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|latest | |ST | STM32F4 | dwc2 |[stm32f429_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f429igt6) [stm32f429_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32f429igt6)|latest | |ST | STM32H7 | dwc2 |[stm32h743_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32h743vbt6) [stm32h743_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32h743xih6)|latest | -|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.5.2 | +|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|latest | |WCH | CH32V307 | ch32_usbfs/ch32_usbhs|[ch32v307_repo](https://github.com/CherryUSB/cherryusb_ch32v307)|latest | |WCH | CH57x | ch58x |[ch57x_repo](https://github.com/CherryUSB/cherryusb_ch57x)|v0.4.1 | |Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 | diff --git a/README_zh.md b/README_zh.md index a58e8c3d..772e6ec6 100644 --- a/README_zh.md +++ b/README_zh.md @@ -126,7 +126,7 @@ USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [Ch |ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|latest | |ST | STM32F4 | dwc2 |[stm32f429_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f429igt6) [stm32f429_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32f429igt6)|latest | |ST | STM32H7 | dwc2 |[stm32h743_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32h743vbt6) [stm32h743_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32h743xih6)|latest | -|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|v0.5.2 | +|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|latest | |WCH | CH32V307 | ch32_usbfs/ch32_usbhs|[ch32v307_repo](https://github.com/CherryUSB/cherryusb_ch32v307)|latest | |WCH | CH57x | ch58x |[ch57x_repo](https://github.com/CherryUSB/cherryusb_ch57x)|v0.4.1 | |Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 | diff --git a/demo/hpm/usb_device/src/usb_config.h b/demo/hpm/usb_device/src/usb_config.h index 09c64014..430b3cb4 100644 --- a/demo/hpm/usb_device/src/usb_config.h +++ b/demo/hpm/usb_device/src/usb_config.h @@ -16,30 +16,31 @@ #define CONFIG_USB_PRINTF printf #endif -/* attribute data into no cache ram */ -#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) /* Enable print with color */ #define CONFIG_USB_PRINTF_COLOR_ENABLE -/* ================ USB DEVICE Configuration ================*/ +/* data align size when use dma */ +#ifndef CONFIG_USB_ALIGN_SIZE +#define CONFIG_USB_ALIGN_SIZE 4 +#endif -/* core */ +/* attribute data into no cache ram */ +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) + +/* ================= USB Device Stack Configuration ================ */ /* Ep0 max transfer buffer, specially for receiving data from ep0 out */ #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 + /* Setup packet log for debug */ // #define CONFIG_USBDEV_SETUP_LOG_PRINT + /* Check if the input descriptor is correct */ // #define CONFIG_USBDEV_DESC_CHECK + /* Enable test mode */ // #define CONFIG_USBDEV_TEST_MODE -/* cdc class */ - -// #define CONFIG_USBDEV_CDC_ACM_UART - -/* msc class */ - #ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE #define CONFIG_USBDEV_MSC_BLOCK_SIZE 512 #endif @@ -68,8 +69,6 @@ #endif #endif -/* audio class */ - #ifndef CONFIG_USBDEV_AUDIO_VERSION #define CONFIG_USBDEV_AUDIO_VERSION 0x0100 #endif @@ -78,59 +77,54 @@ #define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8 #endif -/* ================ USB HOST Configuration ================ */ +/* ================ USB HOST Stack Configuration ================== */ -#ifndef CONFIG_USBHOST_RHPORTS -#define CONFIG_USBHOST_RHPORTS 1 +#define CONFIG_USBHOST_RHPORTS 1 +#define CONFIG_USBHOST_EXTHUB_NUM 1 +#define CONFIG_USBHOST_EHPORTS 4 +#define CONFIG_USBHOST_INTF_NUM 6 +#define CONFIG_USBHOST_EP_NUM 4 + +#define CONFIG_USBHOST_DEV_NAMELEN 16 + +#ifndef CONFIG_USBHOST_PSC_PRIO +#define CONFIG_USBHOST_PSC_PRIO 4 +#endif +#ifndef CONFIG_USBHOST_PSC_STACKSIZE +#define CONFIG_USBHOST_PSC_STACKSIZE 2048 #endif -#ifndef CONFIG_USBHOST_EHPORTS -#define CONFIG_USBHOST_EHPORTS 4 -#endif +//#define CONFIG_USBHOST_GET_STRING_DESC -#ifndef CONFIG_USBHOST_PIPE_NUM -#define CONFIG_USBHOST_PIPE_NUM 10 -#endif - -#ifndef CONFIG_USBHOST_INTF_NUM -#define CONFIG_USBHOST_INTF_NUM 6 -#endif - -#ifndef CONFIG_USBHOST_EP_NUM -#define CONFIG_USBHOST_EP_NUM 4 -#endif +/* Ep0 max transfer buffer */ +#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512 #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT -#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000 +#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 #endif #ifndef CONFIG_USBHOST_MSC_TIMEOUT #define CONFIG_USBHOST_MSC_TIMEOUT 5000 #endif -#ifndef CONFIG_USBHOST_PSC_PRIO -#define CONFIG_USBHOST_PSC_PRIO 4 -#endif -#ifndef CONFIG_USBHOST_PSC_STACKSIZE -#define CONFIG_USBHOST_PSC_STACKSIZE 4096 -#endif +/* ================ USB Device Port Configuration ================*/ -#ifndef CONFIG_USBHOST_DEV_NAMELEN -#define CONFIG_USBHOST_DEV_NAMELEN 16 -#endif +//#define USBD_IRQHandler USBD_IRQHandler +//#define USB_BASE (0x40080000UL) +//#define USB_NUM_BIDIR_ENDPOINTS 4 -#define CONFIG_USBHOST_ASYNCH -//#define CONFIG_USBHOST_GET_STRING_DESC +/* ================ USB Host Port Configuration ==================*/ + +#define CONFIG_USBHOST_PIPE_NUM 10 /* ================ EHCI Configuration ================ */ -#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) -#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) -#define CONFIG_USB_EHCI_QH_NUM (10) -#define CONFIG_USB_EHCI_QTD_NUM (10) +#define CONFIG_USB_EHCI_HCCR_BASE (0) +#define CONFIG_USB_EHCI_HCOR_BASE (0xF2020000UL + 0x140) +#define CONFIG_EHCI_FRAME_LIST_SIZE 1024 // #define CONFIG_USB_EHCI_INFO_ENABLE // #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG -// #define CONFIG_USB_EHCI_PORT_POWER +#define CONFIG_USB_EHCI_PORT_POWER #endif diff --git a/demo/hpm/usb_host/ram.icf b/demo/hpm/usb_host/ram.icf index e74ef3cc..5228b442 100644 --- a/demo/hpm/usb_host/ram.icf +++ b/demo/hpm/usb_host/ram.icf @@ -10,7 +10,7 @@ define memory with size = 4G; define region CORE0_LM_SLV = [from 0x1000000 size 512k]; /* CORE0 LM slave */ define region CORE1_LM_SLV = [from 0x1180000 size 512k]; /* CORE1 LM slave */ define region AXI_SRAM = [from 0x1080000 size 700k]; /* reserve 256K for noncacheable region */ -define region CHERRYUSB_RAM = [from 0x1080000 + 700k size 64]; /* reserve 64B for cherryusb region */ +define region CHERRYUSB_RAM = [from 0x1080000 + 700k size 72]; /* reserve 64B for cherryusb region */ define region NONCACHEABLE_RAM = [from 0x1140000 size 256K]; define exported symbol __noncacheable_start__ = start of region NONCACHEABLE_RAM; diff --git a/demo/hpm/usb_host/src/main.c b/demo/hpm/usb_host/src/main.c index cb128c48..3b50fbad 100644 --- a/demo/hpm/usb_host/src/main.c +++ b/demo/hpm/usb_host/src/main.c @@ -15,9 +15,10 @@ #include "hpm_gpio_drv.h" #include "usbh_core.h" +extern void usbh_class_test(); + int main(void) { - l1c_dc_disable(); board_init(); board_init_gpio_pins(); board_init_usb_pins(); @@ -26,7 +27,9 @@ int main(void) gpio_write_pin(BOARD_LED_GPIO_CTRL, BOARD_LED_GPIO_INDEX, BOARD_LED_GPIO_PIN, BOARD_LED_ON_LEVEL); #endif + printf("Start usb host task...\r\n"); usbh_initialize(); + usbh_class_test(); vTaskStartScheduler(); for (;;) { ; diff --git a/demo/hpm/usb_host/src/usb_config.h b/demo/hpm/usb_host/src/usb_config.h index e01b709d..430b3cb4 100644 --- a/demo/hpm/usb_host/src/usb_config.h +++ b/demo/hpm/usb_host/src/usb_config.h @@ -16,30 +16,31 @@ #define CONFIG_USB_PRINTF printf #endif -/* attribute data into no cache ram */ -// #define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) /* Enable print with color */ #define CONFIG_USB_PRINTF_COLOR_ENABLE -/* ================ USB DEVICE Configuration ================*/ +/* data align size when use dma */ +#ifndef CONFIG_USB_ALIGN_SIZE +#define CONFIG_USB_ALIGN_SIZE 4 +#endif -/* core */ +/* attribute data into no cache ram */ +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) + +/* ================= USB Device Stack Configuration ================ */ /* Ep0 max transfer buffer, specially for receiving data from ep0 out */ #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 + /* Setup packet log for debug */ // #define CONFIG_USBDEV_SETUP_LOG_PRINT + /* Check if the input descriptor is correct */ // #define CONFIG_USBDEV_DESC_CHECK + /* Enable test mode */ // #define CONFIG_USBDEV_TEST_MODE -/* cdc class */ - -// #define CONFIG_USBDEV_CDC_ACM_UART - -/* msc class */ - #ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE #define CONFIG_USBDEV_MSC_BLOCK_SIZE 512 #endif @@ -68,8 +69,6 @@ #endif #endif -/* audio class */ - #ifndef CONFIG_USBDEV_AUDIO_VERSION #define CONFIG_USBDEV_AUDIO_VERSION 0x0100 #endif @@ -78,59 +77,54 @@ #define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8 #endif -/* ================ USB HOST Configuration ================ */ +/* ================ USB HOST Stack Configuration ================== */ -#ifndef CONFIG_USBHOST_RHPORTS -#define CONFIG_USBHOST_RHPORTS 1 +#define CONFIG_USBHOST_RHPORTS 1 +#define CONFIG_USBHOST_EXTHUB_NUM 1 +#define CONFIG_USBHOST_EHPORTS 4 +#define CONFIG_USBHOST_INTF_NUM 6 +#define CONFIG_USBHOST_EP_NUM 4 + +#define CONFIG_USBHOST_DEV_NAMELEN 16 + +#ifndef CONFIG_USBHOST_PSC_PRIO +#define CONFIG_USBHOST_PSC_PRIO 4 +#endif +#ifndef CONFIG_USBHOST_PSC_STACKSIZE +#define CONFIG_USBHOST_PSC_STACKSIZE 2048 #endif -#ifndef CONFIG_USBHOST_EHPORTS -#define CONFIG_USBHOST_EHPORTS 4 -#endif +//#define CONFIG_USBHOST_GET_STRING_DESC -#ifndef CONFIG_USBHOST_PIPE_NUM -#define CONFIG_USBHOST_PIPE_NUM 10 -#endif - -#ifndef CONFIG_USBHOST_INTF_NUM -#define CONFIG_USBHOST_INTF_NUM 6 -#endif - -#ifndef CONFIG_USBHOST_EP_NUM -#define CONFIG_USBHOST_EP_NUM 4 -#endif +/* Ep0 max transfer buffer */ +#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512 #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT -#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000 +#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 #endif #ifndef CONFIG_USBHOST_MSC_TIMEOUT #define CONFIG_USBHOST_MSC_TIMEOUT 5000 #endif -#ifndef CONFIG_USBHOST_PSC_PRIO -#define CONFIG_USBHOST_PSC_PRIO 4 -#endif -#ifndef CONFIG_USBHOST_PSC_STACKSIZE -#define CONFIG_USBHOST_PSC_STACKSIZE 4096 -#endif +/* ================ USB Device Port Configuration ================*/ -#ifndef CONFIG_USBHOST_DEV_NAMELEN -#define CONFIG_USBHOST_DEV_NAMELEN 16 -#endif +//#define USBD_IRQHandler USBD_IRQHandler +//#define USB_BASE (0x40080000UL) +//#define USB_NUM_BIDIR_ENDPOINTS 4 -#define CONFIG_USBHOST_ASYNCH -//#define CONFIG_USBHOST_GET_STRING_DESC +/* ================ USB Host Port Configuration ==================*/ + +#define CONFIG_USBHOST_PIPE_NUM 10 /* ================ EHCI Configuration ================ */ -#define CONFIG_USB_EHCI_HCCR_BASE (0x20072000) -#define CONFIG_USB_EHCI_HCOR_BASE (0x20072000 + 0x10) -#define CONFIG_USB_EHCI_QH_NUM (10) -#define CONFIG_USB_EHCI_QTD_NUM (10) +#define CONFIG_USB_EHCI_HCCR_BASE (0) +#define CONFIG_USB_EHCI_HCOR_BASE (0xF2020000UL + 0x140) +#define CONFIG_EHCI_FRAME_LIST_SIZE 1024 // #define CONFIG_USB_EHCI_INFO_ENABLE // #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG -// #define CONFIG_USB_EHCI_PORT_POWER +#define CONFIG_USB_EHCI_PORT_POWER #endif diff --git a/port/ehci/usb_glue_hpm.c b/port/ehci/usb_glue_hpm.c new file mode 100644 index 00000000..4f8baa03 --- /dev/null +++ b/port/ehci/usb_glue_hpm.c @@ -0,0 +1,102 @@ +#include "usbh_core.h" +#include "hpm_common.h" +#include "hpm_soc.h" +#include "hpm_usb_drv.h" + +#define USB_PHY_INIT_DELAY_COUNT (16U) /**< a delay count for USB phy initialization */ + +/* Initialize USB phy */ +static void usb_phy_init(USB_Type *ptr) +{ + uint32_t status; + + ptr->OTG_CTRL0 |= USB_OTG_CTRL0_OTG_UTMI_RESET_SW_MASK; /* set otg_utmi_reset_sw for naneng usbphy */ + ptr->OTG_CTRL0 &= ~USB_OTG_CTRL0_OTG_UTMI_SUSPENDM_SW_MASK; /* clr otg_utmi_suspend_m for naneng usbphy */ + ptr->PHY_CTRL1 &= ~USB_PHY_CTRL1_UTMI_CFG_RST_N_MASK; /* clr cfg_rst_n */ + + do { + status = USB_OTG_CTRL0_OTG_UTMI_RESET_SW_GET(ptr->OTG_CTRL0); /* wait for reset status */ + } while (status == 0); + + ptr->OTG_CTRL0 |= USB_OTG_CTRL0_OTG_UTMI_SUSPENDM_SW_MASK; /* set otg_utmi_suspend_m for naneng usbphy */ + + for (int i = 0; i < USB_PHY_INIT_DELAY_COUNT; i++) { + ptr->PHY_CTRL0 = USB_PHY_CTRL0_GPIO_ID_SEL_N_SET(0); /* used for delay */ + } + + ptr->OTG_CTRL0 &= ~USB_OTG_CTRL0_OTG_UTMI_RESET_SW_MASK; /* clear otg_utmi_reset_sw for naneng usbphy */ + + /* otg utmi clock detection */ + ptr->PHY_STATUS |= USB_PHY_STATUS_UTMI_CLK_VALID_MASK; /* write 1 to clear valid status */ + do { + status = USB_PHY_STATUS_UTMI_CLK_VALID_GET(ptr->PHY_STATUS); /* get utmi clock status */ + } while (status == 0); + + ptr->PHY_CTRL1 |= USB_PHY_CTRL1_UTMI_CFG_RST_N_MASK; /* set cfg_rst_n */ + + ptr->PHY_CTRL1 |= USB_PHY_CTRL1_UTMI_OTG_SUSPENDM_MASK; /* set otg_suspendm */ +} + +static void usb_host_mode_init(USB_Type *ptr) +{ + /* Set mode to host, must be set immediately after reset */ + ptr->USBMODE &= ~USB_USBMODE_CM_MASK; + ptr->USBMODE |= USB_USBMODE_CM_SET(3); + + /* Set the endian */ + ptr->USBMODE &= ~USB_USBMODE_ES_MASK; + + /* Set parallel interface signal */ + ptr->PORTSC1 &= ~USB_PORTSC1_STS_MASK; + + /* Set parallel transceiver width */ + ptr->PORTSC1 &= ~USB_PORTSC1_PTW_MASK; + + /* Not use interrupt threshold. */ + ptr->USBCMD &= ~USB_USBCMD_ITC_MASK; +} + +void usb_hc_low_level_init() +{ + usb_phy_init((USB_Type *)HPM_USB0_BASE); + intc_m_enable_irq(IRQn_USB0); +} + +void usb_hc_low_level2_init() +{ + usb_host_mode_init((USB_Type *)HPM_USB0_BASE); +} + +uint8_t usbh_get_port_speed(const uint8_t port) +{ + uint8_t speed; + + speed = usb_get_port_speed((USB_Type *)HPM_USB0_BASE); + + if (speed == 0x00) { + return USB_SPEED_FULL; + } + if (speed == 0x01) { + return USB_SPEED_LOW; + } + if (speed == 0x02) { + return USB_SPEED_HIGH; + } + + return 0; +} + +extern void USBH_IRQHandler(void); + +void isr_usb0(void) +{ + USBH_IRQHandler(); +} +SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usb0) + +#ifdef HPM_USB1_BASE +void isr_usb1(void) +{ +} +SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usb1) +#endif \ No newline at end of file diff --git a/port/hpm/usb_hc_hpm.c b/port/hpm/usb_hc_hpm.c deleted file mode 100644 index c9b6258d..00000000 --- a/port/hpm/usb_hc_hpm.c +++ /dev/null @@ -1,850 +0,0 @@ -#include "usbh_core.h" -#include "hpm_usb_host.h" -#include "hpm_common.h" -#include "hpm_soc.h" -#include "hpm_l1c_drv.h" -#include "board.h" - -#define HCD_MAX_ENDPOINT 16 - -struct hpm_ehci_pipe { - uint8_t ep_addr; - uint8_t dev_addr; - uint8_t *buffer; /* for dcache invalidate */ - volatile int result; /* The result of the transfer */ - volatile uint32_t xfrd; /* Bytes transferred (at end of transfer) */ - volatile bool waiter; /* True: Thread is waiting for a channel event */ - usb_osal_sem_t waitsem; /* Channel wait semaphore */ - usb_osal_mutex_t exclsem; /* Support mutually exclusive access */ -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; /* Transfer complete callback */ - void *arg; /* Argument that accompanies the callback */ -#endif -}; - -struct hpm_ehci_hcd { - struct hpm_ehci_pipe chan[HCD_MAX_ENDPOINT][2]; -} g_hpm_ehci_hcd; - -static inline uint32_t hpm_ehci_align32(uint32_t value) -{ - return (value & 0xFFFFFFE0UL); -} - -/*---------------------------------------------------------------------* - * Enum Declaration - *---------------------------------------------------------------------*/ -typedef enum { - hcd_int_mask_usb = HPM_BITSMASK(1, 0), - hcd_int_mask_error = HPM_BITSMASK(1, 1), - hcd_int_mask_port_change = HPM_BITSMASK(1, 2), - - hcd_int_mask_framelist_rollover = HPM_BITSMASK(1, 3), - hcd_int_mask_pci_host_system_error = HPM_BITSMASK(1, 4), - hcd_int_mask_async_advance = HPM_BITSMASK(1, 5), - hcd_int_mask_sof = HPM_BITSMASK(1, 7), - - hcd_int_mask_async = HPM_BITSMASK(1, 18), - hcd_int_mask_periodic = HPM_BITSMASK(1, 19), - - hcd_int_mask_all = hcd_int_mask_usb | hcd_int_mask_error | hcd_int_mask_port_change | - hcd_int_mask_framelist_rollover | hcd_int_mask_pci_host_system_error | - hcd_int_mask_async_advance | hcd_int_mask_sof | - hcd_int_mask_async | hcd_int_mask_periodic -} usb_interrupt_mask_t; -typedef struct -{ - USB_Type *regs; /* register base */ - const uint32_t irqnum; /* IRQ number */ -} hcd_controller_t; - -static const hcd_controller_t _hcd_controller[] = { - { .regs = (USB_Type *)HPM_USB0_BASE, .irqnum = IRQn_USB0 }, -#ifdef HPM_USB1_BASE - { .regs = (USB_Type *)HPM_USB1_BASE, .irqnum = IRQn_USB1 } -#endif -}; - -/*---------------------------------------------------------------------* - * Variable Definitions - *---------------------------------------------------------------------*/ -ATTR_PLACE_AT_NONCACHEABLE static usb_host_handle_t usb_host_handle; -ATTR_PLACE_AT_NONCACHEABLE static bool hcd_int_sta; -// clang-format off -ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(USB_SOC_HCD_DATA_RAM_ADDRESS_ALIGNMENT) static hcd_data_t _hcd_data; -// clang-format on - -bool hcd_init(uint8_t rhport) -{ - uint32_t int_mask; - - if (rhport > USB_SOC_MAX_COUNT) { - return false; - } - - usb_host_handle.rhport = rhport; - usb_host_handle.regs = _hcd_controller[rhport].regs; - usb_host_handle.hcd_data = &_hcd_data; - usb_host_handle.hcd_vbus_ctrl_cb = board_usb_vbus_ctrl; - - int_mask = hcd_int_mask_error | hcd_int_mask_port_change | hcd_int_mask_async_advance | - hcd_int_mask_periodic | hcd_int_mask_async | hcd_int_mask_framelist_rollover; - - usb_host_init(&usb_host_handle, int_mask, USB_HOST_FRAMELIST_SIZE); - - intc_m_enable_irq(_hcd_controller[rhport].irqnum); - return true; -} - -static int hpm_ehci_pipe_waitsetup(struct hpm_ehci_pipe *chan) -{ - size_t flags; - int ret = -ENODEV; - - flags = usb_osal_enter_critical_section(); - - if (usbh_get_port_connect_status(1)) { - - chan->waiter = true; - chan->result = -EBUSY; - chan->xfrd = 0; -#ifdef CONFIG_USBHOST_ASYNCH - chan->callback = NULL; - chan->arg = NULL; -#endif - ret = 0; - } - usb_osal_leave_critical_section(flags); - return ret; -} - -#ifdef CONFIG_USBHOST_ASYNCH -static int hpm_ehci_pipe_asynchsetup(struct hpm_ehci_pipe *chan, usbh_asynch_callback_t callback, void *arg) -{ - size_t flags; - int ret = -ENODEV; - - flags = usb_osal_enter_critical_section(); - - if (usbh_get_port_connect_status(1)) { - chan->waiter = false; - chan->result = -EBUSY; - chan->xfrd = 0; - chan->callback = callback; - chan->arg = arg; - - ret = 0; - } - - usb_osal_leave_critical_section(flags); - return ret; -} -#endif - -static int hpm_ehci_pipe_wait(struct hpm_ehci_pipe *chan, uint32_t timeout) -{ - int ret; - - /* wait until timeout or sem give */ - if (chan->waiter) { - ret = usb_osal_sem_take(chan->waitsem, timeout); - if (ret < 0) { - return ret; - } - } - - /* Sem give, check if giving from error isr */ - ret = chan->result; - - if (ret < 0) { - return ret; - } - return chan->xfrd; -} - -static void hpm_ehci_pipe_wakeup(struct hpm_ehci_pipe *chan) -{ - usbh_asynch_callback_t callback; - void *arg; - int nbytes; - - if (chan->waiter) { - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); - } -#ifdef CONFIG_USBHOST_ASYNCH - else if (chan->callback) { - callback = chan->callback; - arg = chan->arg; - nbytes = chan->xfrd; - chan->callback = NULL; - chan->arg = NULL; - if (chan->result < 0) { - nbytes = chan->result; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - if (((chan->ep_addr & 0x80) == 0x80) && (nbytes > 0)) { - l1c_dc_invalidate((uint32_t)chan->buffer, nbytes); - } -#endif - callback(arg, nbytes); - } -#endif -} - -__WEAK void usb_hc_low_level_init(void) -{ -} - -int usb_hc_sw_init(void) -{ - memset(&g_hpm_ehci_hcd, 0, sizeof(struct hpm_ehci_hcd)); - - for (uint8_t chidx = 0; chidx < HCD_MAX_ENDPOINT; chidx++) { - g_hpm_ehci_hcd.chan[chidx][0].exclsem = usb_osal_mutex_create(); - if (g_hpm_ehci_hcd.chan[chidx][0].exclsem == NULL) { - printf("no memory to alloc mutex\r\n"); - return -ENOMEM; - } - g_hpm_ehci_hcd.chan[chidx][0].waitsem = usb_osal_sem_create(0); - if (g_hpm_ehci_hcd.chan[chidx][0].exclsem == NULL) { - printf("no memory to alloc sem\r\n"); - return -ENOMEM; - } - g_hpm_ehci_hcd.chan[chidx][1].exclsem = usb_osal_mutex_create(); - if (g_hpm_ehci_hcd.chan[chidx][0].exclsem == NULL) { - printf("no memory to alloc mutex\r\n"); - return -ENOMEM; - } - g_hpm_ehci_hcd.chan[chidx][1].waitsem = usb_osal_sem_create(0); - if (g_hpm_ehci_hcd.chan[chidx][0].exclsem == NULL) { - printf("no memory to alloc sem\r\n"); - return -ENOMEM; - } - } - - return 0; -} - -int usb_hc_hw_init(void) -{ - usb_hc_low_level_init(); - hcd_init(0); - return 0; -} - -int usbh_reset_port(const uint8_t port) -{ - usb_host_port_reset(&usb_host_handle); - return 0; -} - -bool usbh_get_port_connect_status(const uint8_t port) -{ - return usb_host_get_port_ccs(&usb_host_handle); -} - -uint8_t usbh_get_port_speed(const uint8_t port) -{ - uint8_t speed = usb_host_get_port_speed(&usb_host_handle); - if (speed == 0) { - speed = USB_SPEED_FULL; - } else if (speed == 1) { - speed = USB_SPEED_LOW; - } else if (speed == 2) { - speed = USB_SPEED_HIGH; - } - return speed; -} - -int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed) -{ - struct hpm_ehci_pipe *chan; - int ret; - usb_desc_endpoint_t ep_desc; - - chan = (struct hpm_ehci_pipe *)ep; - - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - if (speed == 1) { - usb_host_handle.ep_speed = 1; - } else if (speed == 2) { - usb_host_handle.ep_speed = 0; - } else if (speed == 3) { - usb_host_handle.ep_speed = 2; - } - - usb_host_handle.hub_addr = 0; - usb_host_handle.hub_port = 0; - - ep_desc.bEndpointAddress = 0x00; - ep_desc.bmAttributes.xfer = 0x00; - ep_desc.wMaxPacketSize.size = ep_mps; - - chan->dev_addr = dev_addr; - usb_host_edpt_open(&usb_host_handle, dev_addr, &ep_desc); - - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) -{ - struct hpm_ehci_pipe *chan; - struct usbh_hubport *hport; - uint8_t speed; - usb_osal_sem_t waitsem; - usb_osal_mutex_t exclsem; - - usb_desc_endpoint_t ep_desc; - - hport = ep_cfg->hport; - - if (ep_desc.bmAttributes.xfer == 0) { - chan = &g_hpm_ehci_hcd.chan[0][0]; - } else { - if (ep_cfg->ep_addr & 0x80) { - chan = &g_hpm_ehci_hcd.chan[ep_cfg->ep_addr & 0x7f][1]; - } else { - chan = &g_hpm_ehci_hcd.chan[ep_cfg->ep_addr & 0x7f][0]; - } - } - - /* store variables */ - waitsem = chan->waitsem; - exclsem = chan->exclsem; - - memset(chan, 0, sizeof(struct hpm_ehci_pipe)); - - if (hport->speed == 1) { - usb_host_handle.ep_speed = 1; - } else if (hport->speed == 2) { - usb_host_handle.ep_speed = 0; - } else if (hport->speed == 3) { - usb_host_handle.ep_speed = 2; - } - - usb_host_handle.hub_addr = 0; - usb_host_handle.hub_port = 0; - - ep_desc.bEndpointAddress = ep_cfg->ep_addr; - ep_desc.bmAttributes.xfer = ep_cfg->ep_type; - ep_desc.wMaxPacketSize.size = ep_cfg->ep_mps; - - chan->ep_addr = ep_cfg->ep_addr; - chan->dev_addr = hport->dev_addr; - - usb_host_edpt_open(&usb_host_handle, hport->dev_addr, &ep_desc); - - /* restore variables */ - chan->waitsem = waitsem; - chan->exclsem = exclsem; - - *ep = (usbh_epinfo_t)chan; - return 0; -} - -int usbh_ep_free(usbh_epinfo_t ep) -{ - struct hpm_ehci_pipe *chan; - int ret; - - chan = (struct hpm_ehci_pipe *)ep; - - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - usb_osal_mutex_give(chan->exclsem); - return 0; -} - -int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer) -{ - struct hpm_ehci_pipe *chan; - int ret; - - chan = (struct hpm_ehci_pipe *)ep; - - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = hpm_ehci_pipe_waitsetup(chan); - if (ret < 0) { - goto error_out; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - l1c_dc_writeback((uint32_t)setup, 8); -#endif - usb_host_setup_send(&usb_host_handle, chan->dev_addr, (uint8_t *)setup); - ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - - if (setup->wLength && buffer) { - if (setup->bmRequestType & 0x80) { - chan->waiter = true; - chan->result = -EBUSY; - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, 0x80, buffer, setup->wLength); - ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - l1c_dc_invalidate((uint32_t)buffer, setup->wLength); -#endif - chan->waiter = true; - chan->result = -EBUSY; - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, 0x00, NULL, 0); - ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - } else { - chan->waiter = true; - chan->result = -EBUSY; - l1c_dc_writeback((uint32_t)buffer, setup->wLength); - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, 0x00, buffer, setup->wLength); - ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - - chan->waiter = true; - chan->result = -EBUSY; - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, 0x00, NULL, 0); - ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - } - } else { - chan->waiter = true; - chan->result = -EBUSY; - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, 0x80, NULL, 0); - ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto error_out; - } - } - - usb_osal_mutex_give(chan->exclsem); - return ret; -error_out: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - struct hpm_ehci_pipe *chan; - int ret; - - chan = (struct hpm_ehci_pipe *)ep; - - if (buffer && (((uint32_t)buffer) & 0x1f)) { - return -EINVAL; - } - - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = hpm_ehci_pipe_waitsetup(chan); - if (ret < 0) { - goto error_out; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x00) { - l1c_dc_writeback((uint32_t)buffer, buflen); - } -#endif - chan->buffer = buffer; - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, chan->ep_addr, buffer, buflen); - ret = hpm_ehci_pipe_wait(chan, timeout); - if (ret < 0) { - goto error_out; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x80) { - l1c_dc_invalidate((uint32_t)buffer, buflen); - } -#endif - usb_osal_mutex_give(chan->exclsem); - return ret; -error_out: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - return usbh_ep_bulk_transfer(ep, buffer, buflen, timeout); -} - -int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - struct hpm_ehci_pipe *chan; - int ret; - - chan = (struct hpm_ehci_pipe *)ep; - - if (buffer && (((uint32_t)buffer) & 0x1f)) { - return -EINVAL; - } - - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = hpm_ehci_pipe_asynchsetup(chan, callback, arg); - if (ret < 0) { - goto error_out; - } -#ifdef CONFIG_USB_DCACHE_ENABLE - if ((chan->ep_addr & 0x80) == 0x00) { - l1c_dc_writeback((uint32_t)buffer, buflen); - } -#endif - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, chan->ep_addr, buffer, buflen); - -error_out: - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - return usbh_ep_bulk_async_transfer(ep, buffer, buflen, callback, arg); -} - -int usb_ep_cancel(usbh_epinfo_t ep) -{ - struct hpm_ehci_pipe *chan; - int ret; - size_t flags; -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; - void *arg; -#endif - - chan = (struct hpm_ehci_pipe *)ep; - - flags = usb_osal_enter_critical_section(); - - chan->result = -ESHUTDOWN; -#ifdef CONFIG_USBHOST_ASYNCH - /* Extract the callback information */ - callback = chan->callback; - arg = chan->arg; - chan->callback = NULL; - chan->arg = NULL; - chan->xfrd = 0; -#endif - usb_osal_leave_critical_section(flags); - - /* Is there a thread waiting for this transfer to complete? */ - - if (chan->waiter) { - /* Wake'em up! */ - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); - } -#ifdef CONFIG_USBHOST_ASYNCH - /* No.. is an asynchronous callback expected when the transfer completes? */ - else if (callback) { - /* Then perform the callback */ - callback(arg, -ESHUTDOWN); - } -#endif - return 0; -} - -/*---------------------------------------------------------------------* - * HCD Interrupt Handler - *---------------------------------------------------------------------*/ -/* async_advance is handshake between usb stack & ehci controller. - * This isr mean it is safe to modify previously removed queue head from async list. - * In tinyusb, queue head is only removed when device is unplugged. - */ -static void async_advance_isr(usb_host_handle_t *handle) -{ - hcd_qhd_t *qhd_pool = handle->hcd_data->qhd_pool; - - for (uint32_t i = 0; i < HCD_MAX_ENDPOINT; i++) { - if (qhd_pool[i].removing) { - qhd_pool[i].removing = 0; - qhd_pool[i].used = 0; - } - } -} - -static void port_connect_status_change_isr(usb_host_handle_t *handle) -{ - struct hpm_ehci_pipe *chan; - /* NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device */ - if (usb_host_get_port_ccs(handle)) { - usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1); - } else { /* device unplugged */ - for (uint8_t chidx = 0; chidx < HCD_MAX_ENDPOINT; chidx++) { - for (uint8_t j = 0; j < 2; j++) { - chan = &g_hpm_ehci_hcd.chan[chidx][j]; - if (chan->waiter) { - chan->result = -ENXIO; - hpm_ehci_pipe_wakeup(chan); - } - } - } - usb_host_device_close(&usb_host_handle, 1); - usbh_event_notify_handler(USBH_EVENT_DISCONNECTED, 1); - } -} - -static void qhd_xfer_complete_isr(hcd_qhd_t *p_qhd) -{ - struct hpm_ehci_pipe *chan; - bool is_ioc; - - while (p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) { - /* TD need to be freed and removed from qhd, before invoking callback */ - is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0); - p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; - - p_qhd->p_qtd_list_head->used = 0; /* free QTD */ - usb_host_qtd_remove_1st_from_qhd(p_qhd); - - if (is_ioc) { - if (p_qhd->ep_number == 0) { - chan = &g_hpm_ehci_hcd.chan[0][0]; - } else { - if (p_qhd->qtd_overlay.pid == usb_pid_in) { - chan = &g_hpm_ehci_hcd.chan[p_qhd->ep_number][1]; - } else { - chan = &g_hpm_ehci_hcd.chan[p_qhd->ep_number][0]; - } - } - - chan->xfrd += p_qhd->total_xferred_bytes; - chan->result = 0; - - p_qhd->total_xferred_bytes = 0; - hpm_ehci_pipe_wakeup(chan); - } - } -} - -static void async_list_xfer_complete_isr(hcd_qhd_t *const async_head) -{ - hcd_qhd_t *p_qhd = async_head; - - do { - if (!p_qhd->qtd_overlay.halted) { /* halted or error is processed in error isr */ - qhd_xfer_complete_isr(p_qhd); - } - - p_qhd = usb_host_qhd_next(p_qhd); - p_qhd = (hcd_qhd_t *)sys_address_to_core_local_mem(USB_HOST_MCU_CORE, (uint32_t)p_qhd); - - } while (p_qhd != async_head); /* async list traversal, stop if loop around */ -} - -static void period_list_xfer_complete_isr(usb_host_handle_t *handle, uint8_t interval_ms) -{ - uint16_t max_loop = 0; - uint32_t const period_1ms_addr = (uint32_t)usb_host_get_period_head(handle, 1); - hcd_link_t next_item = *usb_host_get_period_head(handle, interval_ms); - hcd_qhd_t *p_qhd_int; - - /* TODO abstract max loop guard for period */ - while (!next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == hpm_ehci_align32(next_item.address)) && - max_loop < (HCD_MAX_ENDPOINT + usb_max_itd + usb_max_sitd) * 1) { - switch (next_item.type) { - case usb_qtype_qhd: - p_qhd_int = (hcd_qhd_t *)hpm_ehci_align32(next_item.address); - if (!p_qhd_int->qtd_overlay.halted) { - qhd_xfer_complete_isr(p_qhd_int); - } - - break; - - case usb_qtype_itd: - case usb_qtype_sitd: - case usb_qtype_fstn: - - default: - break; - } - - next_item = *usb_host_list_next(&next_item); - max_loop++; - } -} - -static void qhd_xfer_error_isr(usb_host_handle_t *handle, hcd_qhd_t *p_qhd) -{ - struct hpm_ehci_pipe *chan; - hcd_qtd_t *p_setup; - - if ((p_qhd->dev_addr != 0 && p_qhd->qtd_overlay.halted) || /* addr0 cannot be protocol STALL */ - usb_host_qhd_has_xact_error(p_qhd)) { - /* no error bits are set, endpoint is halted due to STALL */ - p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; - - if (p_qhd->ep_number == 0) { - chan = &g_hpm_ehci_hcd.chan[0][0]; - } else { - if (p_qhd->qtd_overlay.pid == usb_pid_in) { - chan = &g_hpm_ehci_hcd.chan[p_qhd->ep_number][1]; - } else { - chan = &g_hpm_ehci_hcd.chan[p_qhd->ep_number][0]; - } - } - - if (p_qhd->qtd_overlay.babble_err) { - chan->result = -EPERM; - } - if (p_qhd->qtd_overlay.xact_err) { - chan->result = -EIO; - } - if (p_qhd->qtd_overlay.buffer_err) { - chan->result = -EIO; - } - - /* TODO skip unplugged device */ - - p_qhd->p_qtd_list_head->used = 0; /* free QTD */ - usb_host_qtd_remove_1st_from_qhd(p_qhd); - - if (0 == p_qhd->ep_number) { - /* control cannot be halted --> clear all qtd list */ - p_qhd->p_qtd_list_head = NULL; - p_qhd->p_qtd_list_tail = NULL; - - p_qhd->qtd_overlay.next.terminate = 1; - p_qhd->qtd_overlay.alternate.terminate = 1; - p_qhd->qtd_overlay.halted = 0; - - p_setup = usb_host_qtd_control(handle, p_qhd->dev_addr); - p_setup->used = 0; - } - - p_qhd->total_xferred_bytes = 0; - hpm_ehci_pipe_wakeup(chan); - } -} - -static void xfer_error_isr(usb_host_handle_t *handle) -{ - hcd_qhd_t *const async_head = usb_host_qhd_async_head(handle); - hcd_qhd_t *p_qhd = async_head; - hcd_qhd_t *p_qhd_int; - hcd_link_t next_item, *p; - - /*------------- async list -------------*/ - do { - qhd_xfer_error_isr(handle, p_qhd); - p_qhd = usb_host_qhd_next(p_qhd); - p_qhd = (hcd_qhd_t *)sys_address_to_core_local_mem(USB_HOST_MCU_CORE, (uint32_t)p_qhd); - } while (p_qhd != async_head); /* async list traversal, stop if loop around */ - - /*------------- TODO refractor period list -------------*/ - uint32_t const period_1ms_addr = (uint32_t)usb_host_get_period_head(handle, 1); - for (uint8_t interval_ms = 1; interval_ms <= USB_HOST_FRAMELIST_SIZE; interval_ms *= 2) { - next_item = *usb_host_get_period_head(handle, interval_ms); - - /* TODO abstract max loop guard for period */ - while (!next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == hpm_ehci_align32(next_item.address))) { - switch (next_item.type) { - case usb_qtype_qhd: - p_qhd_int = (hcd_qhd_t *)hpm_ehci_align32(next_item.address); - qhd_xfer_error_isr(handle, p_qhd_int); - break; - - case usb_qtype_itd: - case usb_qtype_sitd: - case usb_qtype_fstn: - - default: - break; - } - - p = usb_host_list_next(&next_item); - p = (hcd_link_t *)sys_address_to_core_local_mem(USB_HOST_MCU_CORE, (uint32_t)p); - next_item = *p; - } - } -} - -/*------------- Host Controller Driver's Interrupt Handler -------------*/ -void hcd_int_handler(uint8_t rhport) -{ - uint32_t status; - usb_host_handle_t *handle = &usb_host_handle; - - /* Acknowledge handled interrupt */ - status = usb_host_status_flags(handle); - status &= usb_host_interrupts(handle); - usb_host_clear_status_flags(handle, status); - - if (status == 0) { - return; - } - - if (status & hcd_int_mask_framelist_rollover) { - handle->hcd_data->uframe_number += (USB_HOST_FRAMELIST_SIZE << 3); - } - - if (status & hcd_int_mask_port_change) { - if (usb_host_port_csc(handle)) { - port_connect_status_change_isr(handle); - } - } - - if (status & hcd_int_mask_error) { - xfer_error_isr(handle); - } - - /*------------- some QTD/SITD/ITD with IOC set is completed -------------*/ - if (status & hcd_int_mask_async) { - async_list_xfer_complete_isr(usb_host_qhd_async_head(handle)); - } - - if (status & hcd_int_mask_periodic) { - for (uint8_t i = 1; i <= USB_HOST_FRAMELIST_SIZE; i *= 2) { - period_list_xfer_complete_isr(handle, i); - } - } - - /*------------- There is some removed async previously -------------*/ - if (status & hcd_int_mask_async_advance) { /* need to place after EHCI_INT_MASK_ASYNC */ - async_advance_isr(handle); - } -} - -void isr_usb0(void) -{ - hcd_int_handler(0); -} -SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usb0) - -#ifdef HPM_USB1_BASE -void isr_usb1(void) -{ - hcd_int_handler(1); -} -SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usb1) -#endif \ No newline at end of file