4242
4343#include "device/dcd.h"
4444
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-
4945// Max number of bi-directional endpoints including EP0
5046// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0
5147// We should probably prohibit enabling Endpoint IN > 4 (not done yet)
@@ -92,11 +88,12 @@ static void bus_reset(void)
9288 USB0 .out_ep_reg [ep_num ].doepctl |= USB_DO_SNAK0_M ; // DOEPCTL0_SNAK
9389 }
9490
95- USB0 .dcfg &= ~USB_DEVADDR_M ; // reset address
91+ // clear device address
92+ USB0 .dcfg &= ~USB_DEVADDR_M ;
9693
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*/ ;
10097
10198 // "USB Data FIFOs" section in reference manual
10299 // Peripheral FIFO architecture
@@ -166,8 +163,6 @@ static void enum_done_processing(void)
166163 *------------------------------------------------------------------*/
167164void dcd_init (uint8_t rhport )
168165{
169- (void )rhport ;
170-
171166 ESP_LOGV (TAG , "DCD init - Start" );
172167
173168 bool did_persist = (USB_WRAP .date .val & (1 << 31 )) != 0 ;
@@ -205,9 +200,6 @@ void dcd_init(uint8_t rhport)
205200
206201 USB0 .gintmsk = USB_OTGINTMSK_M |
207202 USB_MODEMISMSK_M |
208- #if USE_SOF
209- USB_SOFMSK_M |
210- #endif
211203 USB_RXFLVIMSK_M |
212204 USB_ERLYSUSPMSK_M |
213205 USB_USBSUSPMSK_M |
@@ -265,8 +257,17 @@ void dcd_remote_wakeup(uint8_t rhport)
265257{
266258 (void )rhport ;
267259
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 ;
270271}
271272
272273// 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)
305306 xfer -> max_size = desc_edpt -> wMaxPacketSize .size ;
306307
307308 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 ;
312314 USB0 .daintmsk |= (1 << (16 + epnum ));
313315 } else {
314316 // "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)
330332 // --------------- 0
331333 //
332334 // 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".
335338
336339 uint8_t fifo_num = 0 ;
337340 // 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)
367370void dcd_edpt_close_all (uint8_t rhport )
368371{
369372 (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 ;
371392}
372393
373394bool 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
419440bool dcd_edpt_xfer_fifo (uint8_t rhport , uint8_t ep_addr , tu_fifo_t * ff , uint16_t total_bytes )
420441{
421442 (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;
465443}
466444#endif
467445
@@ -769,27 +747,26 @@ static void handle_epin_ints(void)
769747 xfer_ctl_t * xfer = & xfer_status [n ][TUSB_DIR_IN ];
770748
771749 if (USB0 .daint & (1 << (0 + n ))) {
772- uint32_t const in_status = USB0 .in_ep_reg [n ].diepint ;
773750 ESP_EARLY_LOGV (TAG , "TUSB IRQ - EP IN %u" , n );
774751
775- if (in_status & BIT (15 )) {
752+ if (USB0 . in_ep_reg [ n ]. diepint & BIT (15 )) {
776753 USB0 .in_ep_reg [n ].diepint = BIT (15 );
777754 ESP_EARLY_LOGE (TAG , "Unknown Condition" );//todo:
778755 bus_reset ();
779756 }
780757
781758 // 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 ) {
783760 ESP_EARLY_LOGV (TAG , "TUSB IRQ - IN XFER complete!" );
784761 USB0 .in_ep_reg [n ].diepint = USB_D_XFERCOMPL0_M ;
785762 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 )) {
787764 ESP_EARLY_LOGE (TAG , "Complete but not empty: %u/%u" , xfer -> queued_len , xfer -> total_len );//todo:
788765 }
789766 }
790767
791768 // XFER FIFO empty
792- if (in_status & USB_D_TXFEMP0_M ) {
769+ if (USB0 . in_ep_reg [ n ]. diepint & USB_D_TXFEMP0_M ) {
793770 ESP_EARLY_LOGV (TAG , "TUSB IRQ - IN XFER FIFO empty!" );
794771 USB0 .in_ep_reg [n ].diepint = USB_D_TXFEMP0_M ;
795772 transmit_packet (xfer , & USB0 .in_ep_reg [n ], n );
@@ -801,9 +778,12 @@ static void handle_epin_ints(void)
801778 }
802779 }
803780
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.
806784 USB0 .in_ep_reg [n ].diepint = USB_D_TIMEOUT0_M ;
785+ ESP_EARLY_LOGE (TAG , "XFER Timeout" );//todo:
786+ // Maybe retry?
807787 }
808788 }
809789 }
@@ -815,8 +795,8 @@ static void _dcd_int_handler(void* arg)
815795 (void ) arg ;
816796 uint8_t const rhport = 0 ;
817797
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 ;
820800
821801 if (int_status & USB_USBRST_M ) {
822802 // start of reset
@@ -830,8 +810,8 @@ static void _dcd_int_handler(void* arg)
830810 if (int_status & USB_RESETDET_M ) {
831811 ESP_EARLY_LOGV (TAG , "dcd_int_handler - reset while suspend" );
832812 USB0 .gintsts = USB_RESETDET_M ;
813+ // no need to double reset
833814 if ((int_status & USB_USBRST_M ) == 0 ) {
834- // no need to double reset
835815 _allocated_fifos = 1 ;
836816 bus_reset ();
837817 }
@@ -846,9 +826,8 @@ static void _dcd_int_handler(void* arg)
846826 dcd_event_bus_reset (rhport , TUSB_SPEED_FULL , true);
847827 }
848828
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+ {
852831 USB0 .gintsts = USB_USBSUSP_M ;
853832 //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
854833 dcd_event_bus_signal (rhport , DCD_EVENT_UNPLUGGED , true);
@@ -877,12 +856,15 @@ static void _dcd_int_handler(void* arg)
877856 USB0 .gotgint = otg_int ;
878857 }
879858
880- #if USE_SOF
881859 if (int_status & USB_SOF_M ) {
882860 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);
884866 }
885- #endif
867+
886868
887869 if (int_status & USB_RXFLVI_M ) {
888870 // RXFLVL bit is read-only
0 commit comments