From 00af84ba09007910e1ae124467f0d6c809cc46b1 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 11 Nov 2026 17:16:45 +0100 Subject: [PATCH] wch/usbhs: report resume when the SUSPEND interrupt fires on bus resume The USBHS SUSPEND interrupt fires on both suspend and resume, but the DCD reported every one as DCD_EVENT_SUSPEND. SOF interrupts are off after the bus reset, so nothing cleared usbd's suspended flag: after one host suspend, tud_ready() stayed false for good and net_lwip_webserver's linkoutput dropped every frame (DHCP, ARP, HTTP) while OUT NTBs still arrived. Tell the two edges apart with MIS_ST's suspend bit, as the CH583 USBFS path already does. Refs #4477: fixes the Windows-host case only; the CI board still fails on Linux. --- src/portable/wch/dcd_ch32_usbhs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 9c0865e80d..48956d7a8c 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -473,7 +473,11 @@ void dcd_int_handler(uint8_t rhport) { USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */ } else if (int_flag & USBHS_SUSPEND_FLAG) { - dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND}; + // The SUSPEND interrupt fires on both suspend and resume; MIS_ST's suspend bit tells them apart + // (set while suspended, clear once resumed). Reporting both as suspend leaves usbd suspended for + // good: SOF interrupts are off after reset, so nothing else clears it and tud_ready() stays false. + dcd_event_t event = {.rhport = rhport, + .event_id = (USBHSD->MIS_ST & USBHS_SUSPEND) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME}; dcd_event_handler(&event, true); USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */