diff options
| author | HiFiPHile <[email protected]> | 2026-08-27 14:49:47 +0200 |
|---|---|---|
| committer | HiFiPHile <[email protected]> | 2026-09-02 10:50:02 +0200 |
| commit | 13971b58df52bc29de97632295fcae43aeade5c9 (patch) | |
| tree | 8ca52d5bf292290368132b1d815cd3a9891e4b1d | |
| parent | a0d3de76869ce728c7c1d9713085bc970da39671 (diff) | |
fix(dwc2): drain host RX status before channel IRQ
Popping an IN transfer-completion entry from GRXSTSP asserts HCINT.XferCompl. Drain the receive FIFO first, then read the live masked global status so the newly asserted channel completion is handled without waiting for another interrupt.
| -rw-r--r-- | src/portable/synopsys/dwc2/hcd_dwc2.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 05efacbee..ca16eec70 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -1574,21 +1574,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { handle_hprt_irq(rhport, in_isr); } - if (gintsts & GINTSTS_HCINT) { - // Host Channel interrupt: source is cleared in HCINT register - // must be handled after TX FIFO empty - handle_channel_irq(rhport, in_isr); - } - - if (gintsts & GINTSTS_DISCINT) { - // Device disconnected - dwc2->gintsts = GINTSTS_DISCINT; - - if (0 == (dwc2->hprt & HPRT_CONN_STATUS)) { - hcd_event_device_remove(rhport, in_isr); - } - } - #if CFG_TUH_DWC2_SLAVE_ENABLE // RxFIFO non-empty interrupt handling if (gintsts & GINTSTS_RXFLVL) { @@ -1620,6 +1605,21 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { } } #endif + + // Draining the RxFIFO completion status can assert HCINT.XferCompl. Read + // the live status here so the completion is handled in this ISR invocation. + if ((dwc2->gintsts & dwc2->gintmsk) & GINTSTS_HCINT) { + handle_channel_irq(rhport, in_isr); + } + + if (gintsts & GINTSTS_DISCINT) { + // Device disconnected + dwc2->gintsts = GINTSTS_DISCINT; + + if (0 == (dwc2->hprt & HPRT_CONN_STATUS)) { + hcd_event_device_remove(rhport, in_isr); + } + } } #endif |
