diff options
| author | hathach <[email protected]> | 2026-07-08 07:32:49 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-07-08 07:32:49 +0700 |
| commit | 9d51270f7bb1d70978e2b4abb672d0fe930fb68d (patch) | |
| tree | c8953fbab4f935ab3d0c868c64170dbe2def9760 | |
| parent | 206e63349199e34047486d3dba3f2c8972aae5f2 (diff) | |
Retry CH569 SuperSpeed training and fix net_lwip_webserver EP0 size
Two fixes found bringing up SuperSpeed on a Renesas uPD720201-based hub:
- dcd_ch56x_usb30: retry link training with a fresh detect cycle every
second fallback-timer tick (4 ticks total) before switching to the
USB2 fallback. Some hubs only complete Polling on a re-attempt; with
a single continuous attempt the link reached U0 rarely and the port
fell back to high speed almost every boot.
- net_lwip_webserver: CFG_TUD_ENDPOINT0_SIZE was left at plain 64, so
usbd chunked EP0 data at 64 bytes; on a 512-mps SuperSpeed control
endpoint the first chunk is a short packet, the host ends the data
stage early and the status stage deadlocks until timeout ("can't
read configurations, error -110"). Use the SuperSpeed-aware size and
clamp the device-qualifier bMaxPacketSize0 like the other examples.
Validated on HydraUSB3: NCM enumerates at 5000M reliably across warm
reboots; lwiperf over SuperSpeed measures 51 Mbit/s device RX (TCP
window bound; 33 Mbit/s on the high-speed fallback), MSC 169/136 MB/s.
Full example sweep, 65/65 unit tests, pre-commit clean.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019MRGjBT2NBkCoWwyDT4LaE
| -rw-r--r-- | examples/device/net_lwip_webserver/src/tusb_config.h | 2 | ||||
| -rw-r--r-- | examples/device/net_lwip_webserver/src/usb_descriptors.c | 2 | ||||
| -rw-r--r-- | src/portable/wch/dcd_ch56x_usb30.c | 16 |
3 files changed, 16 insertions, 4 deletions
diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 2ff68a356..ef5d5f622 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -149,7 +149,7 @@ extern "C" { //-------------------------------------------------------------------- #ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 + #define CFG_TUD_ENDPOINT0_SIZE (TUD_OPT_SUPER_SPEED ? 512 : 64) // SuperSpeed EP0 is fixed at 512 #endif //------------- CLASS -------------// diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 10c003c75..a5c2da6ab 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -346,7 +346,7 @@ static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bMaxPacketSize0 = EP0_SIZE_FSHS, .bNumConfigurations = CONFIG_ID_COUNT, .bReserved = 0x00 }; diff --git a/src/portable/wch/dcd_ch56x_usb30.c b/src/portable/wch/dcd_ch56x_usb30.c index f9c7fded7..cc14a86ce 100644 --- a/src/portable/wch/dcd_ch56x_usb30.c +++ b/src/portable/wch/dcd_ch56x_usb30.c @@ -103,6 +103,7 @@ static volatile bool _lmp_pending; // send LMP PORT_CAPABILITY at next li // timer. One way: returning to SuperSpeed after fallback requires a new dcd_init (or power cycle). enum { FB_USB3_TRAINING = 0, FB_USB3_OFF, FB_USB3_UP, FB_USB2_ACTIVE }; static volatile uint8_t _fb_state; +static uint8_t _fb_train_ticks; // training timer expiries; a fresh detect cycle every 2nd tick static void fallback_timer_stop(void) { R8_TMR0_INTER_EN = 0; @@ -111,9 +112,10 @@ static void fallback_timer_stop(void) { } static void fallback_timer_start(void) { + _fb_train_ticks = 0; R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; // TMR0 counts 26 bits: CNT_END must stay below 2^26 (67108864). 0.55 s per expiry at - // 120 MHz, ~1.1 s total before USB2 comes up + // 120 MHz; training gets several expiries (with re-attempts) before USB2 comes up R32_TMR0_CNT_END = 66000000; R8_TMR0_INT_FLAG = RB_TMR_IF_CYC_END; R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END; @@ -543,7 +545,17 @@ void dcd_int_handler(uint8_t rhport) { if (R8_TMR0_INT_FLAG & RB_TMR_IF_CYC_END) { R8_TMR0_INT_FLAG = RB_TMR_IF_CYC_END; if (_fb_state == FB_USB3_TRAINING) { - // first expiry: shut USB3 down so the host sees a disconnect + // Retry SuperSpeed training with a fresh detect cycle a few times before giving up: + // some hubs (e.g. Renesas uPD720201's) only complete training on a re-attempt + _fb_train_ticks++; + if (_fb_train_ticks < 4) { + if ((_fb_train_ticks & 1u) == 0) { + usb30_hw_deinit(); + usb30_hw_init(); + } + return; + } + // training window exhausted: shut USB3 down so the host sees a disconnect PFIC_DisableIRQ(USBSS_IRQn); PFIC_DisableIRQ(LINK_IRQn); usb30_hw_deinit(); |
