Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit eda5d26

Browse files
committedNov 12, 2024
Update TinyUSB DCD Source
1 parent 1684457 commit eda5d26

File tree

3 files changed

+118
-390
lines changed

3 files changed

+118
-390
lines changed
 

‎components/arduino_tinyusb/patches/dcd_dwc2.patch

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
--- a/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:17:40.000000000 +0300
22
+++ b/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:19:48.000000000 +0300
3-
@@ -316,6 +316,16 @@
3+
@@ -209,6 +209,17 @@
44
//--------------------------------------------------------------------
55
// Endpoint
66
//--------------------------------------------------------------------
@@ -14,10 +14,11 @@
1414
+ return 0;
1515
+}
1616
+#endif
17-
17+
+
1818
static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) {
1919
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
20-
@@ -332,7 +342,19 @@
20+
uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
21+
@@ -224,7 +235,19 @@
2122
(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) |
2223
(xfer->max_size << DOEPCTL_MPSIZ_Pos);
2324
if (dir == TUSB_DIR_IN) {
@@ -38,7 +39,7 @@
3839
}
3940

4041
dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum];
41-
@@ -840,6 +862,10 @@
42+
@@ -304,6 +327,10 @@
4243
}
4344
}
4445

@@ -49,7 +50,7 @@
4950
dfifo_flush_tx(dwc2, 0x10); // all tx fifo
5051
dfifo_flush_rx(dwc2);
5152

52-
@@ -1186,6 +1212,9 @@
53+
@@ -908,6 +935,9 @@
5354
if (int_status & GINTSTS_USBRST) {
5455
// USBRST is start of reset.
5556
dwc2->gintsts = GINTSTS_USBRST;
@@ -59,7 +60,7 @@
5960
bus_reset(rhport);
6061
}
6162

62-
@@ -1217,7 +1246,11 @@
63+
@@ -939,7 +969,11 @@
6364

6465
if (int_status & GINTSTS_USBSUSP) {
6566
dwc2->gintsts = GINTSTS_USBSUSP;
@@ -72,7 +73,7 @@
7273
}
7374

7475
if (int_status & GINTSTS_WKUINT) {
75-
@@ -1234,6 +1267,9 @@
76+
@@ -956,6 +990,9 @@
7677

7778
if (otg_int & GOTGINT_SEDET) {
7879
dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);

‎components/arduino_tinyusb/src/dcd_dwc2.c

Lines changed: 106 additions & 383 deletions
Original file line numberDiff line numberDiff line change
@@ -35,45 +35,7 @@
3535
#define DWC2_DEBUG 2
3636

3737
#include "device/dcd.h"
38-
#include "dwc2_type.h"
39-
40-
// Following symbols must be defined by port header
41-
// - _dwc2_controller[]: array of controllers
42-
// - DWC2_EP_MAX: largest EP counts of all controllers
43-
// - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset
44-
// - dwc2_dcd_int_enable/dwc2_dcd_int_disable
45-
// - dwc2_remote_wakeup_delay
46-
47-
#if defined(TUP_USBIP_DWC2_STM32)
48-
#include "dwc2_stm32.h"
49-
#elif defined(TUP_USBIP_DWC2_ESP32)
50-
#include "dwc2_esp32.h"
51-
#elif TU_CHECK_MCU(OPT_MCU_GD32VF103)
52-
#include "dwc2_gd32.h"
53-
#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837)
54-
#include "dwc2_bcm.h"
55-
#elif TU_CHECK_MCU(OPT_MCU_EFM32GG)
56-
#include "dwc2_efm32.h"
57-
#elif TU_CHECK_MCU(OPT_MCU_XMC4000)
58-
#include "dwc2_xmc.h"
59-
#else
60-
#error "Unsupported MCUs"
61-
#endif
62-
63-
enum {
64-
DWC2_CONTROLLER_COUNT = TU_ARRAY_SIZE(_dwc2_controller)
65-
};
66-
67-
// DWC2 registers
68-
//#define DWC2_REG(_port) ((dwc2_regs_t*) _dwc2_controller[_port].reg_base)
69-
70-
TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) {
71-
if (rhport >= DWC2_CONTROLLER_COUNT) {
72-
// user mis-configured, ignore and use first controller
73-
rhport = 0;
74-
}
75-
return (dwc2_regs_t*) _dwc2_controller[rhport].reg_base;
76-
}
38+
#include "dwc2_common.h"
7739

7840
//--------------------------------------------------------------------+
7941
// MACRO TYPEDEF CONSTANT ENUM
@@ -94,7 +56,7 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2];
9456

9557
// EP0 transfers are limited to 1 packet - larger sizes has to be split
9658
static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type
97-
static uint16_t _dfifo_top; // top free location in FIFO RAM
59+
static uint16_t _dfifo_top; // top free location in DFIFO in words
9860

9961
// Number of IN endpoints active
10062
static uint8_t _allocated_ep_in_count;
@@ -106,20 +68,10 @@ static bool _sof_en;
10668
// DMA
10769
//--------------------------------------------------------------------
10870

109-
TU_ATTR_ALWAYS_INLINE static inline bool dma_enabled(const dwc2_regs_t* dwc2) {
110-
#if !CFG_TUD_DWC2_DMA
71+
TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) {
11172
(void) dwc2;
112-
return false;
113-
#else
11473
// Internal DMA only
115-
return (dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA);
116-
#endif
117-
}
118-
119-
TU_ATTR_ALWAYS_INLINE static inline uint16_t dma_cal_epfifo_base(uint8_t rhport) {
120-
// Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction
121-
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
122-
return dwc2_controller->ep_fifo_size/4 - 2*dwc2_controller->ep_count;
74+
return CFG_TUD_DWC2_DMA && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA;
12375
}
12476

12577
static void dma_setup_prepare(uint8_t rhport) {
@@ -141,18 +93,8 @@ static void dma_setup_prepare(uint8_t rhport) {
14193
// Data FIFO
14294
//--------------------------------------------------------------------+
14395

144-
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_tx(dwc2_regs_t* dwc2, uint8_t epnum) {
145-
// flush TX fifo and wait for it cleared
146-
dwc2->grstctl = GRSTCTL_TXFFLSH | (epnum << GRSTCTL_TXFNUM_Pos);
147-
while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {}
148-
}
149-
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) {
150-
// flush RX fifo and wait for it cleared
151-
dwc2->grstctl = GRSTCTL_RXFFLSH;
152-
while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {}
153-
}
15496

155-
/* USB Data FIFO Layout
97+
/* Device Data FIFO scheme
15698
15799
The FIFO is split up into
158100
- EPInfo: for storing DMA metadata, only required when use DMA. Maximum size is called
@@ -167,11 +109,9 @@ TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) {
167109
possible since the free space is located between the RX and TX FIFOs.
168110
169111
---------------- ep_fifo_size
170-
| EPInfo |
171-
| for DMA |
112+
| DxEPIDMAn |
172113
|-------------|-- gdfifocfg.EPINFOBASE (max is ghwcfg3.dfifo_depth)
173-
| IN FIFO 0 |
174-
| control |
114+
| IN FIFO 0 | control EP
175115
|-------------|
176116
| IN FIFO 1 |
177117
|-------------|
@@ -190,13 +130,13 @@ TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) {
190130
- All EP OUT shared a unique OUT FIFO which uses (for Slave or Buffer DMA, Scatt/Gather DMA use different formula):
191131
- 13 for setup packets + control words (up to 3 setup packets).
192132
- 1 for global NAK (not required/used here).
193-
- Largest-EPsize / 4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4) + 1"
133+
- Largest-EPsize/4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)"
194134
- 2 for each used OUT endpoint
195135
196136
Therefore GRXFSIZ = 13 + 1 + 2 x (Largest-EPsize/4 + 1) + 2 x EPOUTnum
197137
*/
198138

199-
TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) {
139+
TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) {
200140
return 13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count;
201141
}
202142

@@ -212,7 +152,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
212152
uint16_t fifo_size = tu_div_ceil(packet_size, 4);
213153
if (dir == TUSB_DIR_OUT) {
214154
// Calculate required size of RX FIFO
215-
uint16_t const new_sz = calc_grxfsiz(4 * fifo_size, ep_count);
155+
uint16_t const new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count);
216156

217157
// If size_rx needs to be extended check if there is enough free space
218158
if (dwc2->grxfsiz < new_sz) {
@@ -227,7 +167,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
227167
}
228168

229169
// If The TXFELVL is configured as half empty, the fifo must be twice the max_size.
230-
if ((dwc2->gahbcfg & GAHBCFG_TXFELVL) == 0) {
170+
if ((dwc2->gahbcfg & GAHBCFG_TX_FIFO_EPMTY_LVL) == 0) {
231171
fifo_size *= 2;
232172
}
233173

@@ -248,70 +188,23 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
248188
return true;
249189
}
250190

251-
static void dfifo_init(uint8_t rhport) {
191+
static void dfifo_device_init(uint8_t rhport) {
252192
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
253193
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
254-
dwc2->grxfsiz = calc_grxfsiz(CFG_TUD_ENDPOINT0_SIZE, dwc2_controller->ep_count);
194+
dwc2->grxfsiz = calc_device_grxfsiz(CFG_TUD_ENDPOINT0_SIZE, dwc2_controller->ep_count);
255195

256-
if(dma_enabled(dwc2)) {
257-
// DMA use last DFIFO to store metadata
258-
_dfifo_top = dma_cal_epfifo_base(rhport);
259-
}else {
260-
_dfifo_top = dwc2_controller->ep_fifo_size / 4;
196+
// Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction
197+
const bool is_dma = dma_device_enabled(dwc2);
198+
_dfifo_top = dwc2_controller->ep_fifo_size/4;
199+
if (is_dma) {
200+
_dfifo_top -= 2 * dwc2_controller->ep_count;
261201
}
202+
dwc2->gdfifocfg = (_dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dfifo_top;
262203

263204
// Allocate FIFO for EP0 IN
264205
dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE);
265206
}
266207

267-
// Read a single data packet from receive FIFO
268-
static void dfifo_read_packet(uint8_t rhport, uint8_t* dst, uint16_t len) {
269-
(void) rhport;
270-
271-
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
272-
volatile const uint32_t* rx_fifo = dwc2->fifo[0];
273-
274-
// Reading full available 32 bit words from fifo
275-
uint16_t full_words = len >> 2;
276-
while (full_words--) {
277-
tu_unaligned_write32(dst, *rx_fifo);
278-
dst += 4;
279-
}
280-
281-
// Read the remaining 1-3 bytes from fifo
282-
uint8_t const bytes_rem = len & 0x03;
283-
if (bytes_rem != 0) {
284-
uint32_t const tmp = *rx_fifo;
285-
dst[0] = tu_u32_byte0(tmp);
286-
if (bytes_rem > 1) dst[1] = tu_u32_byte1(tmp);
287-
if (bytes_rem > 2) dst[2] = tu_u32_byte2(tmp);
288-
}
289-
}
290-
291-
// Write a single data packet to EPIN FIFO
292-
static void dfifo_write_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const* src, uint16_t len) {
293-
(void) rhport;
294-
295-
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
296-
volatile uint32_t* tx_fifo = dwc2->fifo[fifo_num];
297-
298-
// Pushing full available 32 bit words to fifo
299-
uint16_t full_words = len >> 2;
300-
while (full_words--) {
301-
*tx_fifo = tu_unaligned_read32(src);
302-
src += 4;
303-
}
304-
305-
// Write the remaining 1-3 bytes into fifo
306-
uint8_t const bytes_rem = len & 0x03;
307-
if (bytes_rem) {
308-
uint32_t tmp_word = src[0];
309-
if (bytes_rem > 1) tmp_word |= (src[1] << 8);
310-
if (bytes_rem > 2) tmp_word |= (src[2] << 16);
311-
312-
*tx_fifo = tmp_word;
313-
}
314-
}
315208

316209
//--------------------------------------------------------------------
317210
// Endpoint
@@ -326,7 +219,7 @@ static uint8_t get_free_fifo(void) {
326219
return 0;
327220
}
328221
#endif
329-
222+
330223
static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) {
331224
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
332225
uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
@@ -434,6 +327,10 @@ static void bus_reset(uint8_t rhport) {
434327
}
435328
}
436329

330+
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
331+
_allocated_fifos = 1;
332+
#endif
333+
437334
dfifo_flush_tx(dwc2, 0x10); // all tx fifo
438335
dfifo_flush_rx(dwc2);
439336

@@ -443,7 +340,7 @@ static void bus_reset(uint8_t rhport) {
443340
dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM;
444341

445342
// 4. Set up DFIFO
446-
dfifo_init(rhport);
343+
dfifo_device_init(rhport);
447344

448345
// 5. Reset device address
449346
dwc2->dcfg &= ~DCFG_DAD_Msk;
@@ -455,7 +352,7 @@ static void bus_reset(uint8_t rhport) {
455352
xfer_status[0][TUSB_DIR_OUT].max_size = 64;
456353
xfer_status[0][TUSB_DIR_IN].max_size = 64;
457354

458-
if(dma_enabled(dwc2)) {
355+
if(dma_device_enabled(dwc2)) {
459356
dma_setup_prepare(rhport);
460357
} else {
461358
dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos);
@@ -485,9 +382,9 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
485382
if (dir == TUSB_DIR_IN) {
486383
// A full IN transfer (multiple packets, possibly) triggers XFRC.
487384
dep->dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) |
488-
((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk);
385+
((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk);
489386

490-
if(dma_enabled(dwc2)) {
387+
if(dma_device_enabled(dwc2)) {
491388
dep->diepdma = (uintptr_t)xfer->buffer;
492389

493390
// For ISO endpoint set correct odd/even bit for next frame.
@@ -525,231 +422,69 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
525422
dep->doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk);
526423
}
527424

528-
if(dma_enabled(dwc2)) {
425+
if(dma_device_enabled(dwc2)) {
529426
dep->doepdma = (uintptr_t)xfer->buffer;
530427
}
531428

532429
dep->doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK;
533430
}
534431
}
535432

536-
/*------------------------------------------------------------------*/
537-
/* Controller API
538-
*------------------------------------------------------------------*/
539-
540-
static void reset_core(dwc2_regs_t* dwc2) {
541-
// reset core
542-
dwc2->grstctl |= GRSTCTL_CSRST;
543-
544-
// wait for reset bit is cleared
545-
// TODO version 4.20a should wait for RESET DONE mask
546-
while (dwc2->grstctl & GRSTCTL_CSRST) {}
547-
548-
// wait for AHB master IDLE
549-
while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {}
550-
551-
// wait for device mode ?
552-
}
553-
554-
static bool phy_hs_supported(dwc2_regs_t* dwc2) {
555-
(void) dwc2;
556-
557-
#if !TUD_OPT_HIGH_SPEED
558-
return false;
559-
#else
560-
return dwc2->ghwcfg2_bm.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED;
561-
#endif
562-
}
563-
564-
static void phy_fs_init(dwc2_regs_t* dwc2) {
565-
TU_LOG(DWC2_DEBUG, "Fullspeed PHY init\r\n");
566-
567-
// Select FS PHY
568-
dwc2->gusbcfg |= GUSBCFG_PHYSEL;
569-
570-
// MCU specific PHY init before reset
571-
dwc2_phy_init(dwc2, GHWCFG2_HSPHY_NOT_SUPPORTED);
572-
573-
// Reset core after selecting PHY
574-
reset_core(dwc2);
575-
576-
// USB turnaround time is critical for certification where long cables and 5-Hubs are used.
577-
// So if you need the AHB to run at less than 30 MHz, and if USB turnaround time is not critical,
578-
// these bits can be programmed to a larger value. Default is 5
579-
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (5u << GUSBCFG_TRDT_Pos);
580-
581-
// MCU specific PHY update post reset
582-
dwc2_phy_update(dwc2, GHWCFG2_HSPHY_NOT_SUPPORTED);
583-
584-
// set max speed
585-
dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_FS << DCFG_DSPD_Pos);
586-
}
587-
588-
static void phy_hs_init(dwc2_regs_t* dwc2) {
589-
uint32_t gusbcfg = dwc2->gusbcfg;
590-
591-
// De-select FS PHY
592-
gusbcfg &= ~GUSBCFG_PHYSEL;
593-
594-
if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
595-
TU_LOG(DWC2_DEBUG, "Highspeed ULPI PHY init\r\n");
596-
597-
// Select ULPI
598-
gusbcfg |= GUSBCFG_ULPI_UTMI_SEL;
599-
600-
// ULPI 8-bit interface, single data rate
601-
gusbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
602-
603-
// default internal VBUS Indicator and Drive
604-
gusbcfg &= ~(GUSBCFG_ULPIEVBUSD | GUSBCFG_ULPIEVBUSI);
605-
606-
// Disable FS/LS ULPI
607-
gusbcfg &= ~(GUSBCFG_ULPIFSLS | GUSBCFG_ULPICSM);
608-
} else {
609-
TU_LOG(DWC2_DEBUG, "Highspeed UTMI+ PHY init\r\n");
610-
611-
// Select UTMI+ with 8-bit interface
612-
gusbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
613-
614-
// Set 16-bit interface if supported
615-
if (dwc2->ghwcfg4_bm.phy_data_width) {
616-
gusbcfg |= GUSBCFG_PHYIF16;
617-
}
618-
}
619-
620-
// Apply config
621-
dwc2->gusbcfg = gusbcfg;
622-
623-
// mcu specific phy init
624-
dwc2_phy_init(dwc2, dwc2->ghwcfg2_bm.hs_phy_type);
625-
626-
// Reset core after selecting PHY
627-
reset_core(dwc2);
628-
629-
// Set turn-around, must after core reset otherwise it will be clear
630-
// - 9 if using 8-bit PHY interface
631-
// - 5 if using 16-bit PHY interface
632-
gusbcfg &= ~GUSBCFG_TRDT_Msk;
633-
gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos;
634-
dwc2->gusbcfg = gusbcfg;
635-
636-
// MCU specific PHY update post reset
637-
dwc2_phy_update(dwc2, dwc2->ghwcfg2_bm.hs_phy_type);
638-
639-
// Set max speed
640-
uint32_t dcfg = dwc2->dcfg;
641-
dcfg &= ~DCFG_DSPD_Msk;
642-
dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos;
643-
644-
// XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required
645-
// when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347)
646-
if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
647-
dcfg |= DCFG_XCVRDLY;
648-
}
649-
650-
dwc2->dcfg = dcfg;
651-
}
652-
653-
static bool check_dwc2(dwc2_regs_t* dwc2) {
654-
#if CFG_TUSB_DEBUG >= DWC2_DEBUG
655-
// print guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4
656-
// Run 'python dwc2_info.py' and check dwc2_info.md for bit-field value and comparison with other ports
657-
volatile uint32_t const* p = (volatile uint32_t const*) &dwc2->guid;
658-
TU_LOG1("guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4\r\n");
659-
for (size_t i = 0; i < 5; i++) {
660-
TU_LOG1("0x%08" PRIX32 ", ", p[i]);
661-
}
662-
TU_LOG1("0x%08" PRIX32 "\r\n", p[5]);
663-
#endif
664-
665-
// For some reason: GD32VF103 snpsid and all hwcfg register are always zero (skip it)
666-
(void) dwc2;
667-
#if !TU_CHECK_MCU(OPT_MCU_GD32VF103)
668-
uint32_t const gsnpsid = dwc2->gsnpsid & GSNPSID_ID_MASK;
669-
TU_ASSERT(gsnpsid == DWC2_OTG_ID || gsnpsid == DWC2_FS_IOT_ID || gsnpsid == DWC2_HS_IOT_ID);
670-
#endif
671-
672-
return true;
673-
}
674-
433+
//--------------------------------------------------------------------
434+
// Controller API
435+
//--------------------------------------------------------------------
675436
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
676-
(void) rhport;
677437
(void) rh_init;
678-
// Programming model begins in the last section of the chapter on the USB
679-
// peripheral in each Reference Manual.
680438
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
681439

682-
// Check Synopsys ID register, failed if controller clock/power is not enabled
683-
TU_ASSERT(check_dwc2(dwc2));
684-
dcd_disconnect(rhport);
440+
// Core Initialization
441+
const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE);
442+
TU_ASSERT(dwc2_core_init(rhport, is_highspeed));
685443

686-
if (phy_hs_supported(dwc2)) {
687-
phy_hs_init(dwc2); // Highspeed
444+
if (dma_device_enabled(dwc2)) {
445+
// DMA seems to be only settable after a core reset, and not possible to switch on-the-fly
446+
dwc2->gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2;
688447
} else {
689-
phy_fs_init(dwc2); // core does not support highspeed or hs phy is not present
448+
dwc2->gintmsk |= GINTSTS_RXFLVL;
690449
}
691450

692-
// Restart PHY clock
693-
dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE);
451+
// Device Initialization
452+
dcd_disconnect(rhport);
694453

695-
/* Set HS/FS Timeout Calibration to 7 (max available value).
696-
* The number of PHY clocks that the application programs in
697-
* this field is added to the high/full speed interpacket timeout
698-
* duration in the core to account for any additional delays
699-
* introduced by the PHY. This can be required, because the delay
700-
* introduced by the PHY in generating the linestate condition
701-
* can vary from one PHY to another.
702-
*/
703-
dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos);
454+
// Set device max speed
455+
uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk;
456+
if (is_highspeed) {
457+
dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos;
458+
459+
// XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required
460+
// when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347)
461+
if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
462+
dcfg |= DCFG_XCVRDLY;
463+
}
464+
}else {
465+
dcfg |= DCFG_DSPD_FS << DCFG_DSPD_Pos;
466+
}
467+
dwc2->dcfg = dcfg;
704468

705469
// Force device mode
706470
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD;
707471

708472
// Clear A override, force B Valid
709473
dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL;
710474

711-
// If USB host misbehaves during status portion of control xfer
712-
// (non zero-length packet), send STALL back and discard.
475+
// If USB host misbehaves during status portion of control xfer (non zero-length packet), send STALL back and discard
713476
dwc2->dcfg |= DCFG_NZLSOHSK;
714477

715-
dfifo_flush_tx(dwc2, 0x10); // all tx fifo
716-
dfifo_flush_rx(dwc2);
717-
718-
// Clear all interrupts
719-
uint32_t int_mask = dwc2->gintsts;
720-
dwc2->gintsts |= int_mask;
721-
int_mask = dwc2->gotgint;
722-
dwc2->gotgint |= int_mask;
723-
724-
// Required as part of core initialization.
725-
dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
726-
727-
// Configure TX FIFO empty level for interrupt. Default is complete empty
728-
dwc2->gahbcfg |= GAHBCFG_TXFELVL;
729-
730-
if (dma_enabled(dwc2)) {
731-
const uint16_t epinfo_base = dma_cal_epfifo_base(rhport);
732-
dwc2->gdfifocfg = (epinfo_base << GDFIFOCFG_EPINFOBASE_SHIFT) | epinfo_base;
478+
// Enable required interrupts
479+
dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
733480

734-
// DMA seems to be only settable after a core reset
735-
dwc2->gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2;
736-
}else {
737-
dwc2->gintmsk |= GINTMSK_RXFLVLM;
738-
}
739-
740-
// Enable global interrupt
741-
dwc2->gahbcfg |= GAHBCFG_GINT;
742-
743-
// make sure we are in device mode
744-
// TU_ASSERT(!(dwc2->gintsts & GINTSTS_CMOD), );
745-
746-
// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl);
747-
// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg);
748-
// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg);
749-
// TU_LOG_HEX(DWC2_DEBUG, dwc2->gahbcfg);
481+
// TX FIFO empty level for interrupt is complete empty
482+
uint32_t gahbcfg = dwc2->gahbcfg;
483+
gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL;
484+
gahbcfg |= GAHBCFG_GINT; // Enable global interrupt
485+
dwc2->gahbcfg = gahbcfg;
750486

751487
dcd_connect(rhport);
752-
753488
return true;
754489
}
755490

@@ -873,7 +608,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
873608
dfifo_flush_tx(dwc2, 0x10); // all tx fifo
874609
dfifo_flush_rx(dwc2);
875610

876-
dfifo_init(rhport); // re-init dfifo
611+
dfifo_device_init(rhport); // re-init dfifo
877612
}
878613

879614
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
@@ -904,11 +639,10 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
904639
// Schedule the first transaction for EP0 transfer
905640
edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]);
906641
} else {
907-
uint16_t num_packets = (total_bytes / xfer->max_size);
908-
uint16_t const short_packet_size = total_bytes % xfer->max_size;
909-
910-
// Zero-size packet is special case.
911-
if ((short_packet_size > 0) || (total_bytes == 0)) num_packets++;
642+
uint16_t num_packets = tu_div_ceil(total_bytes, xfer->max_size);
643+
if (num_packets == 0) {
644+
num_packets = 1; // zero length packet still count as 1
645+
}
912646

913647
// Schedule packets to be sent within interrupt
914648
edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes);
@@ -952,8 +686,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
952686
}
953687

954688
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
689+
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
955690
edpt_disable(rhport, ep_addr, true);
956-
if((tu_edpt_number(ep_addr) == 0) && dma_enabled(DWC2_REG(rhport))) {
691+
if((tu_edpt_number(ep_addr) == 0) && dma_device_enabled(dwc2)) {
957692
dma_setup_prepare(rhport);
958693
}
959694
}
@@ -976,16 +711,15 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
976711
// Process shared receive FIFO, this interrupt is only used in Slave mode
977712
static void handle_rxflvl_irq(uint8_t rhport) {
978713
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
979-
volatile uint32_t const* rx_fifo = dwc2->fifo[0];
714+
const volatile uint32_t* rx_fifo = dwc2->fifo[0];
980715

981716
// Pop control word off FIFO
982-
uint32_t const grxstsp = dwc2->grxstsp;
983-
uint8_t const pktsts = (grxstsp & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos;
984-
uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos;
985-
uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos;
717+
const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm;
718+
const uint8_t epnum = grxstsp_bm.ep_ch_num;
719+
const uint16_t byte_count = grxstsp_bm.byte_count;
986720
dwc2_epout_t* epout = &dwc2->epout[epnum];
987721

988-
switch (pktsts) {
722+
switch (grxstsp_bm.packet_status) {
989723
// Global OUT NAK: do nothing
990724
case GRXSTS_PKTSTS_GLOBALOUTNAK:
991725
break;
@@ -1010,18 +744,18 @@ static void handle_rxflvl_irq(uint8_t rhport) {
1010744
// Read packet off RxFIFO
1011745
if (xfer->ff) {
1012746
// Ring buffer
1013-
tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, bcnt);
747+
tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count);
1014748
} else {
1015749
// Linear buffer
1016-
dfifo_read_packet(rhport, xfer->buffer, bcnt);
750+
dfifo_read_packet(dwc2, xfer->buffer, byte_count);
1017751

1018752
// Increment pointer to xfer data
1019-
xfer->buffer += bcnt;
753+
xfer->buffer += byte_count;
1020754
}
1021755

1022-
// Truncate transfer length in case of short packet
1023-
if (bcnt < xfer->max_size) {
1024-
xfer->total_len -= (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos;
756+
// short packet, minus remaining bytes (xfer_size)
757+
if (byte_count < xfer->max_size) {
758+
xfer->total_len -= epout->doeptsiz_bm.xfer_size;
1025759
if (epnum == 0) {
1026760
xfer->total_len -= ep0_pending[TUSB_DIR_OUT];
1027761
ep0_pending[TUSB_DIR_OUT] = 0;
@@ -1070,7 +804,7 @@ static void handle_epout_irq(uint8_t rhport) {
1070804
if (doepint & DOEPINT_SETUP) {
1071805
epout->doepint = DOEPINT_SETUP;
1072806

1073-
if(dma_enabled(dwc2)) {
807+
if(dma_device_enabled(dwc2)) {
1074808
dma_setup_prepare(rhport);
1075809
}
1076810

@@ -1086,7 +820,7 @@ static void handle_epout_irq(uint8_t rhport) {
1086820
if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) {
1087821
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
1088822

1089-
if(dma_enabled(dwc2)) {
823+
if(dma_device_enabled(dwc2)) {
1090824
if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) {
1091825
// EP0 can only handle one packet Schedule another packet to be received.
1092826
edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]);
@@ -1118,65 +852,64 @@ static void handle_epout_irq(uint8_t rhport) {
1118852

1119853
static void handle_epin_irq(uint8_t rhport) {
1120854
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
1121-
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
1122-
dwc2_epin_t* epin = dwc2->epin;
855+
const uint8_t ep_count = _dwc2_controller[rhport].ep_count;
1123856

1124857
// DAINT for a given EP clears when DIEPINTx is cleared.
1125858
// IEPINT will be cleared when DAINT's out bits are cleared.
1126859
for (uint8_t n = 0; n < ep_count; n++) {
1127860
if (dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n)) {
1128861
// IN XFER complete (entire xfer).
1129862
xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
863+
dwc2_epin_t* epin = &dwc2->epin[n];
1130864

1131-
if (epin[n].diepint & DIEPINT_XFRC) {
1132-
epin[n].diepint = DIEPINT_XFRC;
865+
if (epin->diepint & DIEPINT_XFRC) {
866+
epin->diepint = DIEPINT_XFRC;
1133867

1134868
// EP0 can only handle one packet
1135869
if ((n == 0) && ep0_pending[TUSB_DIR_IN]) {
1136870
// Schedule another packet to be transmitted.
1137871
edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]);
1138872
} else {
1139-
if((n == 0) && dma_enabled(dwc2)) {
873+
if((n == 0) && dma_device_enabled(dwc2)) {
1140874
dma_setup_prepare(rhport);
1141875
}
1142876
dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
1143877
}
1144878
}
1145879

1146880
// XFER FIFO empty
1147-
if ((epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) {
881+
if ((epin->diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) {
1148882
// diepint's TXFE bit is read-only, software cannot clear it.
1149883
// It will only be cleared by hardware when written bytes is more than
1150884
// - 64 bytes or
1151-
// - Half of TX FIFO size (configured by DIEPTXF)
1152-
1153-
uint16_t remaining_packets = (epin[n].dieptsiz & DIEPTSIZ_PKTCNT_Msk) >> DIEPTSIZ_PKTCNT_Pos;
885+
// - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL)
886+
const uint16_t remain_packets = epin->dieptsiz_bm.packet_count;
1154887

1155888
// Process every single packet (only whole packets can be written to fifo)
1156-
for (uint16_t i = 0; i < remaining_packets; i++) {
1157-
uint16_t const remaining_bytes = (epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos;
889+
for (uint16_t i = 0; i < remain_packets; i++) {
890+
const uint16_t remain_bytes = (uint16_t) epin->dieptsiz_bm.xfer_size;
1158891

1159892
// Packet can not be larger than ep max size
1160-
uint16_t const packet_size = tu_min16(remaining_bytes, xfer->max_size);
893+
const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size);
1161894

1162895
// It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current
1163896
// EP has to be checked if the buffer can take another WHOLE packet
1164-
if (packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) break;
897+
if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) {
898+
break;
899+
}
1165900

1166901
// Push packet to Tx-FIFO
1167902
if (xfer->ff) {
1168903
volatile uint32_t* tx_fifo = dwc2->fifo[n];
1169-
tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, packet_size);
904+
tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, xact_bytes);
1170905
} else {
1171-
dfifo_write_packet(rhport, n, xfer->buffer, packet_size);
1172-
1173-
// Increment pointer to xfer data
1174-
xfer->buffer += packet_size;
906+
dfifo_write_packet(dwc2, n, xfer->buffer, xact_bytes);
907+
xfer->buffer += xact_bytes;
1175908
}
1176909
}
1177910

1178911
// Turn off TXFE if all bytes are written.
1179-
if (((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0) {
912+
if (epin->dieptsiz_bm.xfer_size == 0) {
1180913
dwc2->diepempmsk &= ~(1 << n);
1181914
}
1182915
}
@@ -1186,21 +919,11 @@ static void handle_epin_irq(uint8_t rhport) {
1186919

1187920
/* Interrupt Hierarchy
1188921
1189-
DxEPMSK.XferComplMsk DxEPINTn.XferCompl
1190-
| |
1191-
+---------- AND --------+
1192-
|
1193-
DAINT.xEPnInt DAINTMSK.xEPnMsk
1194-
| |
1195-
+---------- AND --------+
1196-
|
1197-
GINTSTS.xEPInt GINTMSK.xEPIntMsk
1198-
| |
1199-
+---------- AND --------+
1200-
|
1201-
GAHBCFG.GblIntrMsk
1202-
|
1203-
IRQn
922+
DxEPINTn
923+
|
924+
DAINT.xEPn
925+
|
926+
GINTSTS: xEPInt
1204927
1205928
Note: when OTG_MULTI_PROC_INTRPT = 1, Device Each endpoint interrupt deachint/deachmsk/diepeachmsk/doepeachmsk
1206929
are combined to generate dedicated interrupt line for each endpoint.

‎tools/patch-tinyusb.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
mv components/arduino_tinyusb/src/dcd_dwc2.c components/arduino_tinyusb/src/dcd_dwc2.c.prev
3+
cp components/arduino_tinyusb/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c components/arduino_tinyusb/src/dcd_dwc2.c
4+
patch -p1 -N -i components/arduino_tinyusb/patches/dcd_dwc2.patch

0 commit comments

Comments
 (0)
Please sign in to comment.