Skip to content

Commit ba1192b

Browse files
authored
Update dcd_dwc2.c
1 parent 237b9ae commit ba1192b

File tree

1 file changed

+104
-73
lines changed

1 file changed

+104
-73
lines changed

components/arduino_tinyusb/src/dcd_dwc2.c

Lines changed: 104 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,9 @@
3939
#define DWC2_DEBUG 2
4040

4141
#include "device/dcd.h"
42+
#include "device/usbd_pvt.h"
4243
#include "dwc2_common.h"
4344

44-
#if TU_CHECK_MCU(OPT_MCU_GD32VF103)
45-
#define DWC2_EP_COUNT(_dwc2) DWC2_EP_MAX
46-
#else
47-
#define DWC2_EP_COUNT(_dwc2) ((_dwc2)->ghwcfg2_bm.num_dev_ep + 1)
48-
#endif
49-
5045
//--------------------------------------------------------------------+
5146
// MACRO TYPEDEF CONSTANT ENUM
5247
//--------------------------------------------------------------------+
@@ -58,6 +53,7 @@ typedef struct {
5853
uint8_t interval;
5954
} xfer_ctl_t;
6055

56+
// This variable is modified from ISR context, so it must be protected by critical section
6157
static xfer_ctl_t xfer_status[DWC2_EP_MAX][2];
6258
#define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir])
6359

@@ -79,6 +75,16 @@ CFG_TUD_MEM_SECTION static struct {
7975
TUD_EPBUF_DEF(setup_packet, 8);
8076
} _dcd_usbbuf;
8177

78+
TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) {
79+
#if TU_CHECK_MCU(OPT_MCU_GD32VF103)
80+
return DWC2_EP_MAX;
81+
#else
82+
const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
83+
return ghwcfg2.num_dev_ep + 1;
84+
#endif
85+
}
86+
87+
8288
//--------------------------------------------------------------------
8389
// DMA
8490
//--------------------------------------------------------------------
@@ -102,7 +108,8 @@ bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) {
102108
TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) {
103109
(void) dwc2;
104110
// Internal DMA only
105-
return CFG_TUD_DWC2_DMA_ENABLE && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA;
111+
const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
112+
return CFG_TUD_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA;
106113
}
107114

108115
static void dma_setup_prepare(uint8_t rhport) {
@@ -261,20 +268,15 @@ static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint
261268
xfer->interval = p_endpoint_desc->bInterval;
262269

263270
// Endpoint control
264-
union {
265-
uint32_t value;
266-
dwc2_depctl_t bm;
267-
} depctl;
268-
depctl.value = 0;
269-
270-
depctl.bm.mps = xfer->max_size;
271-
depctl.bm.active = 1;
272-
depctl.bm.type = p_endpoint_desc->bmAttributes.xfer;
271+
dwc2_depctl_t depctl = {.value = 0};
272+
depctl.mps = xfer->max_size;
273+
depctl.active = 1;
274+
depctl.type = p_endpoint_desc->bmAttributes.xfer;
273275
if (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) {
274-
depctl.bm.set_data0_iso_even = 1;
276+
depctl.set_data0_iso_even = 1;
275277
}
276278
if (dir == TUSB_DIR_IN) {
277-
//depctl.bm.tx_fifo_num = epnum;
279+
//depctl.tx_fifo_num = epnum;
278280
uint8_t fifo_num = epnum;
279281
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
280282
// Special Case for EP5, which is used by CDC but not actually called by the driver
@@ -285,7 +287,7 @@ static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint
285287
fifo_num = get_free_fifo();
286288
}
287289
#endif
288-
depctl.bm.tx_fifo_num = fifo_num;
290+
depctl.tx_fifo_num = fifo_num;
289291
}
290292

291293
dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum];
@@ -343,6 +345,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) {
343345
}
344346
}
345347

348+
// Since this function returns void, it is not possible to return a boolean success message
349+
// We must make sure that this function is not called when the EP is disabled
350+
// Must be called from critical section
346351
static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uint8_t dir) {
347352
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
348353
xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, dir);
@@ -365,31 +370,22 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
365370
}
366371

367372
// transfer size: A full OUT transfer (multiple packets, possibly) triggers XFRC.
368-
union {
369-
uint32_t value;
370-
dwc2_ep_tsize_t bm;
371-
} deptsiz;
372-
deptsiz.value = 0;
373-
deptsiz.bm.xfer_size = total_bytes;
374-
deptsiz.bm.packet_count = num_packets;
375-
373+
dwc2_ep_tsize_t deptsiz = {.value = 0};
374+
deptsiz.xfer_size = total_bytes;
375+
deptsiz.packet_count = num_packets;
376376
dep->tsiz = deptsiz.value;
377377

378378
// control
379-
union {
380-
dwc2_depctl_t bm;
381-
uint32_t value;
382-
} depctl;
383-
depctl.value = dep->ctl;
384-
385-
depctl.bm.clear_nak = 1;
386-
depctl.bm.enable = 1;
387-
if (depctl.bm.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) {
388-
const uint32_t odd_now = (dwc2->dsts_bm.frame_number & 1u);
379+
dwc2_depctl_t depctl = {.value = dep->ctl};
380+
depctl.clear_nak = 1;
381+
depctl.enable = 1;
382+
if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) {
383+
const dwc2_dsts_t dsts = {.value = dwc2->dsts};
384+
const uint32_t odd_now = dsts.frame_number & 1u;
389385
if (odd_now) {
390-
depctl.bm.set_data0_iso_even = 1;
386+
depctl.set_data0_iso_even = 1;
391387
} else {
392-
depctl.bm.set_data1_iso_odd = 1;
388+
depctl.set_data1_iso_odd = 1;
393389
}
394390
}
395391

@@ -432,7 +428,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
432428

433429
// XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required
434430
// when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347)
435-
if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
431+
const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
432+
if (ghwcfg2.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
436433
dcfg |= DCFG_XCVRDLY;
437434
}
438435
} else {
@@ -561,6 +558,8 @@ void dcd_edpt_close_all(uint8_t rhport) {
561558
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
562559
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
563560

561+
usbd_spin_lock(false);
562+
564563
_dcd_data.allocated_epin_count = 0;
565564

566565
// Disable non-control interrupt
@@ -582,8 +581,9 @@ void dcd_edpt_close_all(uint8_t rhport) {
582581

583582
dfifo_flush_tx(dwc2, 0x10); // all tx fifo
584583
dfifo_flush_rx(dwc2);
585-
586584
dfifo_device_init(rhport); // re-init dfifo
585+
586+
usbd_spin_unlock(false);
587587
}
588588

589589
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
@@ -601,21 +601,31 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpo
601601
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
602602
uint8_t const epnum = tu_edpt_number(ep_addr);
603603
uint8_t const dir = tu_edpt_dir(ep_addr);
604-
605604
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir);
606-
xfer->buffer = buffer;
607-
xfer->ff = NULL;
608-
xfer->total_len = total_bytes;
605+
bool ret;
609606

610-
// EP0 can only handle one packet
611-
if (epnum == 0) {
612-
_dcd_data.ep0_pending[dir] = total_bytes;
607+
usbd_spin_lock(false);
608+
609+
if (xfer->max_size == 0) {
610+
ret = false; // Endpoint is closed
611+
} else {
612+
xfer->buffer = buffer;
613+
xfer->ff = NULL;
614+
xfer->total_len = total_bytes;
615+
616+
// EP0 can only handle one packet
617+
if (epnum == 0) {
618+
_dcd_data.ep0_pending[dir] = total_bytes;
619+
}
620+
621+
// Schedule packets to be sent within interrupt
622+
edpt_schedule_packets(rhport, epnum, dir);
623+
ret = true;
613624
}
614625

615-
// Schedule packets to be sent within interrupt
616-
edpt_schedule_packets(rhport, epnum, dir);
626+
usbd_spin_unlock(false);
617627

618-
return true;
628+
return ret;
619629
}
620630

621631
// The number of bytes has to be given explicitly to allow more flexible control of how many
@@ -628,17 +638,27 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t
628638

629639
uint8_t const epnum = tu_edpt_number(ep_addr);
630640
uint8_t const dir = tu_edpt_dir(ep_addr);
631-
632641
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir);
633-
xfer->buffer = NULL;
634-
xfer->ff = ff;
635-
xfer->total_len = total_bytes;
642+
bool ret;
636643

637-
// Schedule packets to be sent within interrupt
638-
// TODO xfer fifo may only available for slave mode
639-
edpt_schedule_packets(rhport, epnum, dir);
644+
usbd_spin_lock(false);
640645

641-
return true;
646+
if (xfer->max_size == 0) {
647+
ret = false; // Endpoint is closed
648+
} else {
649+
xfer->buffer = NULL;
650+
xfer->ff = ff;
651+
xfer->total_len = total_bytes;
652+
653+
// Schedule packets to be sent within interrupt
654+
// TODO xfer fifo may only available for slave mode
655+
edpt_schedule_packets(rhport, epnum, dir);
656+
ret = true;
657+
}
658+
659+
usbd_spin_unlock(false);
660+
661+
return ret;
642662
}
643663

644664
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
@@ -665,9 +685,10 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
665685
//--------------------------------------------------------------------
666686

667687
// 7.4.1 Initialization on USB Reset
688+
// Must be called from critical section
668689
static void handle_bus_reset(uint8_t rhport) {
669690
dwc2_regs_t *dwc2 = DWC2_REG(rhport);
670-
const uint8_t ep_count = DWC2_EP_COUNT(dwc2);
691+
const uint8_t ep_count = dwc2_ep_count(dwc2);
671692

672693
tu_memclr(xfer_status, sizeof(xfer_status));
673694

@@ -697,7 +718,9 @@ static void handle_bus_reset(uint8_t rhport) {
697718
dfifo_device_init(rhport);
698719

699720
// 5. Reset device address
700-
dwc2->dcfg_bm.address = 0;
721+
dwc2_dcfg_t dcfg = {.value = dwc2->dcfg};
722+
dcfg.address = 0;
723+
dwc2->dcfg = dcfg.value;
701724

702725
// Fixed both control EP0 size to 64 bytes
703726
dwc2->epin[0].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos);
@@ -717,8 +740,9 @@ static void handle_bus_reset(uint8_t rhport) {
717740

718741
static void handle_enum_done(uint8_t rhport) {
719742
dwc2_regs_t *dwc2 = DWC2_REG(rhport);
743+
const dwc2_dsts_t dsts = {.value = dwc2->dsts};
720744
tusb_speed_t speed;
721-
switch (dwc2->dsts_bm.enum_speed) {
745+
switch (dsts.enum_speed) {
722746
case DCFG_SPEED_HIGH:
723747
speed = TUSB_SPEED_HIGH;
724748
break;
@@ -763,12 +787,12 @@ static void handle_rxflvl_irq(uint8_t rhport) {
763787
const volatile uint32_t* rx_fifo = dwc2->fifo[0];
764788

765789
// Pop control word off FIFO
766-
const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm;
767-
const uint8_t epnum = grxstsp_bm.ep_ch_num;
790+
const dwc2_grxstsp_t grxstsp = {.value = dwc2->grxstsp};
791+
const uint8_t epnum = grxstsp.ep_ch_num;
768792

769793
dwc2_dep_t* epout = &dwc2->epout[epnum];
770794

771-
switch (grxstsp_bm.packet_status) {
795+
switch (grxstsp.packet_status) {
772796
case GRXSTS_PKTSTS_GLOBAL_OUT_NAK:
773797
// Global OUT NAK: do nothing
774798
break;
@@ -790,7 +814,7 @@ static void handle_rxflvl_irq(uint8_t rhport) {
790814

791815
case GRXSTS_PKTSTS_RX_DATA: {
792816
// Out packet received
793-
const uint16_t byte_count = grxstsp_bm.byte_count;
817+
const uint16_t byte_count = grxstsp.byte_count;
794818
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
795819

796820
if (byte_count) {
@@ -804,7 +828,8 @@ static void handle_rxflvl_irq(uint8_t rhport) {
804828

805829
// short packet, minus remaining bytes (xfer_size)
806830
if (byte_count < xfer->max_size) {
807-
xfer->total_len -= epout->tsiz_bm.xfer_size;
831+
const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz};
832+
xfer->total_len -= tsiz.xfer_size;
808833
if (epnum == 0) {
809834
xfer->total_len -= _dcd_data.ep0_pending[TUSB_DIR_OUT];
810835
_dcd_data.ep0_pending[TUSB_DIR_OUT] = 0;
@@ -866,11 +891,13 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep
866891
// - 64 bytes or
867892
// - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL)
868893
if (diepint_bm.txfifo_empty && (dwc2->diepempmsk & (1 << epnum))) {
869-
const uint16_t remain_packets = epin->tsiz_bm.packet_count;
894+
dwc2_ep_tsize_t tsiz = {.value = epin->tsiz};
895+
const uint16_t remain_packets = tsiz.packet_count;
870896

871897
// Process every single packet (only whole packets can be written to fifo)
872898
for (uint16_t i = 0; i < remain_packets; i++) {
873-
const uint16_t remain_bytes = (uint16_t) epin->tsiz_bm.xfer_size;
899+
tsiz.value = epin->tsiz;
900+
const uint16_t remain_bytes = (uint16_t) tsiz.xfer_size;
874901
const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size);
875902

876903
// Check if dtxfsts has enough space available
@@ -889,7 +916,8 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep
889916
}
890917

891918
// Turn off TXFE if all bytes are written.
892-
if (epin->tsiz_bm.xfer_size == 0) {
919+
tsiz.value = epin->tsiz;
920+
if (tsiz.xfer_size == 0) {
893921
dwc2->diepempmsk &= ~(1 << epnum);
894922
}
895923
}
@@ -920,7 +948,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
920948
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
921949

922950
// determine actual received bytes
923-
const uint16_t remain = epout->tsiz_bm.xfer_size;
951+
const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz};
952+
const uint16_t remain = tsiz.xfer_size;
924953
xfer->total_len -= remain;
925954

926955
// this is ZLP, so prepare EP0 for next setup
@@ -956,7 +985,7 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin
956985
static void handle_ep_irq(uint8_t rhport, uint8_t dir) {
957986
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
958987
const bool is_dma = dma_device_enabled(dwc2);
959-
const uint8_t ep_count = DWC2_EP_COUNT(dwc2);
988+
const uint8_t ep_count = dwc2_ep_count(dwc2);
960989
const uint8_t daint_offset = (dir == TUSB_DIR_IN) ? DAINT_IEPINT_Pos : DAINT_OEPINT_Pos;
961990
dwc2_dep_t* ep_base = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][0];
962991

@@ -1009,7 +1038,6 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) {
10091038
*/
10101039
void dcd_int_handler(uint8_t rhport) {
10111040
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
1012-
10131041
const uint32_t gintmask = dwc2->gintmsk;
10141042
const uint32_t gintsts = dwc2->gintsts & gintmask;
10151043

@@ -1019,7 +1047,10 @@ void dcd_int_handler(uint8_t rhport) {
10191047
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
10201048
_allocated_fifos = 1;
10211049
#endif
1050+
1051+
usbd_spin_lock(true);
10221052
handle_bus_reset(rhport);
1053+
usbd_spin_unlock(true);
10231054
}
10241055

10251056
if (gintsts & GINTSTS_ENUMDNE) {

0 commit comments

Comments
 (0)