31
31
32
32
#if CFG_TUD_ENABLED && defined(TUP_USBIP_DWC2 )
33
33
34
+ #if !CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE
35
+ #error DWC2 require either CFG_TUD_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled
36
+ #endif
37
+
34
38
// Debug level for DWC2
35
39
#define DWC2_DEBUG 2
36
40
46
50
//--------------------------------------------------------------------+
47
51
// MACRO TYPEDEF CONSTANT ENUM
48
52
//--------------------------------------------------------------------+
49
-
50
- static CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED (4 ) uint32_t _setup_packet [2 ];
51
-
52
53
typedef struct {
53
54
uint8_t * buffer ;
54
55
tu_fifo_t * ff ;
@@ -60,19 +61,46 @@ typedef struct {
60
61
static xfer_ctl_t xfer_status [DWC2_EP_MAX ][2 ];
61
62
#define XFER_CTL_BASE (_ep , _dir ) (&xfer_status[_ep][_dir])
62
63
63
- // EP0 transfers are limited to 1 packet - larger sizes has to be split
64
- static uint16_t ep0_pending [2 ]; // Index determines direction as tusb_dir_t type
65
- static uint16_t _dfifo_top ; // top free location in DFIFO in words
64
+ typedef struct {
65
+ // EP0 transfers are limited to 1 packet - larger sizes has to be split
66
+ uint16_t ep0_pending [2 ]; // Index determines direction as tusb_dir_t type
67
+ uint16_t dfifo_top ; // top free location in DFIFO in words
68
+
69
+ // Number of IN endpoints active
70
+ uint8_t allocated_epin_count ;
71
+
72
+ // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by
73
+ bool sof_en ;
74
+ } dcd_data_t ;
66
75
67
- // Number of IN endpoints active
68
- static uint8_t _allocated_ep_in_count ;
76
+ static dcd_data_t _dcd_data ;
69
77
70
- // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by
71
- static bool _sof_en ;
78
+ CFG_TUD_MEM_SECTION static struct {
79
+ TUD_EPBUF_DEF (setup_packet , 8 );
80
+ } _dcd_usbbuf ;
72
81
73
82
//--------------------------------------------------------------------
74
83
// DMA
75
84
//--------------------------------------------------------------------
85
+ #if CFG_TUD_MEM_DCACHE_ENABLE
86
+ void dcd_dcache_clean (const void * addr , uint32_t data_size ) {
87
+ if (addr && data_size ) {
88
+ dwc2_dcache_clean (addr , data_size );
89
+ }
90
+ }
91
+
92
+ void dcd_dcache_invalidate (const void * addr , uint32_t data_size ) {
93
+ if (addr && data_size ) {
94
+ dwc2_dcache_invalidate (addr , data_size );
95
+ }
96
+ }
97
+
98
+ void dcd_dcache_clean_invalidate (const void * addr , uint32_t data_size ) {
99
+ if (addr && data_size ) {
100
+ dwc2_dcache_clean_invalidate (addr , data_size );
101
+ }
102
+ }
103
+ #endif
76
104
77
105
TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled (const dwc2_regs_t * dwc2 ) {
78
106
(void ) dwc2 ;
@@ -91,7 +119,7 @@ static void dma_setup_prepare(uint8_t rhport) {
91
119
92
120
// Receive only 1 packet
93
121
dwc2 -> epout [0 ].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos ) | (1 << DOEPTSIZ_PKTCNT_Pos ) | (8 << DOEPTSIZ_XFRSIZ_Pos );
94
- dwc2 -> epout [0 ].doepdma = (uintptr_t )_setup_packet ;
122
+ dwc2 -> epout [0 ].doepdma = (uintptr_t ) _dcd_usbbuf . setup_packet ;
95
123
dwc2 -> epout [0 ].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP ;
96
124
}
97
125
@@ -149,27 +177,27 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t larges
149
177
static bool dfifo_alloc (uint8_t rhport , uint8_t ep_addr , uint16_t packet_size ) {
150
178
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
151
179
const dwc2_controller_t * dwc2_controller = & _dwc2_controller [rhport ];
152
- uint8_t const ep_count = dwc2_controller -> ep_count ;
153
- uint8_t const epnum = tu_edpt_number (ep_addr );
154
- uint8_t const dir = tu_edpt_dir (ep_addr );
180
+ const uint8_t ep_count = dwc2_controller -> ep_count ;
181
+ const uint8_t epnum = tu_edpt_number (ep_addr );
182
+ const uint8_t dir = tu_edpt_dir (ep_addr );
155
183
156
184
TU_ASSERT (epnum < ep_count );
157
185
158
186
uint16_t fifo_size = tu_div_ceil (packet_size , 4 );
159
187
if (dir == TUSB_DIR_OUT ) {
160
188
// Calculate required size of RX FIFO
161
- uint16_t const new_sz = calc_device_grxfsiz (4 * fifo_size , ep_count );
189
+ const uint16_t new_sz = calc_device_grxfsiz (4 * fifo_size , ep_count );
162
190
163
191
// If size_rx needs to be extended check if there is enough free space
164
192
if (dwc2 -> grxfsiz < new_sz ) {
165
- TU_ASSERT (new_sz <= _dfifo_top );
193
+ TU_ASSERT (new_sz <= _dcd_data . dfifo_top );
166
194
dwc2 -> grxfsiz = new_sz ; // Enlarge RX FIFO
167
195
}
168
196
} else {
169
197
// Check IN endpoints concurrently active limit
170
198
if (_dwc2_controller -> ep_in_count ) {
171
- TU_ASSERT (_allocated_ep_in_count < _dwc2_controller -> ep_in_count );
172
- _allocated_ep_in_count ++ ;
199
+ TU_ASSERT (_dcd_data . allocated_epin_count < _dwc2_controller -> ep_in_count );
200
+ _dcd_data . allocated_epin_count ++ ;
173
201
}
174
202
175
203
// If The TXFELVL is configured as half empty, the fifo must be twice the max_size.
@@ -178,16 +206,16 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
178
206
}
179
207
180
208
// Check if free space is available
181
- TU_ASSERT (_dfifo_top >= fifo_size + dwc2 -> grxfsiz );
182
- _dfifo_top -= fifo_size ;
183
- TU_LOG (DWC2_DEBUG , " TX FIFO %u: allocated %u words at offset %u\r\n" , epnum , fifo_size , _dfifo_top );
209
+ TU_ASSERT (_dcd_data . dfifo_top >= fifo_size + dwc2 -> grxfsiz );
210
+ _dcd_data . dfifo_top -= fifo_size ;
211
+ // TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, dfifo_top );
184
212
185
213
// Both TXFD and TXSA are in unit of 32-bit words.
186
214
if (epnum == 0 ) {
187
- dwc2 -> dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos ) | _dfifo_top ;
215
+ dwc2 -> dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos ) | _dcd_data . dfifo_top ;
188
216
} else {
189
217
// DIEPTXF starts at FIFO #1.
190
- dwc2 -> dieptxf [epnum - 1 ] = (fifo_size << DIEPTXF_INEPTXFD_Pos ) | _dfifo_top ;
218
+ dwc2 -> dieptxf [epnum - 1 ] = (fifo_size << DIEPTXF_INEPTXFD_Pos ) | _dcd_data . dfifo_top ;
191
219
}
192
220
}
193
221
@@ -201,11 +229,11 @@ static void dfifo_device_init(uint8_t rhport) {
201
229
202
230
// Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction
203
231
const bool is_dma = dma_device_enabled (dwc2 );
204
- _dfifo_top = dwc2_controller -> ep_fifo_size /4 ;
232
+ _dcd_data . dfifo_top = dwc2_controller -> ep_fifo_size /4 ;
205
233
if (is_dma ) {
206
- _dfifo_top -= 2 * dwc2_controller -> ep_count ;
234
+ _dcd_data . dfifo_top -= 2 * dwc2_controller -> ep_count ;
207
235
}
208
- dwc2 -> gdfifocfg = (_dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT ) | _dfifo_top ;
236
+ dwc2 -> gdfifocfg = (_dcd_data . dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT ) | _dcd_data . dfifo_top ;
209
237
210
238
// Allocate FIFO for EP0 IN
211
239
dfifo_alloc (rhport , 0x80 , CFG_TUD_ENDPOINT0_SIZE );
@@ -225,8 +253,8 @@ static uint8_t get_free_fifo(void) {
225
253
return 0 ;
226
254
}
227
255
#endif
228
-
229
- static void edpt_activate (uint8_t rhport , tusb_desc_endpoint_t const * p_endpoint_desc ) {
256
+
257
+ static void edpt_activate (uint8_t rhport , const tusb_desc_endpoint_t * p_endpoint_desc ) {
230
258
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
231
259
const uint8_t epnum = tu_edpt_number (p_endpoint_desc -> bEndpointAddress );
232
260
const uint8_t dir = tu_edpt_dir (p_endpoint_desc -> bEndpointAddress );
@@ -328,8 +356,8 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
328
356
329
357
// EP0 is limited to one packet per xfer
330
358
if (epnum == 0 ) {
331
- total_bytes = tu_min16 (ep0_pending [dir ], xfer -> max_size );
332
- ep0_pending [dir ] -= total_bytes ;
359
+ total_bytes = tu_min16 (_dcd_data . ep0_pending [dir ], xfer -> max_size );
360
+ _dcd_data . ep0_pending [dir ] -= total_bytes ;
333
361
num_packets = 1 ;
334
362
} else {
335
363
total_bytes = xfer -> total_len ;
@@ -370,14 +398,18 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
370
398
371
399
const bool is_dma = dma_device_enabled (dwc2 );
372
400
if (is_dma ) {
401
+ if (dir == TUSB_DIR_IN && total_bytes != 0 ) {
402
+ dcd_dcache_clean (xfer -> buffer , total_bytes );
403
+ }
373
404
dep -> diepdma = (uintptr_t ) xfer -> buffer ;
374
- }
375
-
376
- dep -> diepctl = depctl .value ; // enable endpoint
405
+ dep -> diepctl = depctl . value ; // enable endpoint
406
+ } else {
407
+ dep -> diepctl = depctl .value ; // enable endpoint
377
408
378
- // Slave: enable tx fifo empty interrupt only if there is data. Note must after depctl enable
379
- if (!is_dma && dir == TUSB_DIR_IN && total_bytes != 0 ) {
380
- dwc2 -> diepempmsk |= (1 << epnum );
409
+ // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable
410
+ if (dir == TUSB_DIR_IN && total_bytes != 0 ) {
411
+ dwc2 -> diepempmsk |= (1 << epnum );
412
+ }
381
413
}
382
414
}
383
415
@@ -388,6 +420,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
388
420
(void ) rh_init ;
389
421
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
390
422
423
+ tu_memclr (& _dcd_data , sizeof (_dcd_data ));
424
+
391
425
// Core Initialization
392
426
const bool is_highspeed = dwc2_core_is_highspeed (dwc2 , TUSB_ROLE_DEVICE );
393
427
const bool is_dma = dma_device_enabled (dwc2 );
@@ -505,7 +539,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) {
505
539
(void ) rhport ;
506
540
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
507
541
508
- _sof_en = en ;
542
+ _dcd_data . sof_en = en ;
509
543
510
544
if (en ) {
511
545
dwc2 -> gintsts = GINTSTS_SOF ;
@@ -530,7 +564,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
530
564
dwc2_regs_t * dwc2 = DWC2_REG (rhport );
531
565
uint8_t const ep_count = _dwc2_controller [rhport ].ep_count ;
532
566
533
- _allocated_ep_in_count = 1 ;
567
+ _dcd_data . allocated_epin_count = 1 ;
534
568
535
569
// Disable non-control interrupt
536
570
dwc2 -> daintmsk = (1 << DAINTMSK_OEPM_Pos ) | (1 << DAINTMSK_IEPM_Pos );
@@ -578,7 +612,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
578
612
579
613
// EP0 can only handle one packet
580
614
if (epnum == 0 ) {
581
- ep0_pending [dir ] = total_bytes ;
615
+ _dcd_data . ep0_pending [dir ] = total_bytes ;
582
616
}
583
617
584
618
// Schedule packets to be sent within interrupt
@@ -644,8 +678,8 @@ static void handle_bus_reset(uint8_t rhport) {
644
678
645
679
tu_memclr (xfer_status , sizeof (xfer_status ));
646
680
647
- _sof_en = false;
648
- _allocated_ep_in_count = 1 ;
681
+ _dcd_data . sof_en = false;
682
+ _dcd_data . allocated_epin_count = 1 ;
649
683
650
684
// 1. NAK for all OUT endpoints
651
685
for (uint8_t n = 0 ; n < ep_count ; n ++ ) {
@@ -746,12 +780,14 @@ static void handle_rxflvl_irq(uint8_t rhport) {
746
780
// Global OUT NAK: do nothing
747
781
break ;
748
782
749
- case GRXSTS_PKTSTS_SETUP_RX :
783
+ case GRXSTS_PKTSTS_SETUP_RX : {
750
784
// Setup packet received
785
+ uint32_t * setup = (uint32_t * )(uintptr_t ) _dcd_usbbuf .setup_packet ;
751
786
// We can receive up to three setup packets in succession, but only the last one is valid.
752
- _setup_packet [0 ] = (* rx_fifo );
753
- _setup_packet [1 ] = (* rx_fifo );
787
+ setup [0 ] = (* rx_fifo );
788
+ setup [1 ] = (* rx_fifo );
754
789
break ;
790
+ }
755
791
756
792
case GRXSTS_PKTSTS_SETUP_DONE :
757
793
// Setup packet done:
@@ -777,8 +813,8 @@ static void handle_rxflvl_irq(uint8_t rhport) {
777
813
if (byte_count < xfer -> max_size ) {
778
814
xfer -> total_len -= epout -> tsiz_bm .xfer_size ;
779
815
if (epnum == 0 ) {
780
- xfer -> total_len -= ep0_pending [TUSB_DIR_OUT ];
781
- ep0_pending [TUSB_DIR_OUT ] = 0 ;
816
+ xfer -> total_len -= _dcd_data . ep0_pending [TUSB_DIR_OUT ];
817
+ _dcd_data . ep0_pending [TUSB_DIR_OUT ] = 0 ;
782
818
}
783
819
}
784
820
}
@@ -797,7 +833,7 @@ static void handle_rxflvl_irq(uint8_t rhport) {
797
833
798
834
static void handle_epout_slave (uint8_t rhport , uint8_t epnum , dwc2_doepint_t doepint_bm ) {
799
835
if (doepint_bm .setup_phase_done ) {
800
- dcd_event_setup_received (rhport , ( uint8_t * ) _setup_packet , true);
836
+ dcd_event_setup_received (rhport , _dcd_usbbuf . setup_packet , true);
801
837
return ;
802
838
}
803
839
@@ -809,7 +845,7 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe
809
845
if (!doepint_bm .status_phase_rx && !doepint_bm .setup_packet_rx ) {
810
846
xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , TUSB_DIR_OUT );
811
847
812
- if ((epnum == 0 ) && ep0_pending [TUSB_DIR_OUT ]) {
848
+ if ((epnum == 0 ) && _dcd_data . ep0_pending [TUSB_DIR_OUT ]) {
813
849
// EP0 can only handle one packet, Schedule another packet to be received.
814
850
edpt_schedule_packets (rhport , epnum , TUSB_DIR_OUT );
815
851
} else {
@@ -825,7 +861,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep
825
861
xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , TUSB_DIR_IN );
826
862
827
863
if (diepint_bm .xfer_complete ) {
828
- if ((epnum == 0 ) && ep0_pending [TUSB_DIR_IN ]) {
864
+ if ((epnum == 0 ) && _dcd_data . ep0_pending [TUSB_DIR_IN ]) {
829
865
// EP0 can only handle one packet. Schedule another packet to be transmitted.
830
866
edpt_schedule_packets (rhport , epnum , TUSB_DIR_IN );
831
867
} else {
@@ -873,7 +909,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
873
909
874
910
if (doepint_bm .setup_phase_done ) {
875
911
dma_setup_prepare (rhport );
876
- dcd_event_setup_received (rhport , (uint8_t * ) _setup_packet , true);
912
+ dcd_dcache_invalidate (_dcd_usbbuf .setup_packet , 8 );
913
+ dcd_event_setup_received (rhport , _dcd_usbbuf .setup_packet , true);
877
914
return ;
878
915
}
879
916
@@ -882,7 +919,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
882
919
// only handle data skip if it is setup or status related
883
920
// Normal OUT transfer complete
884
921
if (!doepint_bm .status_phase_rx && !doepint_bm .setup_packet_rx ) {
885
- if ((epnum == 0 ) && ep0_pending [TUSB_DIR_OUT ]) {
922
+ if ((epnum == 0 ) && _dcd_data . ep0_pending [TUSB_DIR_OUT ]) {
886
923
// EP0 can only handle one packet Schedule another packet to be received.
887
924
edpt_schedule_packets (rhport , epnum , TUSB_DIR_OUT );
888
925
} else {
@@ -899,6 +936,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
899
936
dma_setup_prepare (rhport );
900
937
}
901
938
939
+ dcd_dcache_invalidate (xfer -> buffer , xfer -> total_len );
902
940
dcd_event_xfer_complete (rhport , epnum , xfer -> total_len , XFER_RESULT_SUCCESS , true);
903
941
}
904
942
}
@@ -909,7 +947,7 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin
909
947
xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , TUSB_DIR_IN );
910
948
911
949
if (diepint_bm .xfer_complete ) {
912
- if ((epnum == 0 ) && ep0_pending [TUSB_DIR_IN ]) {
950
+ if ((epnum == 0 ) && _dcd_data . ep0_pending [TUSB_DIR_IN ]) {
913
951
// EP0 can only handle one packet. Schedule another packet to be transmitted.
914
952
edpt_schedule_packets (rhport , epnum , TUSB_DIR_IN );
915
953
} else {
@@ -1016,7 +1054,7 @@ void dcd_int_handler(uint8_t rhport) {
1016
1054
1017
1055
if (gintsts & GINTSTS_OTGINT ) {
1018
1056
// OTG INT bit is read-only
1019
- uint32_t const otg_int = dwc2 -> gotgint ;
1057
+ const uint32_t otg_int = dwc2 -> gotgint ;
1020
1058
1021
1059
if (otg_int & GOTGINT_SEDET ) {
1022
1060
dcd_event_bus_signal (rhport , DCD_EVENT_UNPLUGGED , true);
@@ -1033,7 +1071,7 @@ void dcd_int_handler(uint8_t rhport) {
1033
1071
const uint32_t frame = (dwc2 -> dsts & DSTS_FNSOF ) >> DSTS_FNSOF_Pos ;
1034
1072
1035
1073
// Disable SOF interrupt if SOF was not explicitly enabled since SOF was used for remote wakeup detection
1036
- if (!_sof_en ) {
1074
+ if (!_dcd_data . sof_en ) {
1037
1075
dwc2 -> gintmsk &= ~GINTMSK_SOFM ;
1038
1076
}
1039
1077
0 commit comments