39
39
#define DWC2_DEBUG 2
40
40
41
41
#include "device/dcd.h"
42
+ #include "device/usbd_pvt.h"
42
43
#include "dwc2_common.h"
43
44
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
-
50
45
//--------------------------------------------------------------------+
51
46
// MACRO TYPEDEF CONSTANT ENUM
52
47
//--------------------------------------------------------------------+
@@ -58,6 +53,7 @@ typedef struct {
58
53
uint8_t interval ;
59
54
} xfer_ctl_t ;
60
55
56
+ // This variable is modified from ISR context, so it must be protected by critical section
61
57
static xfer_ctl_t xfer_status [DWC2_EP_MAX ][2 ];
62
58
#define XFER_CTL_BASE (_ep , _dir ) (&xfer_status[_ep][_dir])
63
59
@@ -79,6 +75,16 @@ CFG_TUD_MEM_SECTION static struct {
79
75
TUD_EPBUF_DEF (setup_packet , 8 );
80
76
} _dcd_usbbuf ;
81
77
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
+
82
88
//--------------------------------------------------------------------
83
89
// DMA
84
90
//--------------------------------------------------------------------
@@ -102,7 +108,8 @@ bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) {
102
108
TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled (const dwc2_regs_t * dwc2 ) {
103
109
(void ) dwc2 ;
104
110
// 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 ;
106
113
}
107
114
108
115
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
261
268
xfer -> interval = p_endpoint_desc -> bInterval ;
262
269
263
270
// 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 ;
273
275
if (p_endpoint_desc -> bmAttributes .xfer != TUSB_XFER_ISOCHRONOUS ) {
274
- depctl .bm . set_data0_iso_even = 1 ;
276
+ depctl .set_data0_iso_even = 1 ;
275
277
}
276
278
if (dir == TUSB_DIR_IN ) {
277
- //depctl.bm. tx_fifo_num = epnum;
279
+ //depctl.tx_fifo_num = epnum;
278
280
uint8_t fifo_num = epnum ;
279
281
#if TU_CHECK_MCU (OPT_MCU_ESP32S2 , OPT_MCU_ESP32S3 )
280
282
// 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
285
287
fifo_num = get_free_fifo ();
286
288
}
287
289
#endif
288
- depctl .bm . tx_fifo_num = fifo_num ;
290
+ depctl .tx_fifo_num = fifo_num ;
289
291
}
290
292
291
293
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) {
343
345
}
344
346
}
345
347
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
346
351
static void edpt_schedule_packets (uint8_t rhport , const uint8_t epnum , const uint8_t dir ) {
347
352
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
348
353
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
365
370
}
366
371
367
372
// 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 ;
376
376
dep -> tsiz = deptsiz .value ;
377
377
378
378
// 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 ;
389
385
if (odd_now ) {
390
- depctl .bm . set_data0_iso_even = 1 ;
386
+ depctl .set_data0_iso_even = 1 ;
391
387
} else {
392
- depctl .bm . set_data1_iso_odd = 1 ;
388
+ depctl .set_data1_iso_odd = 1 ;
393
389
}
394
390
}
395
391
@@ -432,7 +428,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
432
428
433
429
// XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required
434
430
// 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 ) {
436
433
dcfg |= DCFG_XCVRDLY ;
437
434
}
438
435
} else {
@@ -561,6 +558,8 @@ void dcd_edpt_close_all(uint8_t rhport) {
561
558
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
562
559
uint8_t const ep_count = _dwc2_controller [rhport ].ep_count ;
563
560
561
+ usbd_spin_lock (false);
562
+
564
563
_dcd_data .allocated_epin_count = 0 ;
565
564
566
565
// Disable non-control interrupt
@@ -582,8 +581,9 @@ void dcd_edpt_close_all(uint8_t rhport) {
582
581
583
582
dfifo_flush_tx (dwc2 , 0x10 ); // all tx fifo
584
583
dfifo_flush_rx (dwc2 );
585
-
586
584
dfifo_device_init (rhport ); // re-init dfifo
585
+
586
+ usbd_spin_unlock (false);
587
587
}
588
588
589
589
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
601
601
bool dcd_edpt_xfer (uint8_t rhport , uint8_t ep_addr , uint8_t * buffer , uint16_t total_bytes ) {
602
602
uint8_t const epnum = tu_edpt_number (ep_addr );
603
603
uint8_t const dir = tu_edpt_dir (ep_addr );
604
-
605
604
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 ;
609
606
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;
613
624
}
614
625
615
- // Schedule packets to be sent within interrupt
616
- edpt_schedule_packets (rhport , epnum , dir );
626
+ usbd_spin_unlock (false);
617
627
618
- return true ;
628
+ return ret ;
619
629
}
620
630
621
631
// 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
628
638
629
639
uint8_t const epnum = tu_edpt_number (ep_addr );
630
640
uint8_t const dir = tu_edpt_dir (ep_addr );
631
-
632
641
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 ;
636
643
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);
640
645
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 ;
642
662
}
643
663
644
664
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) {
665
685
//--------------------------------------------------------------------
666
686
667
687
// 7.4.1 Initialization on USB Reset
688
+ // Must be called from critical section
668
689
static void handle_bus_reset (uint8_t rhport ) {
669
690
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 );
671
692
672
693
tu_memclr (xfer_status , sizeof (xfer_status ));
673
694
@@ -697,7 +718,9 @@ static void handle_bus_reset(uint8_t rhport) {
697
718
dfifo_device_init (rhport );
698
719
699
720
// 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 ;
701
724
702
725
// Fixed both control EP0 size to 64 bytes
703
726
dwc2 -> epin [0 ].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos );
@@ -717,8 +740,9 @@ static void handle_bus_reset(uint8_t rhport) {
717
740
718
741
static void handle_enum_done (uint8_t rhport ) {
719
742
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
743
+ const dwc2_dsts_t dsts = {.value = dwc2 -> dsts };
720
744
tusb_speed_t speed ;
721
- switch (dwc2 -> dsts_bm .enum_speed ) {
745
+ switch (dsts .enum_speed ) {
722
746
case DCFG_SPEED_HIGH :
723
747
speed = TUSB_SPEED_HIGH ;
724
748
break ;
@@ -763,12 +787,12 @@ static void handle_rxflvl_irq(uint8_t rhport) {
763
787
const volatile uint32_t * rx_fifo = dwc2 -> fifo [0 ];
764
788
765
789
// 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 ;
768
792
769
793
dwc2_dep_t * epout = & dwc2 -> epout [epnum ];
770
794
771
- switch (grxstsp_bm .packet_status ) {
795
+ switch (grxstsp .packet_status ) {
772
796
case GRXSTS_PKTSTS_GLOBAL_OUT_NAK :
773
797
// Global OUT NAK: do nothing
774
798
break ;
@@ -790,7 +814,7 @@ static void handle_rxflvl_irq(uint8_t rhport) {
790
814
791
815
case GRXSTS_PKTSTS_RX_DATA : {
792
816
// Out packet received
793
- const uint16_t byte_count = grxstsp_bm .byte_count ;
817
+ const uint16_t byte_count = grxstsp .byte_count ;
794
818
xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , TUSB_DIR_OUT );
795
819
796
820
if (byte_count ) {
@@ -804,7 +828,8 @@ static void handle_rxflvl_irq(uint8_t rhport) {
804
828
805
829
// short packet, minus remaining bytes (xfer_size)
806
830
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 ;
808
833
if (epnum == 0 ) {
809
834
xfer -> total_len -= _dcd_data .ep0_pending [TUSB_DIR_OUT ];
810
835
_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
866
891
// - 64 bytes or
867
892
// - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL)
868
893
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 ;
870
896
871
897
// Process every single packet (only whole packets can be written to fifo)
872
898
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 ;
874
901
const uint16_t xact_bytes = tu_min16 (remain_bytes , xfer -> max_size );
875
902
876
903
// 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
889
916
}
890
917
891
918
// 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 ) {
893
921
dwc2 -> diepempmsk &= ~(1 << epnum );
894
922
}
895
923
}
@@ -920,7 +948,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
920
948
xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , TUSB_DIR_OUT );
921
949
922
950
// 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 ;
924
953
xfer -> total_len -= remain ;
925
954
926
955
// 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
956
985
static void handle_ep_irq (uint8_t rhport , uint8_t dir ) {
957
986
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
958
987
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 );
960
989
const uint8_t daint_offset = (dir == TUSB_DIR_IN ) ? DAINT_IEPINT_Pos : DAINT_OEPINT_Pos ;
961
990
dwc2_dep_t * ep_base = & dwc2 -> ep [dir == TUSB_DIR_IN ? 0 : 1 ][0 ];
962
991
@@ -1009,7 +1038,6 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) {
1009
1038
*/
1010
1039
void dcd_int_handler (uint8_t rhport ) {
1011
1040
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
1012
-
1013
1041
const uint32_t gintmask = dwc2 -> gintmsk ;
1014
1042
const uint32_t gintsts = dwc2 -> gintsts & gintmask ;
1015
1043
@@ -1019,7 +1047,10 @@ void dcd_int_handler(uint8_t rhport) {
1019
1047
#if TU_CHECK_MCU (OPT_MCU_ESP32S2 , OPT_MCU_ESP32S3 )
1020
1048
_allocated_fifos = 1 ;
1021
1049
#endif
1050
+
1051
+ usbd_spin_lock (true);
1022
1052
handle_bus_reset (rhport );
1053
+ usbd_spin_unlock (true);
1023
1054
}
1024
1055
1025
1056
if (gintsts & GINTSTS_ENUMDNE ) {
0 commit comments