summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-06-13 00:18:55 +0700
committerhathach <[email protected]>2026-06-13 23:34:57 +0700
commit1ea385a6c431cee759695515a4bed94c6dff65c6 (patch)
tree34f4b64cd7da5bfff44bb830e4b894f9a3ca653e /src
parentb21d59f8177af967e2b2757c4ef996df00d1e617 (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.c12
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 */