summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-06-02 22:38:57 +0200
committerHiFiPhile <[email protected]>2026-06-02 22:59:45 +0200
commitcc979da5163d0d407e27d90411a6d4b1a0092779 (patch)
tree9076a2d370ff55dad1102e4ab01a2e2ac621db29 /src
parent5004a24b2cceffbe998a5238f625da97537f5de7 (diff)
dcd/dwc2: fix back-to-back SETUP reception in DMA mode
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index c90429a15..e6d7dc08e 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -73,9 +73,8 @@ typedef struct {
static dcd_data_t _dcd_data;
-CFG_TUD_MEM_SECTION static union {
- TUD_EPBUF_DEF(setup_buffer, 8);
- tusb_control_request_t setup_packet;
+CFG_TUD_MEM_SECTION static struct {
+ TUD_EPBUF_DEF(setup_buffer, 24);
} _dcd_usbbuf;
static tud_configure_dwc2_t _tud_cfg = CFG_TUD_CONFIGURE_DWC2_DEFAULT;
@@ -137,8 +136,8 @@ static void dma_setup_prepare(uint8_t rhport) {
}
}
- // Receive only 1 packet
- dwc2->epout[0].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos);
+ // Receive back-to-back setup packets
+ dwc2->epout[0].doeptsiz = (3 << DOEPTSIZ_STUPCNT_Pos);
dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_buffer;
dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP;
}
@@ -1003,15 +1002,19 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
if (doepint_bm.setup_phase_done) {
// Cleanup previous pending EP0 IN transfer if any
- dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0];
+ dwc2_dep_t* epin0 = &dwc2->epin[0];
+ dwc2_dep_t* epout0 = &dwc2->epout[0];
if (edpt_is_enabled(epin0)) {
edpt_disable(rhport, 0x80, false);
}
- dcd_dcache_invalidate(_dcd_usbbuf.setup_buffer, 8);
- dcd_event_setup_received(rhport, _dcd_usbbuf.setup_buffer, true);
+
+ dcd_dcache_invalidate(_dcd_usbbuf.setup_buffer, sizeof(_dcd_usbbuf.setup_buffer));
+
+ tusb_control_request_t *setup_packet = (tusb_control_request_t *) (epout0->doepdma - 8);
+ dcd_event_setup_received(rhport, (uint8_t*)setup_packet, true);
// Prepare EP0 for next setup if this setup has no data stage
- if (_dcd_usbbuf.setup_packet.wLength == 0) {
+ if (setup_packet->wLength == 0) {
dma_setup_prepare(rhport);
}
return;