42
42
43
43
#include "device/dcd.h"
44
44
45
- // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
46
- // We disable SOF for now until needed later on
47
- #define USE_SOF 0
48
-
49
45
// Max number of bi-directional endpoints including EP0
50
46
// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0
51
47
// We should probably prohibit enabling Endpoint IN > 4 (not done yet)
@@ -92,11 +88,12 @@ static void bus_reset(void)
92
88
USB0 .out_ep_reg [ep_num ].doepctl |= USB_DO_SNAK0_M ; // DOEPCTL0_SNAK
93
89
}
94
90
95
- USB0 .dcfg &= ~USB_DEVADDR_M ; // reset address
91
+ // clear device address
92
+ USB0 .dcfg &= ~USB_DEVADDR_M ;
96
93
97
- USB0 .daintmsk | = USB_OUTEPMSK0_M | USB_INEPMSK0_M ;
98
- USB0 .doepmsk | = USB_SETUPMSK_M | USB_XFERCOMPLMSK ;
99
- USB0 .diepmsk | = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/ ;
94
+ USB0 .daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M ;
95
+ USB0 .doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK ;
96
+ USB0 .diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/ ;
100
97
101
98
// "USB Data FIFOs" section in reference manual
102
99
// Peripheral FIFO architecture
@@ -166,8 +163,6 @@ static void enum_done_processing(void)
166
163
*------------------------------------------------------------------*/
167
164
void dcd_init (uint8_t rhport )
168
165
{
169
- (void )rhport ;
170
-
171
166
ESP_LOGV (TAG , "DCD init - Start" );
172
167
173
168
bool did_persist = (USB_WRAP .date .val & (1 << 31 )) != 0 ;
@@ -205,9 +200,6 @@ void dcd_init(uint8_t rhport)
205
200
206
201
USB0 .gintmsk = USB_OTGINTMSK_M |
207
202
USB_MODEMISMSK_M |
208
- #if USE_SOF
209
- USB_SOFMSK_M |
210
- #endif
211
203
USB_RXFLVIMSK_M |
212
204
USB_ERLYSUSPMSK_M |
213
205
USB_USBSUSPMSK_M |
@@ -265,8 +257,17 @@ void dcd_remote_wakeup(uint8_t rhport)
265
257
{
266
258
(void )rhport ;
267
259
268
- // TODO must manually clear this bit after 1-15 ms
269
- // USB0.DCTL |= USB_RMTWKUPSIG_M;
260
+ // set remote wakeup
261
+ USB0 .dctl |= USB_RMTWKUPSIG_M ;
262
+
263
+ // enable SOF to detect bus resume
264
+ USB0 .gintsts = USB_SOF_M ;
265
+ USB0 .gintmsk |= USB_SOFMSK_M ;
266
+
267
+ // Per specs: remote wakeup signal bit must be clear within 1-15ms
268
+ vTaskDelay (pdMS_TO_TICKS (1 ));
269
+
270
+ USB0 .dctl &= ~USB_RMTWKUPSIG_M ;
270
271
}
271
272
272
273
// connect by enabling internal pull-up resistor on D+/D-
@@ -305,10 +306,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
305
306
xfer -> max_size = desc_edpt -> wMaxPacketSize .size ;
306
307
307
308
if (dir == TUSB_DIR_OUT ) {
308
- out_ep [epnum ].doepctl &= ~(USB_D_EPTYPE1_M | USB_D_MPS1_M );
309
- out_ep [epnum ].doepctl |= USB_USBACTEP0_M |
310
- desc_edpt -> bmAttributes .xfer << USB_EPTYPE0_S |
311
- desc_edpt -> wMaxPacketSize .size << USB_MPS0_S ;
309
+ out_ep [epnum ].doepctl &= ~(USB_D_EPTYPE0_M | USB_D_MPS0_M );
310
+ out_ep [epnum ].doepctl |= USB_USBACTEP1_M |
311
+ desc_edpt -> bmAttributes .xfer << USB_EPTYPE1_S |
312
+ (desc_edpt -> bmAttributes .xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0 ) |
313
+ desc_edpt -> wMaxPacketSize .size << USB_MPS1_S ;
312
314
USB0 .daintmsk |= (1 << (16 + epnum ));
313
315
} else {
314
316
// "USB Data FIFOs" section in reference manual
@@ -330,8 +332,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
330
332
// --------------- 0
331
333
//
332
334
// Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints
333
- // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_FIFO_NUM-1)
334
- // - Offset: GRXFSIZ + 16 + Size*(fifo_num-1)
335
+ // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1)
336
+ // - Offset: GRXFSIZ + 16 + Size*(epnum-1)
337
+ // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
335
338
336
339
uint8_t fifo_num = 0 ;
337
340
// Special Case for EP5, which is used by CDC but not actually called by the driver
@@ -367,7 +370,25 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
367
370
void dcd_edpt_close_all (uint8_t rhport )
368
371
{
369
372
(void ) rhport ;
370
- // TODO implement dcd_edpt_close_all()
373
+
374
+ usb_out_endpoint_t * out_ep = & (USB0 .out_ep_reg [0 ]);
375
+ usb_in_endpoint_t * in_ep = & (USB0 .in_ep_reg [0 ]);
376
+
377
+ // Disable non-control interrupt
378
+ USB0 .daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M ;
379
+
380
+ for (uint8_t n = 1 ; n < EP_MAX ; n ++ )
381
+ {
382
+ // disable OUT endpoint
383
+ out_ep [n ].doepctl = 0 ;
384
+ xfer_status [n ][TUSB_DIR_OUT ].max_size = 0 ;
385
+
386
+ // disable IN endpoint
387
+ in_ep [n ].diepctl = 0 ;
388
+ xfer_status [n ][TUSB_DIR_IN ].max_size = 0 ;
389
+ }
390
+
391
+ _allocated_fifos = 1 ;
371
392
}
372
393
373
394
bool dcd_edpt_xfer (uint8_t rhport , uint8_t ep_addr , uint8_t * buffer , uint16_t total_bytes )
@@ -419,49 +440,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
419
440
bool dcd_edpt_xfer_fifo (uint8_t rhport , uint8_t ep_addr , tu_fifo_t * ff , uint16_t total_bytes )
420
441
{
421
442
(void )rhport ;
422
-
423
- // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
424
- TU_ASSERT (ff -> item_size == 1 );
425
-
426
- uint8_t const epnum = tu_edpt_number (ep_addr );
427
- uint8_t const dir = tu_edpt_dir (ep_addr );
428
-
429
- xfer_ctl_t * xfer = XFER_CTL_BASE (epnum , dir );
430
- xfer -> buffer = NULL ;
431
- xfer -> ff = ff ;
432
- xfer -> total_len = total_bytes ;
433
- xfer -> queued_len = 0 ;
434
- xfer -> short_packet = false;
435
-
436
- uint16_t num_packets = (total_bytes / xfer -> max_size );
437
- uint8_t short_packet_size = total_bytes % xfer -> max_size ;
438
-
439
- // Zero-size packet is special case.
440
- if (short_packet_size > 0 || (total_bytes == 0 )) {
441
- num_packets ++ ;
442
- }
443
-
444
- ESP_LOGV (TAG , "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i" ,
445
- epnum , ((dir == TUSB_DIR_IN ) ? "USB0.HOST (in)" : "HOST->DEV (out)" ),
446
- num_packets , total_bytes );
447
-
448
- // IN and OUT endpoint xfers are interrupt-driven, we just schedule them
449
- // here.
450
- if (dir == TUSB_DIR_IN ) {
451
- // A full IN transfer (multiple packets, possibly) triggers XFRC.
452
- USB0 .in_ep_reg [epnum ].dieptsiz = (num_packets << USB_D_PKTCNT0_S ) | total_bytes ;
453
- USB0 .in_ep_reg [epnum ].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M ; // Enable | CNAK
454
-
455
- // Enable fifo empty interrupt only if there are something to put in the fifo.
456
- if (total_bytes != 0 ) {
457
- USB0 .dtknqr4_fifoemptymsk |= (1 << epnum );
458
- }
459
- } else {
460
- // Each complete packet for OUT xfers triggers XFRC.
461
- USB0 .out_ep_reg [epnum ].doeptsiz |= USB_PKTCNT0_M | ((xfer -> max_size & USB_XFERSIZE0_V ) << USB_XFERSIZE0_S );
462
- USB0 .out_ep_reg [epnum ].doepctl |= USB_EPENA0_M | USB_CNAK0_M ;
463
- }
464
- return true;
465
443
}
466
444
#endif
467
445
@@ -769,27 +747,26 @@ static void handle_epin_ints(void)
769
747
xfer_ctl_t * xfer = & xfer_status [n ][TUSB_DIR_IN ];
770
748
771
749
if (USB0 .daint & (1 << (0 + n ))) {
772
- uint32_t const in_status = USB0 .in_ep_reg [n ].diepint ;
773
750
ESP_EARLY_LOGV (TAG , "TUSB IRQ - EP IN %u" , n );
774
751
775
- if (in_status & BIT (15 )) {
752
+ if (USB0 . in_ep_reg [ n ]. diepint & BIT (15 )) {
776
753
USB0 .in_ep_reg [n ].diepint = BIT (15 );
777
754
ESP_EARLY_LOGE (TAG , "Unknown Condition" );//todo:
778
755
bus_reset ();
779
756
}
780
757
781
758
// IN XFER complete (entire xfer).
782
- if (in_status & USB_D_XFERCOMPL0_M ) {
759
+ if (USB0 . in_ep_reg [ n ]. diepint & USB_D_XFERCOMPL0_M ) {
783
760
ESP_EARLY_LOGV (TAG , "TUSB IRQ - IN XFER complete!" );
784
761
USB0 .in_ep_reg [n ].diepint = USB_D_XFERCOMPL0_M ;
785
762
dcd_event_xfer_complete (0 , n | TUSB_DIR_IN_MASK , xfer -> total_len , XFER_RESULT_SUCCESS , true);
786
- if (!(in_status & USB_D_TXFEMP0_M )) {
763
+ if (!(USB0 . in_ep_reg [ n ]. diepint & USB_D_TXFEMP0_M )) {
787
764
ESP_EARLY_LOGE (TAG , "Complete but not empty: %u/%u" , xfer -> queued_len , xfer -> total_len );//todo:
788
765
}
789
766
}
790
767
791
768
// XFER FIFO empty
792
- if (in_status & USB_D_TXFEMP0_M ) {
769
+ if (USB0 . in_ep_reg [ n ]. diepint & USB_D_TXFEMP0_M ) {
793
770
ESP_EARLY_LOGV (TAG , "TUSB IRQ - IN XFER FIFO empty!" );
794
771
USB0 .in_ep_reg [n ].diepint = USB_D_TXFEMP0_M ;
795
772
transmit_packet (xfer , & USB0 .in_ep_reg [n ], n );
@@ -801,9 +778,12 @@ static void handle_epin_ints(void)
801
778
}
802
779
}
803
780
804
- // Timeout sending the last packet
805
- if (in_status & USB_D_TIMEOUT0_M ) {
781
+ // XFER Timeout
782
+ if (USB0 .in_ep_reg [n ].diepint & USB_D_TIMEOUT0_M ) {
783
+ // Clear interrupt or enpoint will hang.
806
784
USB0 .in_ep_reg [n ].diepint = USB_D_TIMEOUT0_M ;
785
+ ESP_EARLY_LOGE (TAG , "XFER Timeout" );//todo:
786
+ // Maybe retry?
807
787
}
808
788
}
809
789
}
@@ -815,8 +795,8 @@ static void _dcd_int_handler(void* arg)
815
795
(void ) arg ;
816
796
uint8_t const rhport = 0 ;
817
797
818
- const uint32_t int_status = USB0 .gintsts ;
819
- // const uint32_t int_msk = USB0.gintmsk ;
798
+ const uint32_t int_msk = USB0 .gintmsk ;
799
+ const uint32_t int_status = USB0 .gintsts & int_msk ;
820
800
821
801
if (int_status & USB_USBRST_M ) {
822
802
// start of reset
@@ -830,8 +810,8 @@ static void _dcd_int_handler(void* arg)
830
810
if (int_status & USB_RESETDET_M ) {
831
811
ESP_EARLY_LOGV (TAG , "dcd_int_handler - reset while suspend" );
832
812
USB0 .gintsts = USB_RESETDET_M ;
813
+ // no need to double reset
833
814
if ((int_status & USB_USBRST_M ) == 0 ) {
834
- // no need to double reset
835
815
_allocated_fifos = 1 ;
836
816
bus_reset ();
837
817
}
@@ -846,9 +826,8 @@ static void _dcd_int_handler(void* arg)
846
826
dcd_event_bus_reset (rhport , TUSB_SPEED_FULL , true);
847
827
}
848
828
849
- if (int_status & USB_USBSUSP_M ) {
850
- // start of reset
851
- ESP_EARLY_LOGV (TAG , "dcd_int_handler - suspended" );
829
+ if (int_status & USB_USBSUSP_M )
830
+ {
852
831
USB0 .gintsts = USB_USBSUSP_M ;
853
832
//dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
854
833
dcd_event_bus_signal (rhport , DCD_EVENT_UNPLUGGED , true);
@@ -877,12 +856,15 @@ static void _dcd_int_handler(void* arg)
877
856
USB0 .gotgint = otg_int ;
878
857
}
879
858
880
- #if USE_SOF
881
859
if (int_status & USB_SOF_M ) {
882
860
USB0 .gintsts = USB_SOF_M ;
883
- dcd_event_bus_signal (rhport , DCD_EVENT_SOF , true); // do nothing actually
861
+
862
+ // Disable SOF interrupt since currently only used for remote wakeup detection
863
+ USB0 .gintmsk &= ~USB_SOFMSK_M ;
864
+
865
+ dcd_event_bus_signal (rhport , DCD_EVENT_SOF , true);
884
866
}
885
- #endif
867
+
886
868
887
869
if (int_status & USB_RXFLVI_M ) {
888
870
// RXFLVL bit is read-only
0 commit comments