diff options
| author | hathach <[email protected]> | 2026-06-13 00:18:55 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-06-13 23:34:57 +0700 |
| commit | 1ea385a6c431cee759695515a4bed94c6dff65c6 (patch) | |
| tree | 34f4b64cd7da5bfff44bb830e4b894f9a3ca653e /src | |
| parent | b21d59f8177af967e2b2757c4ef996df00d1e617 (diff) | |
dcd/musb: check SentStall/SetupEnd before DATAEND guard
MUSBMHDRC 21.1.5 requires the EP0 service routine to check SentStall
and SetupEnd first; the early DATAEND return ran before both, and
SentStall is most likely to fire exactly while DataEnd may still read
back set (auto-STALL after DataEnd, 21.1.7), which would skip the
recovery. The guard also moves below the RXRDY block so a coalesced
DATAEND|RXRDY read cannot swallow a SETUP on cores where the
CPU-set-only DataEnd bit reads back 1; the comment documents the
vendor-dependent read-back.
Review follow-up for #3643 (dcd_musb.c l.445 finding).
Co-Authored-By: Claude Fable 5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/portable/mentor/musb/dcd_musb.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 9bdd6b080..86ae3ae9a 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -458,10 +458,7 @@ static void process_ep0(uint8_t rhport) { musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0); uint_fast8_t csrl = ep_csr->csr0l; - if (csrl & MUSB_CSRL0_DATAEND) { - return; - } - + // 21.1.5: SentStall and SetupEnd must be checked before anything else. if (csrl & MUSB_CSRL0_STALLED) { ep_csr->csr0l = 0; _dcd.pipe0.state = PIPE0_STATE_IDLE; @@ -559,6 +556,13 @@ static void process_ep0(uint8_t rhport) { return; } + if (csrl & MUSB_CSRL0_DATAEND) { + // Last DATA IN chunk / STATUS IN arm wrote TXRDY|DATAEND and the status stage has not completed + // yet — nothing to service. DataEnd is CPU-set-only per the CSR access table; whether it ever + // reads back 1 is vendor-dependent (on cores where it reads 0 this guard is dead code). + return; + } + /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ |
