From ecea890fdc7a0dc4b92a365f0455b7b91258d543 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 Mar 2024 16:56:13 +0700 Subject: [PATCH 1/9] use usbreset to reset built-in usb 2.0 hub VIA Labs before each test --- .github/workflows/build_esp.yml | 16 +++++++++++----- .github/workflows/cmake_arm.yml | 16 +++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index 07cbf3552..b44da51e6 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -86,11 +86,17 @@ jobs: # USB bus on rpi4 is not stable, reset it before testing - name: Reset USB bus run: | - for port in $(lspci | grep USB | cut -d' ' -f1); do - echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind; - sleep 0.1; - echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind; - done + lsusb + lsusb -t + # reset VIA Labs 2.0 hub + usbreset 001/002 + + # legacy code + #for port in $(lspci | grep USB | cut -d' ' -f1); do + # echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind; + # sleep 0.1; + # echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind; + #done - name: Checkout test/hil uses: actions/checkout@v4 diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 732e9b9df..c44d3780e 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -141,11 +141,17 @@ jobs: # USB bus on rpi4 is not stable, reset it before testing - name: Reset USB bus run: | - for port in $(lspci | grep USB | cut -d' ' -f1); do - echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind; - sleep 0.1; - echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind; - done + lsusb + lsusb -t + # reset VIA Labs 2.0 hub + usbreset 001/002 + + # legacy code + #for port in $(lspci | grep USB | cut -d' ' -f1); do + # echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind; + # sleep 0.1; + # echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind; + #done - name: Checkout test/hil uses: actions/checkout@v4 From 7f1e327be3feca54cef56a3fadf49465fa452c06 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 Mar 2024 17:13:02 +0700 Subject: [PATCH 2/9] add sudo usbreset --- .github/workflows/build_esp.yml | 2 +- .github/workflows/cmake_arm.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index b44da51e6..d283c6535 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -89,7 +89,7 @@ jobs: lsusb lsusb -t # reset VIA Labs 2.0 hub - usbreset 001/002 + sudo usbreset 001/002 # legacy code #for port in $(lspci | grep USB | cut -d' ' -f1); do diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index c44d3780e..1e5f61e0e 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -144,7 +144,7 @@ jobs: lsusb lsusb -t # reset VIA Labs 2.0 hub - usbreset 001/002 + sudo usbreset 001/002 # legacy code #for port in $(lspci | grep USB | cut -d' ' -f1); do From 62864d53560baa0b23a1bbc4ea82faf403ac01dc Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Thu, 28 Mar 2024 12:12:07 +0700 Subject: [PATCH 3/9] Update labeler.yml --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index b4a2cdafa..4733c6f06 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -14,7 +14,7 @@ jobs: - name: Label New Issue or PR uses: actions/github-script@v7 with: - github-token: ${{ secrets.API_TOKEN_GITHUB }} + github-token: ${{ secrets.GITHUB_TOKEN }} script: | let label = ''; let username = ''; From 275e2f318ec17ba3956eb89965831ad5dff402be Mon Sep 17 00:00:00 2001 From: duckylotl <163729266+duckylotl@users.noreply.github.com> Date: Thu, 28 Mar 2024 10:27:07 +0100 Subject: [PATCH 4/9] forward declare board_millis for OPT_OS_CUSTOM --- hw/bsp/board_api.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 0c8a35924..3b9f211a2 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -116,6 +116,7 @@ static inline uint32_t board_millis(void) { #elif CFG_TUSB_OS == OPT_OS_CUSTOM // Implement your own board_millis() in any of .c file +uint32_t board_millis(void); #else #error "board_millis() is not implemented for this OS" From 0da1da942a735bcac7b48786a511a38b02519e88 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Mar 2024 16:32:02 +0700 Subject: [PATCH 5/9] enhance hub removal using while loop to unroll recursive instead of event queue. --- src/host/usbh.c | 117 +++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 60 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 1edc43fd6..71691fad6 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1138,43 +1138,42 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \ return (uint8_t) result -uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, + void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len); } -uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len); } -uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, + void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len); } -uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, + void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len); } -uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, + void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len); } -uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, + void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len); } -uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, + void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len); } -uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) -{ +uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, + void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); } @@ -1210,57 +1209,55 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// // TODO mark as disconnected in ISR, also handle dev0 + uint32_t removing_hubs = 0; + do { + for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { + usbh_device_t* dev = &_usbh_devices[dev_id]; + uint8_t const daddr = dev_id + 1; -#if 0 - // index as hub addr, value is hub port (0xFF for invalid) - uint8_t removing_hubs[CFG_TUH_HUB]; - memset(removing_hubs, TUSB_INDEX_INVALID_8, sizeof(removing_hubs)); + // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub + if (dev->rhport == rhport && dev->connected && + (hub_addr == 0 || dev->hub_addr == hub_addr) && + (hub_port == 0 || dev->hub_port == hub_port)) { + TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); - removing_hubs[hub_addr-CFG_TUH_DEVICE_MAX] = hub_port; + if (is_hub_addr(daddr)) { + TU_LOG_USBH(" is a HUB device %u\r\n", daddr); + // marking this hub to run the loop on its children next (unroll recursive) + removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); + } else { + // Invoke callback before closing driver (maybe call it later ?) + if (tuh_umount_cb) tuh_umount_cb(daddr); + } - // consecutive non-removing hub - uint8_t nop_count = 0; -#endif + // Close class driver + for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { + usbh_class_driver_t const* driver = get_driver(drv_id); + if (driver) driver->close(daddr); + } - for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { - usbh_device_t *dev = &_usbh_devices[dev_id]; - uint8_t const daddr = dev_id + 1; + hcd_device_close(rhport, daddr); + clear_device(dev); - // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub - if (dev->rhport == rhport && dev->connected && - (hub_addr == 0 || dev->hub_addr == hub_addr) && - (hub_port == 0 || dev->hub_port == hub_port)) { - TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); - - if (is_hub_addr(daddr)) { - TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - - // Submit removed event If the device itself is a hub (un-rolled recursive) - // TODO a better to unroll recursrive is using array of removing_hubs and mark it here - hcd_event_t event; - event.rhport = rhport; - event.event_id = HCD_EVENT_DEVICE_REMOVE; - event.connection.hub_addr = daddr; - event.connection.hub_port = 0; - - hcd_event_handler(&event, false); - } else { - // Invoke callback before closing driver (maybe call it later ?) - if (tuh_umount_cb) tuh_umount_cb(daddr); + // abort on-going control xfer on this device if any + if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); } - - // Close class driver - for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbh_class_driver_t const * driver = get_driver(drv_id); - if ( driver ) driver->close(daddr); - } - - hcd_device_close(rhport, daddr); - clear_device(dev); - // abort on-going control xfer if any - if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); } - } + + if (removing_hubs == 0) break; + + // find the next hub to process + for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { + if (tu_bit_test(removing_hubs, h_id)) { + removing_hubs &= ~TU_BIT(h_id); + + // update hub_addr and hub_port for next loop + hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX; + hub_port = 0; + break; + } + } + } while(1); } //--------------------------------------------------------------------+ From 3dcb7362aa8f0e710157da4b28be44abb2c26230 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Mar 2024 19:18:20 +0700 Subject: [PATCH 6/9] fix build when CFG_TUH_HUB == 0 --- src/host/usbh.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 71691fad6..f2dc2f7c1 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1219,11 +1219,10 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu if (dev->rhport == rhport && dev->connected && (hub_addr == 0 || dev->hub_addr == hub_addr) && (hub_port == 0 || dev->hub_port == hub_port)) { - TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); + TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr); if (is_hub_addr(daddr)) { TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - // marking this hub to run the loop on its children next (unroll recursive) removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); } else { // Invoke callback before closing driver (maybe call it later ?) @@ -1244,9 +1243,11 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu } } + // if removing a hub, we need to remove its downstream devices + #if CFG_TUH_HUB if (removing_hubs == 0) break; - // find the next hub to process + // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { if (tu_bit_test(removing_hubs, h_id)) { removing_hubs &= ~TU_BIT(h_id); @@ -1257,6 +1258,10 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu break; } } + #else + (void) removing_hubs; + break; + #endif } while(1); } From d50003e33d89740c0993ae236629392df82453c2 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 27 Mar 2024 11:21:13 -0700 Subject: [PATCH 7/9] Fake unplug devices when a root hub is deinit --- src/host/usbh.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/host/usbh.c b/src/host/usbh.c index f2dc2f7c1..29c6eb1e9 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -415,6 +415,15 @@ bool tuh_deinit(uint8_t rhport) { _usbh_controller = TUSB_INDEX_INVALID_8; + // "unplug" all devices on this rhport + for (uint8_t idx = 0; idx < CFG_TUH_DEVICE_MAX + CFG_TUH_HUB; idx++) { + usbh_device_t *dev = &_usbh_devices[idx]; + if (!dev->connected || dev->rhport != rhport) { + continue; + } + process_removing_device(rhport, dev->hub_addr, dev->hub_port); + } + // deinit host stack if no controller is active if (!tuh_inited()) { // Class drivers From ddb1034a9c77d8ef4efccf3df76013f86efe5e09 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Mar 2024 21:45:52 +0700 Subject: [PATCH 8/9] use hub_addr=0, hub_port=0 for removing root hub port --- src/host/usbh.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 29c6eb1e9..05091736e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -412,17 +412,10 @@ bool tuh_deinit(uint8_t rhport) { // deinit host controller hcd_int_disable(rhport); hcd_deinit(rhport); - _usbh_controller = TUSB_INDEX_INVALID_8; - // "unplug" all devices on this rhport - for (uint8_t idx = 0; idx < CFG_TUH_DEVICE_MAX + CFG_TUH_HUB; idx++) { - usbh_device_t *dev = &_usbh_devices[idx]; - if (!dev->connected || dev->rhport != rhport) { - continue; - } - process_removing_device(rhport, dev->hub_addr, dev->hub_port); - } + // "unplug" all devices on this rhport (hub_addr = 0, hub_port = 0) + process_removing_device(rhport, 0, 0); // deinit host stack if no controller is active if (!tuh_inited()) { From b9400df4c8bd49f1dd1e3047ca2a2c0284fa785e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 29 Mar 2024 11:23:36 +0700 Subject: [PATCH 9/9] fix rp2 debug build with level 3 --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 08aef9314..b351a9a07 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -113,7 +113,7 @@ static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_en static void __tusb_irq_path_func(hw_handle_buff_status)(void) { uint32_t remaining_buffers = usb_hw->buf_status; - pico_trace("buf_status 0x%08x\n", remaining_buffers); + pico_trace("buf_status 0x%08lx\n", remaining_buffers); // Check EPX first uint bit = 0b1; @@ -325,10 +325,8 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; - pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, tu_edpt_number(ep->ep_addr), - ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->transfer_type); - pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, tu_edpt_number(ep->ep_addr), - ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->hw_data_buf); + pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, ep->transfer_type); + pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->ep_addr, ep->hw_data_buf); uint dpram_offset = hw_data_offset(ep->hw_data_buf); // Bits 0-5 should be 0 assert(!(dpram_offset & 0b111111)); @@ -343,7 +341,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB); } *ep->endpoint_control = ep_reg; - pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg); + pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg); ep->configured = true; if ( ep != &epx )