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

Lines changed: 63 additions & 81 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy