Skip to content

Commit 59ccd97

Browse files
committed
Update dcd_esp32sx.c
1 parent 247570b commit 59ccd97

File tree

1 file changed

+63
-81
lines changed

1 file changed

+63
-81
lines changed

components/arduino_tinyusb/src/dcd_esp32sx.c

+63-81
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@
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
*------------------------------------------------------------------*/
167164
void 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)
367370
void 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

373394
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
419440
bool 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

Comments
 (0)