Skip to content

Commit 59e3ef0

Browse files
authored
Update dcd_dwc2.c
1 parent da17d43 commit 59e3ef0

File tree

1 file changed

+92
-54
lines changed

1 file changed

+92
-54
lines changed

components/arduino_tinyusb/src/dcd_dwc2.c

Lines changed: 92 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131

3232
#if CFG_TUD_ENABLED && defined(TUP_USBIP_DWC2)
3333

34+
#if !CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE
35+
#error DWC2 require either CFG_TUD_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled
36+
#endif
37+
3438
// Debug level for DWC2
3539
#define DWC2_DEBUG 2
3640

@@ -46,9 +50,6 @@
4650
//--------------------------------------------------------------------+
4751
// MACRO TYPEDEF CONSTANT ENUM
4852
//--------------------------------------------------------------------+
49-
50-
static CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2];
51-
5253
typedef struct {
5354
uint8_t* buffer;
5455
tu_fifo_t* ff;
@@ -60,19 +61,46 @@ typedef struct {
6061
static xfer_ctl_t xfer_status[DWC2_EP_MAX][2];
6162
#define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir])
6263

63-
// EP0 transfers are limited to 1 packet - larger sizes has to be split
64-
static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type
65-
static uint16_t _dfifo_top; // top free location in DFIFO in words
64+
typedef struct {
65+
// EP0 transfers are limited to 1 packet - larger sizes has to be split
66+
uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type
67+
uint16_t dfifo_top; // top free location in DFIFO in words
68+
69+
// Number of IN endpoints active
70+
uint8_t allocated_epin_count;
71+
72+
// SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by
73+
bool sof_en;
74+
} dcd_data_t;
6675

67-
// Number of IN endpoints active
68-
static uint8_t _allocated_ep_in_count;
76+
static dcd_data_t _dcd_data;
6977

70-
// SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by
71-
static bool _sof_en;
78+
CFG_TUD_MEM_SECTION static struct {
79+
TUD_EPBUF_DEF(setup_packet, 8);
80+
} _dcd_usbbuf;
7281

7382
//--------------------------------------------------------------------
7483
// DMA
7584
//--------------------------------------------------------------------
85+
#if CFG_TUD_MEM_DCACHE_ENABLE
86+
void dcd_dcache_clean(const void* addr, uint32_t data_size) {
87+
if (addr && data_size) {
88+
dwc2_dcache_clean(addr, data_size);
89+
}
90+
}
91+
92+
void dcd_dcache_invalidate(const void* addr, uint32_t data_size) {
93+
if (addr && data_size) {
94+
dwc2_dcache_invalidate(addr, data_size);
95+
}
96+
}
97+
98+
void dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) {
99+
if (addr && data_size) {
100+
dwc2_dcache_clean_invalidate(addr, data_size);
101+
}
102+
}
103+
#endif
76104

77105
TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) {
78106
(void) dwc2;
@@ -91,7 +119,7 @@ static void dma_setup_prepare(uint8_t rhport) {
91119

92120
// Receive only 1 packet
93121
dwc2->epout[0].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos);
94-
dwc2->epout[0].doepdma = (uintptr_t)_setup_packet;
122+
dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_packet;
95123
dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP;
96124
}
97125

@@ -149,27 +177,27 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t larges
149177
static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
150178
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
151179
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
152-
uint8_t const ep_count = dwc2_controller->ep_count;
153-
uint8_t const epnum = tu_edpt_number(ep_addr);
154-
uint8_t const dir = tu_edpt_dir(ep_addr);
180+
const uint8_t ep_count = dwc2_controller->ep_count;
181+
const uint8_t epnum = tu_edpt_number(ep_addr);
182+
const uint8_t dir = tu_edpt_dir(ep_addr);
155183

156184
TU_ASSERT(epnum < ep_count);
157185

158186
uint16_t fifo_size = tu_div_ceil(packet_size, 4);
159187
if (dir == TUSB_DIR_OUT) {
160188
// Calculate required size of RX FIFO
161-
uint16_t const new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count);
189+
const uint16_t new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count);
162190

163191
// If size_rx needs to be extended check if there is enough free space
164192
if (dwc2->grxfsiz < new_sz) {
165-
TU_ASSERT(new_sz <= _dfifo_top);
193+
TU_ASSERT(new_sz <= _dcd_data.dfifo_top);
166194
dwc2->grxfsiz = new_sz; // Enlarge RX FIFO
167195
}
168196
} else {
169197
// Check IN endpoints concurrently active limit
170198
if(_dwc2_controller->ep_in_count) {
171-
TU_ASSERT(_allocated_ep_in_count < _dwc2_controller->ep_in_count);
172-
_allocated_ep_in_count++;
199+
TU_ASSERT(_dcd_data.allocated_epin_count < _dwc2_controller->ep_in_count);
200+
_dcd_data.allocated_epin_count++;
173201
}
174202

175203
// If The TXFELVL is configured as half empty, the fifo must be twice the max_size.
@@ -178,16 +206,16 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
178206
}
179207

180208
// Check if free space is available
181-
TU_ASSERT(_dfifo_top >= fifo_size + dwc2->grxfsiz);
182-
_dfifo_top -= fifo_size;
183-
TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, _dfifo_top);
209+
TU_ASSERT(_dcd_data.dfifo_top >= fifo_size + dwc2->grxfsiz);
210+
_dcd_data.dfifo_top -= fifo_size;
211+
// TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, dfifo_top);
184212

185213
// Both TXFD and TXSA are in unit of 32-bit words.
186214
if (epnum == 0) {
187-
dwc2->dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos) | _dfifo_top;
215+
dwc2->dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos) | _dcd_data.dfifo_top;
188216
} else {
189217
// DIEPTXF starts at FIFO #1.
190-
dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | _dfifo_top;
218+
dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | _dcd_data.dfifo_top;
191219
}
192220
}
193221

@@ -201,11 +229,11 @@ static void dfifo_device_init(uint8_t rhport) {
201229

202230
// Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction
203231
const bool is_dma = dma_device_enabled(dwc2);
204-
_dfifo_top = dwc2_controller->ep_fifo_size/4;
232+
_dcd_data.dfifo_top = dwc2_controller->ep_fifo_size/4;
205233
if (is_dma) {
206-
_dfifo_top -= 2 * dwc2_controller->ep_count;
234+
_dcd_data.dfifo_top -= 2 * dwc2_controller->ep_count;
207235
}
208-
dwc2->gdfifocfg = (_dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dfifo_top;
236+
dwc2->gdfifocfg = (_dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top;
209237

210238
// Allocate FIFO for EP0 IN
211239
dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE);
@@ -225,8 +253,8 @@ static uint8_t get_free_fifo(void) {
225253
return 0;
226254
}
227255
#endif
228-
229-
static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) {
256+
257+
static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint_desc) {
230258
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
231259
const uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
232260
const uint8_t dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
@@ -328,8 +356,8 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
328356

329357
// EP0 is limited to one packet per xfer
330358
if (epnum == 0) {
331-
total_bytes = tu_min16(ep0_pending[dir], xfer->max_size);
332-
ep0_pending[dir] -= total_bytes;
359+
total_bytes = tu_min16(_dcd_data.ep0_pending[dir], xfer->max_size);
360+
_dcd_data.ep0_pending[dir] -= total_bytes;
333361
num_packets = 1;
334362
} else {
335363
total_bytes = xfer->total_len;
@@ -370,14 +398,18 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
370398

371399
const bool is_dma = dma_device_enabled(dwc2);
372400
if(is_dma) {
401+
if (dir == TUSB_DIR_IN && total_bytes != 0) {
402+
dcd_dcache_clean(xfer->buffer, total_bytes);
403+
}
373404
dep->diepdma = (uintptr_t) xfer->buffer;
374-
}
375-
376-
dep->diepctl = depctl.value; // enable endpoint
405+
dep->diepctl = depctl.value; // enable endpoint
406+
} else {
407+
dep->diepctl = depctl.value; // enable endpoint
377408

378-
// Slave: enable tx fifo empty interrupt only if there is data. Note must after depctl enable
379-
if (!is_dma && dir == TUSB_DIR_IN && total_bytes != 0) {
380-
dwc2->diepempmsk |= (1 << epnum);
409+
// Enable tx fifo empty interrupt only if there is data. Note must after depctl enable
410+
if (dir == TUSB_DIR_IN && total_bytes != 0) {
411+
dwc2->diepempmsk |= (1 << epnum);
412+
}
381413
}
382414
}
383415

@@ -388,6 +420,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
388420
(void) rh_init;
389421
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
390422

423+
tu_memclr(&_dcd_data, sizeof(_dcd_data));
424+
391425
// Core Initialization
392426
const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE);
393427
const bool is_dma = dma_device_enabled(dwc2);
@@ -505,7 +539,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) {
505539
(void) rhport;
506540
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
507541

508-
_sof_en = en;
542+
_dcd_data.sof_en = en;
509543

510544
if (en) {
511545
dwc2->gintsts = GINTSTS_SOF;
@@ -530,7 +564,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
530564
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
531565
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
532566

533-
_allocated_ep_in_count = 1;
567+
_dcd_data.allocated_epin_count = 1;
534568

535569
// Disable non-control interrupt
536570
dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos);
@@ -578,7 +612,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
578612

579613
// EP0 can only handle one packet
580614
if (epnum == 0) {
581-
ep0_pending[dir] = total_bytes;
615+
_dcd_data.ep0_pending[dir] = total_bytes;
582616
}
583617

584618
// Schedule packets to be sent within interrupt
@@ -644,8 +678,8 @@ static void handle_bus_reset(uint8_t rhport) {
644678

645679
tu_memclr(xfer_status, sizeof(xfer_status));
646680

647-
_sof_en = false;
648-
_allocated_ep_in_count = 1;
681+
_dcd_data.sof_en = false;
682+
_dcd_data.allocated_epin_count = 1;
649683

650684
// 1. NAK for all OUT endpoints
651685
for (uint8_t n = 0; n < ep_count; n++) {
@@ -746,12 +780,14 @@ static void handle_rxflvl_irq(uint8_t rhport) {
746780
// Global OUT NAK: do nothing
747781
break;
748782

749-
case GRXSTS_PKTSTS_SETUP_RX:
783+
case GRXSTS_PKTSTS_SETUP_RX: {
750784
// Setup packet received
785+
uint32_t* setup = (uint32_t*)(uintptr_t) _dcd_usbbuf.setup_packet;
751786
// We can receive up to three setup packets in succession, but only the last one is valid.
752-
_setup_packet[0] = (*rx_fifo);
753-
_setup_packet[1] = (*rx_fifo);
787+
setup[0] = (*rx_fifo);
788+
setup[1] = (*rx_fifo);
754789
break;
790+
}
755791

756792
case GRXSTS_PKTSTS_SETUP_DONE:
757793
// Setup packet done:
@@ -777,8 +813,8 @@ static void handle_rxflvl_irq(uint8_t rhport) {
777813
if (byte_count < xfer->max_size) {
778814
xfer->total_len -= epout->tsiz_bm.xfer_size;
779815
if (epnum == 0) {
780-
xfer->total_len -= ep0_pending[TUSB_DIR_OUT];
781-
ep0_pending[TUSB_DIR_OUT] = 0;
816+
xfer->total_len -= _dcd_data.ep0_pending[TUSB_DIR_OUT];
817+
_dcd_data.ep0_pending[TUSB_DIR_OUT] = 0;
782818
}
783819
}
784820
}
@@ -797,7 +833,7 @@ static void handle_rxflvl_irq(uint8_t rhport) {
797833

798834
static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) {
799835
if (doepint_bm.setup_phase_done) {
800-
dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true);
836+
dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true);
801837
return;
802838
}
803839

@@ -809,7 +845,7 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe
809845
if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) {
810846
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
811847

812-
if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) {
848+
if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) {
813849
// EP0 can only handle one packet, Schedule another packet to be received.
814850
edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT);
815851
} else {
@@ -825,7 +861,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep
825861
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN);
826862

827863
if (diepint_bm.xfer_complete) {
828-
if ((epnum == 0) && ep0_pending[TUSB_DIR_IN]) {
864+
if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) {
829865
// EP0 can only handle one packet. Schedule another packet to be transmitted.
830866
edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN);
831867
} else {
@@ -873,7 +909,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
873909

874910
if (doepint_bm.setup_phase_done) {
875911
dma_setup_prepare(rhport);
876-
dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true);
912+
dcd_dcache_invalidate(_dcd_usbbuf.setup_packet, 8);
913+
dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true);
877914
return;
878915
}
879916

@@ -882,7 +919,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
882919
// only handle data skip if it is setup or status related
883920
// Normal OUT transfer complete
884921
if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) {
885-
if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) {
922+
if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) {
886923
// EP0 can only handle one packet Schedule another packet to be received.
887924
edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT);
888925
} else {
@@ -899,6 +936,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
899936
dma_setup_prepare(rhport);
900937
}
901938

939+
dcd_dcache_invalidate(xfer->buffer, xfer->total_len);
902940
dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true);
903941
}
904942
}
@@ -909,7 +947,7 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin
909947
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN);
910948

911949
if (diepint_bm.xfer_complete) {
912-
if ((epnum == 0) && ep0_pending[TUSB_DIR_IN]) {
950+
if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) {
913951
// EP0 can only handle one packet. Schedule another packet to be transmitted.
914952
edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN);
915953
} else {
@@ -1016,7 +1054,7 @@ void dcd_int_handler(uint8_t rhport) {
10161054

10171055
if (gintsts & GINTSTS_OTGINT) {
10181056
// OTG INT bit is read-only
1019-
uint32_t const otg_int = dwc2->gotgint;
1057+
const uint32_t otg_int = dwc2->gotgint;
10201058

10211059
if (otg_int & GOTGINT_SEDET) {
10221060
dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
@@ -1033,7 +1071,7 @@ void dcd_int_handler(uint8_t rhport) {
10331071
const uint32_t frame = (dwc2->dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos;
10341072

10351073
// Disable SOF interrupt if SOF was not explicitly enabled since SOF was used for remote wakeup detection
1036-
if (!_sof_en) {
1074+
if (!_dcd_data.sof_en) {
10371075
dwc2->gintmsk &= ~GINTMSK_SOFM;
10381076
}
10391077

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