Open FFBoard
Open source force feedback firmware
dcd_musb.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2021 Koji KITAYAMA
5 * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc)
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 * This file is part of the TinyUSB stack.
26 */
27
28#include "tusb_option.h"
29
30#if CFG_TUD_ENABLED && defined(TUP_USBIP_MUSB)
31
32#define MUSB_DEBUG 2
33#define MUSB_REGS(rhport) ((musb_regs_t*) MUSB_BASES[rhport])
34
35#if __GNUC__ > 8 && defined(__ARM_FEATURE_UNALIGNED)
36/* GCC warns that an address may be unaligned, even though
37 * the target CPU has the capability for unaligned memory access. */
38_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"");
39#endif
40
41#include "musb_type.h"
42#include "device/dcd.h"
43
44// Following symbols must be defined by port header
45// - musb_dcd_int_enable/disable/clear/get_enable
46// - musb_dcd_int_handler_enter/exit
47#if defined(TUP_USBIP_MUSB_TI)
48 #include "musb_ti.h"
49#elif defined(TUP_USBIP_MUSB_ADI)
50 #include "musb_max32.h"
51#else
52 #error "Unsupported MCU"
53#endif
54
55/*------------------------------------------------------------------
56 * MACRO TYPEDEF CONSTANT ENUM DECLARATION
57 *------------------------------------------------------------------*/
58
59#define REQUEST_TYPE_INVALID (0xFFu)
60
61typedef union {
62 volatile uint8_t u8;
63 volatile uint16_t u16;
64 volatile uint32_t u32;
65} hw_fifo_t;
66
67typedef struct TU_ATTR_PACKED
68{
69 void *buf; /* the start address of a transfer data buffer */
70 uint16_t length; /* the number of bytes in the buffer */
71 uint16_t remaining; /* the number of bytes remaining in the buffer */
73
74typedef struct
75{
77 uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */
78 int8_t status_out;
80 pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]; /* pipe[direction][endpoint number - 1] */
81 uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */
83
85
86//--------------------------------------------------------------------
87// HW FIFO Helper
88// Note: Index register is already set by caller
89//--------------------------------------------------------------------
90
91#if MUSB_CFG_DYNAMIC_FIFO
92
93// musb is configured to use dynamic FIFO sizing.
94// FF Size is encodded: 1 << (fifo_size[3:0] + 3) = 8 << fifo_size[3:0]
95// FF Address is 8*ff_addr[12:0]
96// First 64 bytes are reserved for EP0
97static uint32_t alloced_fifo_bytes;
98
99// ffsize is log2(mps) - 3 (round up)
100TU_ATTR_ALWAYS_INLINE static inline uint8_t hwfifo_byte2size(uint16_t nbytes) {
101 uint8_t ffsize = 28 - tu_min8(28, __builtin_clz(nbytes));
102 if ((8u << ffsize) < nbytes) {
103 ++ffsize;
104 }
105 return ffsize;
106}
107
108TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigned epnum, unsigned is_rx) {
109 (void) epnum;
110 musb->fifo_size[is_rx] = 0;
111 musb->fifo_addr[is_rx] = 0;
112}
113
114TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps,
115 bool double_packet) {
116 (void) epnum;
117 uint8_t ffsize = hwfifo_byte2size(mps);
118 mps = 8 << ffsize; // round up to the next power of 2
119
120 if (double_packet) {
121 ffsize |= MUSB_FIFOSZ_DOUBLE_PACKET;
122 mps <<= 1;
123 }
124
125 TU_ASSERT(alloced_fifo_bytes + mps <= MUSB_CFG_DYNAMIC_FIFO_SIZE);
126 musb->fifo_addr[is_rx] = alloced_fifo_bytes / 8;
127 musb->fifo_size[is_rx] = ffsize;
128
129 alloced_fifo_bytes += mps;
130 return true;
131}
132
133#else
134
135TU_ATTR_ALWAYS_INLINE static inline void hwfifo_reset(musb_regs_t* musb, unsigned epnum, unsigned is_rx) {
136 (void) musb; (void) epnum; (void) is_rx;
137 // nothing to do for static FIFO
138}
139
140TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsigned epnum, unsigned is_rx, unsigned mps,
141 bool double_packet) {
142 (void) epnum; (void) mps;
143 if (!double_packet) {
144 #if defined(TUP_USBIP_MUSB_ADI)
145 musb->indexed_csr.maxp_csr[is_rx].csrh |= MUSB_CSRH_DISABLE_DOUBLE_PACKET(is_rx);
146 #else
147 if (is_rx) {
148 musb->rx_doulbe_packet_disable |= 1u << epnum;
149 } else {
150 musb->tx_double_packet_disable |= 1u << epnum;
151 }
152 #endif
153 }
154
155 return true;
156}
157
158#endif
159
160// Flush FIFO and clear data toggle
161TU_ATTR_ALWAYS_INLINE static inline void hwfifo_flush(musb_regs_t* musb, unsigned epnum, unsigned is_rx, bool clear_dtog) {
162 (void) epnum;
163 const uint8_t csrl_dtog = clear_dtog ? MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx) : 0;
164 musb_ep_maxp_csr_t* maxp_csr = &musb->indexed_csr.maxp_csr[is_rx];
165 // may need to flush twice for double packet
166 for (unsigned i=0; i<2; i++) {
167 if (maxp_csr->csrl & MUSB_CSRL_PACKET_READY(is_rx)) {
168 maxp_csr->csrl = MUSB_CSRL_FLUSH_FIFO(is_rx) | csrl_dtog;
169 }
170 }
171}
172
173static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
174{
175 volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo;
176 uintptr_t addr = (uintptr_t)buf;
177 while (len >= 4) {
178 reg->u32 = *(uint32_t const *)addr;
179 addr += 4;
180 len -= 4;
181 }
182 if (len >= 2) {
183 reg->u16 = *(uint16_t const *)addr;
184 addr += 2;
185 len -= 2;
186 }
187 if (len) {
188 reg->u8 = *(uint8_t const *)addr;
189 }
190}
191
192static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
193{
194 volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo;
195 uintptr_t addr = (uintptr_t)buf;
196 while (len >= 4) {
197 *(uint32_t *)addr = reg->u32;
198 addr += 4;
199 len -= 4;
200 }
201 if (len >= 2) {
202 *(uint16_t *)addr = reg->u16;
203 addr += 2;
204 len -= 2;
205 }
206 if (len) {
207 *(uint8_t *)addr = reg->u8;
208 }
209}
210
211static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir)
212{
213 static const struct {
214 void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
215 void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n);
216 void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len);
217 } ops[] = {
220 };
222 ops[dir].tu_fifo_get_info(f, &info);
223 unsigned total_len = len;
224 len = TU_MIN(total_len, info.len_lin);
225 ops[dir].pipe_read_write(info.ptr_lin, fifo, len);
226 unsigned rem = total_len - len;
227 if (rem) {
228 len = TU_MIN(rem, info.len_wrap);
229 ops[dir].pipe_read_write(info.ptr_wrap, fifo, len);
230 rem -= len;
231 }
232 ops[dir].tu_fifo_advance(f, total_len - rem);
233}
234
235static void process_setup_packet(uint8_t rhport) {
236 musb_regs_t* musb_regs = MUSB_REGS(rhport);
237
238 // Read setup packet
239 uint32_t *p = (void*)&_dcd.setup_packet;
240 volatile uint32_t *fifo_ptr = &musb_regs->fifo[0];
241 p[0] = *fifo_ptr;
242 p[1] = *fifo_ptr;
243
244 _dcd.pipe0.buf = NULL;
245 _dcd.pipe0.length = 0;
246 _dcd.pipe0.remaining = 0;
247 dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true);
248
249 const unsigned len = _dcd.setup_packet.wLength;
250 _dcd.remaining_ctrl = len;
251 const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType);
252 /* Clear RX FIFO and reverse the transaction direction */
253 if (len && dir_in) {
254 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0);
255 ep_csr->csr0l = MUSB_CSRL0_RXRDYC;
256 }
257}
258
259static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr)
260{
261 unsigned epnum = tu_edpt_number(ep_addr);
262 unsigned epnum_minus1 = epnum - 1;
263 pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
264 const unsigned rem = pipe->remaining;
265
266 if (!rem) {
267 pipe->buf = NULL;
268 return true;
269 }
270
271 musb_regs_t* musb_regs = MUSB_REGS(rhport);
272 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum);
273 const unsigned mps = ep_csr->tx_maxp;
274 const unsigned len = TU_MIN(mps, rem);
275 void *buf = pipe->buf;
276 volatile void *fifo_ptr = &musb_regs->fifo[epnum];
277 // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem);
278 if (len) {
279 if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) {
280 pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_IN);
281 } else {
282 pipe_write_packet(buf, fifo_ptr, len);
283 pipe->buf = buf + len;
284 }
285 pipe->remaining = rem - len;
286 }
287 ep_csr->tx_csrl = MUSB_TXCSRL1_TXRDY;
288 // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum, ep_csr->tx_csrl, rem - len);
289 return false;
290}
291
292static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr)
293{
294 unsigned epnum = tu_edpt_number(ep_addr);
295 unsigned epnum_minus1 = epnum - 1;
296 pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
297 musb_regs_t* musb_regs = MUSB_REGS(rhport);
298 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum);
299 // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, ep_csr->rx_csrl);
300
301 TU_ASSERT(ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY);
302
303 const unsigned mps = ep_csr->rx_maxp;
304 const unsigned rem = pipe->remaining;
305 const unsigned vld = ep_csr->rx_count;
306 const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
307 void *buf = pipe->buf;
308 volatile void *fifo_ptr = &musb_regs->fifo[epnum];
309 if (len) {
310 if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) {
311 pipe_read_write_packet_ff(buf, fifo_ptr, len, TUSB_DIR_OUT);
312 } else {
313 pipe_read_packet(buf, fifo_ptr, len);
314 pipe->buf = buf + len;
315 }
316 pipe->remaining = rem - len;
317 }
318 if ((len < mps) || (rem == len)) {
319 pipe->buf = NULL;
320 return NULL != buf;
321 }
322 ep_csr->rx_csrl = 0; /* Clear RXRDY bit */
323 return false;
324}
325
326static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
327{
328 unsigned epnum = tu_edpt_number(ep_addr);
329 unsigned epnum_minus1 = epnum - 1;
330 unsigned dir_in = tu_edpt_dir(ep_addr);
331
332 pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1];
333 pipe->buf = buffer;
334 pipe->length = total_bytes;
335 pipe->remaining = total_bytes;
336
337 if (dir_in) {
338 handle_xfer_in(rhport, ep_addr);
339 } else {
340 musb_regs_t* musb_regs = MUSB_REGS(rhport);
341 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epnum);
342 if (ep_csr->rx_csrl & MUSB_RXCSRL1_RXRDY) ep_csr->rx_csrl = 0;
343 }
344 return true;
345}
346
347static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
348{
349 (void)rhport;
350 TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */
351 musb_regs_t* musb_regs = MUSB_REGS(rhport);
352 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0);
353 const unsigned req = _dcd.setup_packet.bmRequestType;
354 TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0);
355
356 if (req == REQUEST_TYPE_INVALID || _dcd.status_out) {
357 /* STATUS OUT stage.
358 * MUSB controller automatically handles STATUS OUT packets without
359 * software helps. We do not have to do anything. And STATUS stage
360 * may have already finished and received the next setup packet
361 * without calling this function, so we have no choice but to
362 * invoke the callback function of status packet here. */
363 // TU_LOG1(" STATUS OUT ep_csr->csr0l = %x\r\n", ep_csr->csr0l);
364 _dcd.status_out = 0;
365 if (req == REQUEST_TYPE_INVALID) {
367 } else {
368 /* The next setup packet has already been received, it aborts
369 * invoking callback function to avoid confusing TUSB stack. */
370 TU_LOG1("Drop CONTROL_STAGE_ACK\r\n");
371 }
372 return true;
373 }
374 const unsigned dir_in = tu_edpt_dir(ep_addr);
375 if (tu_edpt_dir(req) == dir_in) { /* DATA stage */
376 TU_ASSERT(total_bytes <= _dcd.remaining_ctrl);
377 const unsigned rem = _dcd.remaining_ctrl;
378 const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes);
379 volatile void *fifo_ptr = &musb_regs->fifo[0];
380 if (dir_in) {
381 pipe_write_packet(buffer, fifo_ptr, len);
382
383 _dcd.pipe0.buf = buffer + len;
384 _dcd.pipe0.length = len;
385 _dcd.pipe0.remaining = 0;
386
387 _dcd.remaining_ctrl = rem - len;
388 if ((len < 64) || (rem == len)) {
389 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */
390 _dcd.status_out = 1;
391 /* Flush TX FIFO and reverse the transaction direction. */
392 ep_csr->csr0l = MUSB_CSRL0_TXRDY | MUSB_CSRL0_DATAEND;
393 } else {
394 ep_csr->csr0l = MUSB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */
395 }
396 // TU_LOG1(" IN ep_csr->csr0l = %x\r\n", ep_csr->csr0l);
397 } else {
398 // TU_LOG1(" OUT ep_csr->csr0l = %x\r\n", ep_csr->csr0l);
400 _dcd.pipe0.length = len;
401 _dcd.pipe0.remaining = len;
402 ep_csr->csr0l = MUSB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */
403 }
404 } else if (dir_in) {
405 // TU_LOG1(" STATUS IN ep_csr->csr0l = %x\r\n", ep_csr->csr0l);
406 _dcd.pipe0.buf = NULL;
407 _dcd.pipe0.length = 0;
408 _dcd.pipe0.remaining = 0;
409 /* Clear RX FIFO and reverse the transaction direction */
410 ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND;
411 }
412 return true;
413}
414
415static void process_ep0(uint8_t rhport)
416{
417 musb_regs_t* musb_regs = MUSB_REGS(rhport);
418 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0);
419 uint_fast8_t csrl = ep_csr->csr0l;
420
421 // TU_LOG1(" EP0 ep_csr->csr0l = %x\r\n", csrl);
422 // 21.1.5: endpoint 0 service routine as peripheral
423
424 if (csrl & MUSB_CSRL0_STALLED) {
425 /* Returned STALL packet to HOST. */
426 ep_csr->csr0l = 0; /* Clear STALL */
427 return;
428 }
429
430 unsigned req = _dcd.setup_packet.bmRequestType;
431 if (csrl & MUSB_CSRL0_SETEND) {
432 TU_LOG1(" ABORT by the next packets\r\n");
433 ep_csr->csr0l = MUSB_CSRL0_SETENDC;
434 if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) {
435 /* DATA stage was aborted by receiving STATUS or SETUP packet. */
436 _dcd.pipe0.buf = NULL;
437 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
439 req & TUSB_DIR_IN_MASK,
441 XFER_RESULT_SUCCESS, true);
442 }
443 req = REQUEST_TYPE_INVALID;
444 if (!(csrl & MUSB_CSRL0_RXRDY)) return; /* Received SETUP packet */
445 }
446
447 if (csrl & MUSB_CSRL0_RXRDY) {
448 /* Received SETUP or DATA OUT packet */
449 if (req == REQUEST_TYPE_INVALID) {
450 /* SETUP */
451 TU_ASSERT(sizeof(tusb_control_request_t) == ep_csr->count0,);
452 process_setup_packet(rhport);
453 return;
454 }
455 if (_dcd.pipe0.buf) {
456 /* DATA OUT */
457 const unsigned vld = ep_csr->count0;
458 const unsigned rem = _dcd.pipe0.remaining;
459 const unsigned len = TU_MIN(TU_MIN(rem, 64), vld);
460 volatile void *fifo_ptr = &musb_regs->fifo[0];
461 pipe_read_packet(_dcd.pipe0.buf, fifo_ptr, len);
462
463 _dcd.pipe0.remaining = rem - len;
464 _dcd.remaining_ctrl -= len;
465
466 _dcd.pipe0.buf = NULL;
470 XFER_RESULT_SUCCESS, true);
471 }
472 return;
473 }
474
475 /* When CSRL0 is zero, it means that completion of sending a any length packet
476 * or receiving a zero length packet. */
477 if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) {
478 /* STATUS IN */
479 if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) {
480 /* The address must be changed on completion of the control transfer. */
481 musb_regs->faddr = (uint8_t)_dcd.setup_packet.wValue;
482 }
483 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
487 XFER_RESULT_SUCCESS, true);
488 return;
489 }
490 if (_dcd.pipe0.buf) {
491 /* DATA IN */
492 _dcd.pipe0.buf = NULL;
496 XFER_RESULT_SUCCESS, true);
497 }
498}
499
500static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
501{
502 bool completed;
503 const unsigned dir_in = tu_edpt_dir(ep_addr);
504 const unsigned epn = tu_edpt_number(ep_addr);
505 const unsigned epn_minus1 = epn - 1;
506
507 musb_regs_t* musb_regs = MUSB_REGS(rhport);
508 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn);
509 if (dir_in) {
510 // TU_LOG1(" TX CSRL%d = %x\r\n", epn, ep_csr->tx_csrl);
511 if (ep_csr->tx_csrl & MUSB_TXCSRL1_STALLED) {
512 ep_csr->tx_csrl &= ~(MUSB_TXCSRL1_STALLED | MUSB_TXCSRL1_UNDRN);
513 return;
514 }
515 completed = handle_xfer_in(rhport, ep_addr);
516 } else {
517 // TU_LOG1(" RX CSRL%d = %x\r\n", epn, ep_csr->rx_csrl);
518 if (ep_csr->rx_csrl & MUSB_RXCSRL1_STALLED) {
519 ep_csr->rx_csrl &= ~(MUSB_RXCSRL1_STALLED | MUSB_RXCSRL1_OVER);
520 return;
521 }
522 completed = handle_xfer_out(rhport, ep_addr);
523 }
524
525 if (completed) {
526 pipe_state_t *pipe = &_dcd.pipe[dir_in][epn_minus1];
527 dcd_event_xfer_complete(rhport, ep_addr,
528 pipe->length - pipe->remaining,
529 XFER_RESULT_SUCCESS, true);
530 }
531}
532
533// Upon BUS RESET is detected, hardware havs already done:
534// faddr = 0, index = 0, flushes all ep fifos, clears all ep csr, enabled all ep interrupts
535static void process_bus_reset(uint8_t rhport) {
536 musb_regs_t* musb = MUSB_REGS(rhport);
537
538#if MUSB_CFG_DYNAMIC_FIFO
539 alloced_fifo_bytes = CFG_TUD_ENDPOINT0_SIZE;
540#endif
541
542 /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), a control transfer state is SETUP or STATUS stage. */
543 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
544 _dcd.status_out = 0;
545 /* When pipe0.buf has not NULL, DATA stage works in progress. */
546 _dcd.pipe0.buf = NULL;
547
548 musb->intr_txen = 1; /* Enable only EP0 */
549 musb->intr_rxen = 0;
550
551 /* Clear FIFO settings */
552 for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
553 musb->index = i;
554 hwfifo_reset(musb, i, 0);
555 hwfifo_reset(musb, i, 1);
556 }
557 dcd_event_bus_reset(rhport, (musb->power & MUSB_POWER_HSMODE) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true);
558}
559
560/*------------------------------------------------------------------
561 * Device API
562 *------------------------------------------------------------------*/
563
564#if CFG_TUSB_DEBUG >= MUSB_DEBUG
565void print_musb_info(musb_regs_t* musb_regs) {
566 // print version, epinfo, raminfo, config_data0, fifo_size
567 TU_LOG1("musb version = %u.%u\r\n", musb_regs->hwvers_bit.major, musb_regs->hwvers_bit.minor);
568 TU_LOG1("Number of endpoints: %u TX, %u RX\r\n", musb_regs->epinfo_bit.tx_ep_num, musb_regs->epinfo_bit.rx_ep_num);
569 TU_LOG1("RAM Info: %u DMA Channel, %u RAM address width\r\n", musb_regs->raminfo_bit.dma_channel, musb_regs->raminfo_bit.ram_bits);
570
571 musb_regs->index = 0;
572 TU_LOG1("config_data0 = 0x%x\r\n", musb_regs->indexed_csr.config_data0);
573
574#if MUSB_CFG_DYNAMIC_FIFO
575 TU_LOG1("Dynamic FIFO configuration\r\n");
576#else
577 for (uint8_t i=1; i <= musb_regs->epinfo_bit.tx_ep_num; i++) {
578 musb_regs->index = i;
579 TU_LOG1("FIFO %u Size: TX %u RX %u\r\n", i, musb_regs->indexed_csr.fifo_size_bit.tx, musb_regs->indexed_csr.fifo_size_bit.rx);
580 }
581#endif
582}
583#endif
584
585bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
586 (void) rh_init;
587 musb_regs_t* musb_regs = MUSB_REGS(rhport);
588
589#if CFG_TUSB_DEBUG >= MUSB_DEBUG
590 print_musb_info(musb_regs);
591#endif
592
593 musb_regs->intr_usben |= MUSB_IE_SUSPND;
594 musb_dcd_int_clear(rhport);
595 musb_dcd_phy_init(rhport);
596 dcd_connect(rhport);
597 return true;
598}
599
600void dcd_int_enable(uint8_t rhport) {
601 musb_dcd_int_enable(rhport);
602}
603
604void dcd_int_disable(uint8_t rhport) {
605 musb_dcd_int_disable(rhport);
606}
607
608// Receive Set Address request, mcu port must also include status IN response
609void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
610{
611 (void)dev_addr;
612 musb_regs_t* musb_regs = MUSB_REGS(rhport);
613 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, 0);
614
615 _dcd.pipe0.buf = NULL;
616 _dcd.pipe0.length = 0;
617 _dcd.pipe0.remaining = 0;
618 /* Clear RX FIFO to return ACK. */
619 ep_csr->csr0l = MUSB_CSRL0_RXRDYC | MUSB_CSRL0_DATAEND;
620}
621
622// Wake up host
623void dcd_remote_wakeup(uint8_t rhport) {
624 musb_regs_t* musb_regs = MUSB_REGS(rhport);
625 musb_regs->power |= MUSB_POWER_RESUME;
626
627 unsigned cnt = SystemCoreClock / 1000;
628 while (cnt--) __NOP();
629
630 musb_regs->power &= ~MUSB_POWER_RESUME;
631}
632
633// Connect by enabling internal pull-up resistor on D+/D-
634void dcd_connect(uint8_t rhport)
635{
636 musb_regs_t* musb_regs = MUSB_REGS(rhport);
637 musb_regs->power |= TUD_OPT_HIGH_SPEED ? MUSB_POWER_HSENAB : 0;
638 musb_regs->power |= MUSB_POWER_SOFTCONN;
639}
640
641// Disconnect by disabling internal pull-up resistor on D+/D-
642void dcd_disconnect(uint8_t rhport)
643{
644 musb_regs_t* musb_regs = MUSB_REGS(rhport);
645 musb_regs->power &= ~MUSB_POWER_SOFTCONN;
646}
647
648void dcd_sof_enable(uint8_t rhport, bool en)
649{
650 (void) rhport;
651 (void) en;
652
653 // TODO implement later
654}
655
656//--------------------------------------------------------------------+
657// Endpoint API
658//--------------------------------------------------------------------+
659// static void edpt_setup(musb_regs_t* musb, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_size){
660// const unsigned epn = tu_edpt_number(ep_addr);
661// const unsigned dir_in = tu_edpt_dir(ep_addr);
662// }
663
664// Configure endpoint's registers according to descriptor
665bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
666 const unsigned ep_addr = ep_desc->bEndpointAddress;
667 const unsigned epn = tu_edpt_number(ep_addr);
668 const unsigned dir_in = tu_edpt_dir(ep_addr);
669 const unsigned mps = tu_edpt_packet_size(ep_desc);
670
671 pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1];
672 pipe->buf = NULL;
673 pipe->length = 0;
674 pipe->remaining = 0;
675
676 musb_regs_t* musb = MUSB_REGS(rhport);
677 musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
678 const uint8_t is_rx = 1 - dir_in;
679 musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx];
680
681 maxp_csr->maxp = mps;
682 maxp_csr->csrh = 0;
683#if MUSB_CFG_SHARED_FIFO
684 if (dir_in) {
685 maxp_csr->csrh |= MUSB_CSRH_TX_MODE;
686 }
687#endif
688
689 hwfifo_flush(musb, epn, is_rx, true);
690
691 TU_ASSERT(hwfifo_config(musb, epn, is_rx, mps, false));
692 musb->intren_ep[is_rx] |= TU_BIT(epn);
693
694 return true;
695}
696
697bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
698 const unsigned epn = tu_edpt_number(ep_addr);
699 const unsigned dir_in = tu_edpt_dir(ep_addr);
700 musb_regs_t* musb = MUSB_REGS(rhport);
701 musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
702 const uint8_t is_rx = 1 - dir_in;
703 ep_csr->maxp_csr[is_rx].csrh = 0;
704 return hwfifo_config(musb, epn, is_rx, largest_packet_size, true);
705}
706
707bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc ) {
708 const unsigned ep_addr = ep_desc->bEndpointAddress;
709 const unsigned epn = tu_edpt_number(ep_addr);
710 const unsigned dir_in = tu_edpt_dir(ep_addr);
711 const unsigned mps = tu_edpt_packet_size(ep_desc);
712
713 unsigned const ie = musb_dcd_get_int_enable(rhport);
714 musb_dcd_int_disable(rhport);
715
716 pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1];
717 pipe->buf = NULL;
718 pipe->length = 0;
719 pipe->remaining = 0;
720
721 musb_regs_t* musb = MUSB_REGS(rhport);
722 musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
723 const uint8_t is_rx = 1 - dir_in;
724 musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx];
725
726 maxp_csr->maxp = mps;
727 maxp_csr->csrh |= MUSB_CSRH_ISO;
728#if MUSB_CFG_SHARED_FIFO
729 if (dir_in) {
730 maxp_csr->csrh |= MUSB_CSRH_TX_MODE;
731 }
732#endif
733
734 hwfifo_flush(musb, epn, is_rx, true);
735
736#if MUSB_CFG_DYNAMIC_FIFO
737 // fifo space is already allocated, keep the address and just change packet size
738 musb->fifo_size[is_rx] = hwfifo_byte2size(mps) | MUSB_FIFOSZ_DOUBLE_PACKET;
739#endif
740
741 musb->intren_ep[is_rx] |= TU_BIT(epn);
742
743 if (ie) musb_dcd_int_enable(rhport);
744
745 return true;
746}
747
748void dcd_edpt_close_all(uint8_t rhport)
749{
750 musb_regs_t* musb = MUSB_REGS(rhport);
751 unsigned const ie = musb_dcd_get_int_enable(rhport);
752 musb_dcd_int_disable(rhport);
753
754 musb->intr_txen = 1; /* Enable only EP0 */
755 musb->intr_rxen = 0;
756 for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
757 musb_ep_csr_t* ep_csr = get_ep_csr(musb, i);
758 for (unsigned d = 0; d < 2; d++) {
759 musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[d];
760 hwfifo_flush(musb, i, d, true);
761 hwfifo_reset(musb, i, d);
762 maxp_csr->maxp = 0;
763 maxp_csr->csrh = 0;
764 }
765 }
766
767#if MUSB_CFG_DYNAMIC_FIFO
768 alloced_fifo_bytes = CFG_TUD_ENDPOINT0_SIZE;
769#endif
770
771 if (ie) musb_dcd_int_enable(rhport);
772}
773
774// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
775bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
776{
777 (void)rhport;
778 bool ret;
779 // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
780 unsigned const epnum = tu_edpt_number(ep_addr);
781 unsigned const ie = musb_dcd_get_int_enable(rhport);
782 musb_dcd_int_disable(rhport);
783
784 if (epnum) {
785 _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1);
786 ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes);
787 } else {
788 ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes);
789 }
790
791 if (ie) musb_dcd_int_enable(rhport);
792 return ret;
793}
794
795// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack
796// - optional, however, must be listed in usbd.c
797bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
798{
799 (void)rhport;
800 bool ret;
801 // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
802 unsigned const epnum = tu_edpt_number(ep_addr);
803 TU_ASSERT(epnum);
804 unsigned const ie = musb_dcd_get_int_enable(rhport);
805 musb_dcd_int_disable(rhport);
806 _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1);
807 ret = edpt_n_xfer(rhport, ep_addr, (uint8_t*)ff, total_bytes);
808 if (ie) musb_dcd_int_enable(rhport);
809 return ret;
810}
811
812// Stall endpoint
813void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
814 unsigned const ie = musb_dcd_get_int_enable(rhport);
815 musb_dcd_int_disable(rhport);
816
817 unsigned const epn = tu_edpt_number(ep_addr);
818 musb_regs_t* musb_regs = MUSB_REGS(rhport);
819 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn);
820
821 if (0 == epn) {
822 if (!ep_addr) { /* Ignore EP80 */
823 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
824 _dcd.pipe0.buf = NULL;
825 ep_csr->csr0l = MUSB_CSRL0_STALL;
826 }
827 } else {
828 const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr);
829 ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_SEND_STALL(is_rx);
830 }
831
832 if (ie) musb_dcd_int_enable(rhport);
833}
834
835// clear stall, data toggle is also reset to DATA0
836void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
837{
838 (void)rhport;
839 unsigned const ie = musb_dcd_get_int_enable(rhport);
840 musb_dcd_int_disable(rhport);
841
842 unsigned const epn = tu_edpt_number(ep_addr);
843 musb_regs_t* musb_regs = MUSB_REGS(rhport);
844 musb_ep_csr_t* ep_csr = get_ep_csr(musb_regs, epn);
845 const uint8_t is_rx = 1 - tu_edpt_dir(ep_addr);
846
847 ep_csr->maxp_csr[is_rx].csrl = MUSB_CSRL_CLEAR_DATA_TOGGLE(is_rx);
848
849 if (ie) musb_dcd_int_enable(rhport);
850}
851
852/*-------------------------------------------------------------------
853 * ISR
854 *-------------------------------------------------------------------*/
855void dcd_int_handler(uint8_t rhport) {
856 musb_regs_t* musb_regs = MUSB_REGS(rhport);
857 const uint8_t saved_index = musb_regs->index; // save endpoint index
858
859 //Part specific ISR setup/entry
861
862 uint_fast8_t intr_usb = musb_regs->intr_usb; // a read will clear this interrupt status
863 uint_fast8_t intr_tx = musb_regs->intr_tx; // a read will clear this interrupt status
864 uint_fast8_t intr_rx = musb_regs->intr_rx; // a read will clear this interrupt status
865 // TU_LOG1("D%2x T%2x R%2x\r\n", is, txis, rxis);
866
867 intr_usb &= musb_regs->intr_usben; /* Clear disabled interrupts */
868 if (intr_usb & MUSB_IS_DISCON) {
869 }
870 if (intr_usb & MUSB_IS_SOF) {
871 dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
872 }
873 if (intr_usb & MUSB_IS_RESET) {
874 process_bus_reset(rhport);
875 }
876 if (intr_usb & MUSB_IS_RESUME) {
877 dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
878 }
879 if (intr_usb & MUSB_IS_SUSPEND) {
880 dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
881 }
882
883 intr_tx &= musb_regs->intr_txen; /* Clear disabled interrupts */
884 if (intr_tx & TU_BIT(0)) {
885 process_ep0(rhport);
886 intr_tx &= ~TU_BIT(0);
887 }
888 while (intr_tx) {
889 unsigned const num = __builtin_ctz(intr_tx);
891 intr_tx &= ~TU_BIT(num);
892 }
893
894 intr_rx &= musb_regs->intr_rxen; /* Clear disabled interrupts */
895 while (intr_rx) {
896 unsigned const num = __builtin_ctz(intr_rx);
898 intr_rx &= ~TU_BIT(num);
899 }
900
901 musb_regs->index = saved_index; // restore endpoint index
902}
903
904#endif
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
Definition: dcd.h:196
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
Definition: dcd.h:222
static TU_ATTR_ALWAYS_INLINE void dcd_event_setup_received(uint8_t rhport, uint8_t const *setup, bool in_isr)
Definition: dcd.h:213
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_reset(uint8_t rhport, tusb_speed_t speed, bool in_isr)
Definition: dcd.h:204
u32 SystemCoreClock
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
Definition: dcd_musb.c:797
struct TU_ATTR_PACKED pipe_state_t
static void process_setup_packet(uint8_t rhport)
Definition: dcd_musb.c:235
static TU_ATTR_ALWAYS_INLINE uint8_t hwfifo_byte2size(uint16_t nbytes)
Definition: dcd_musb.c:100
static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
Definition: dcd_musb.c:500
static void process_bus_reset(uint8_t rhport)
Definition: dcd_musb.c:535
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_musb.c:813
static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
Definition: dcd_musb.c:173
void dcd_int_handler(uint8_t rhport)
Definition: dcd_musb.c:855
static TU_ATTR_ALWAYS_INLINE void hwfifo_reset(musb_regs_t *musb, unsigned epnum, unsigned is_rx)
Definition: dcd_musb.c:108
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
Definition: dcd_musb.c:707
void dcd_disconnect(uint8_t rhport)
Definition: dcd_musb.c:642
static dcd_data_t _dcd
Definition: dcd_musb.c:84
static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_musb.c:347
void dcd_edpt_close_all(uint8_t rhport)
Definition: dcd_musb.c:748
_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"")
void dcd_int_disable(uint8_t rhport)
Definition: dcd_musb.c:604
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
Definition: dcd_musb.c:665
static void process_ep0(uint8_t rhport)
Definition: dcd_musb.c:415
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_musb.c:836
static bool handle_xfer_in(uint8_t rhport, uint_fast8_t ep_addr)
Definition: dcd_musb.c:259
static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_musb.c:326
static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
Definition: dcd_musb.c:192
void dcd_connect(uint8_t rhport)
Definition: dcd_musb.c:634
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_musb.c:775
static bool handle_xfer_out(uint8_t rhport, uint_fast8_t ep_addr)
Definition: dcd_musb.c:292
static TU_ATTR_ALWAYS_INLINE bool hwfifo_config(musb_regs_t *musb, unsigned epnum, unsigned is_rx, unsigned mps, bool double_packet)
Definition: dcd_musb.c:114
static uint32_t alloced_fifo_bytes
Definition: dcd_musb.c:97
void print_musb_info(musb_regs_t *musb_regs)
Definition: dcd_musb.c:565
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
Definition: dcd_musb.c:609
static TU_ATTR_ALWAYS_INLINE void hwfifo_flush(musb_regs_t *musb, unsigned epnum, unsigned is_rx, bool clear_dtog)
Definition: dcd_musb.c:161
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: dcd_musb.c:585
static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir)
Definition: dcd_musb.c:211
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size)
Definition: dcd_musb.c:697
void dcd_int_enable(uint8_t rhport)
Definition: dcd_musb.c:600
void dcd_remote_wakeup(uint8_t rhport)
Definition: dcd_musb.c:623
void dcd_sof_enable(uint8_t rhport, bool en)
Definition: dcd_musb.c:648
uint16_t total_bytes
Definition: dcd_nuc505.c:113
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
static TU_ATTR_ALWAYS_INLINE unsigned __builtin_ctz(unsigned int value)
Definition: dcd_rusb2.c:923
TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN union TU_ATTR_PACKED hw_fifo_t
uint8_t const * buffer
Definition: midi_device.h:100
static TU_ATTR_ALWAYS_INLINE void musb_dcd_int_disable(uint8_t rhport)
Definition: musb_max32.h:54
static void musb_dcd_phy_init(uint8_t rhport)
Definition: musb_max32.h:86
static void musb_dcd_int_handler_enter(uint8_t rhport)
Definition: musb_max32.h:71
static TU_ATTR_ALWAYS_INLINE void musb_dcd_int_clear(uint8_t rhport)
Definition: musb_max32.h:67
static TU_ATTR_ALWAYS_INLINE void musb_dcd_int_enable(uint8_t rhport)
Definition: musb_max32.h:50
static TU_ATTR_ALWAYS_INLINE unsigned musb_dcd_get_int_enable(uint8_t rhport)
Definition: musb_max32.h:58
static TU_ATTR_ALWAYS_INLINE musb_ep_csr_t * get_ep_csr(musb_regs_t *musb_regs, unsigned epnum)
Definition: musb_type.h:302
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
musb_ep_maxp_csr_t maxp_csr[2]
Definition: musb_type.h:112
musb_ep_csr_t indexed_csr
Definition: musb_type.h:193
__IO uint16_t intr_txen
Definition: musb_type.h:178
__IO uint8_t intr_usben
Definition: musb_type.h:186
__IO uint16_t rx_maxp
Definition: musb_type.h:107
__IO uint16_t fifo_addr[2]
Definition: musb_type.h:216
__IO uint16_t rx_doulbe_packet_disable
Definition: musb_type.h:287
__IO uint8_t fifo_size
Definition: musb_type.h:140
__IO uint16_t tx_maxp
Definition: musb_type.h:97
struct TU_ATTR_PACKED::@190::@213 fifo_size_bit
__IO uint8_t faddr
Definition: musb_type.h:152
__IO uint16_t tx_double_packet_disable
Definition: musb_type.h:288
__IO uint16_t intren_ep[2]
Definition: musb_type.h:182
__IO uint8_t index
Definition: musb_type.h:189
__IO uint16_t intr_tx
Definition: musb_type.h:169
uint16_t length
Definition: dcd_ci_fs.c:94
__IO uint8_t intr_usb
Definition: musb_type.h:185
__IO uint8_t rx_csrl
Definition: musb_type.h:108
volatile uint16_t
Definition: hcd_rusb2.c:58
__IO uint8_t config_data0
Definition: musb_type.h:128
__IO uint16_t count0
Definition: musb_type.h:116
__IO uint32_t fifo[16]
Definition: musb_type.h:196
void * buf
Definition: dcd_musb.c:69
uint16_t remaining
Definition: dcd_ci_fs.c:95
__IO uint8_t power
Definition: musb_type.h:154
__IO uint8_t tx_csrl
Definition: musb_type.h:100
struct TU_ATTR_PACKED::@235::@256 hwvers_bit
__IO uint16_t rx_count
Definition: musb_type.h:117
struct TU_ATTR_PACKED::@237::@259 epinfo_bit
uint8_t bEndpointAddress
Definition: video.h:306
__IO uint16_t intr_rxen
Definition: musb_type.h:179
struct TU_ATTR_PACKED::@239::@261 raminfo_bit
__IO uint16_t intr_rx
Definition: musb_type.h:170
__IO uint8_t csr0l
Definition: musb_type.h:99
uint16_t remaining_ctrl
Definition: dcd_musb.c:77
uint16_t pipe_buf_is_fifo[2]
Definition: dcd_musb.c:81
pipe_state_t pipe0
Definition: dcd_musb.c:79
uint8_t setup_packet[8]
Definition: dcd_ci_fs.c:110
int8_t status_out
Definition: dcd_musb.c:78
tusb_control_request_t setup_packet
Definition: dcd_musb.c:76
pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]
Definition: dcd_musb.c:80
uint16_t length
Definition: dcd_rusb2.c:62
void * buf
Definition: dcd_rusb2.c:61
uint16_t remaining
Definition: dcd_rusb2.c:63
static TU_ATTR_ALWAYS_INLINE uint8_t tu_min8(uint8_t x, uint8_t y)
Definition: tusb_common.h:154
void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
Get linear write info.
Definition: tusb_fifo.c:1057
void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n)
Advance write pointer - intended to be used in combination with DMA. It is possible to fill the FIFO ...
Definition: tusb_fifo.c:948
void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n)
Advance read pointer - intended to be used in combination with DMA. It is possible to read from the F...
Definition: tusb_fifo.c:969
void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
Get read info.
Definition: tusb_fifo.c:989
@ TUSB_DIR_IN
Definition: tusb_types.h:67
@ TUSB_DIR_OUT
Definition: tusb_types.h:66
@ TUSB_DIR_IN_MASK
Definition: tusb_types.h:69
@ TUSB_SPEED_FULL
Definition: tusb_types.h:50
@ TUSB_SPEED_HIGH
Definition: tusb_types.h:52
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
Definition: tusb_types.h:507
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
Definition: tusb_types.h:515
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
Definition: tusb_types.h:502
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)
Definition: tusb_types.h:511
volatile uint16_t u16
Definition: dcd_musb.c:63
volatile uint32_t u32
Definition: dcd_musb.c:64
volatile uint8_t u8
Definition: dcd_musb.c:62