Open FFBoard
Open source force feedback firmware
dcd_rusb2.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2020 Koji Kitayama
5 * Portions copyrighted (c) 2021 Roland Winistoerfer
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_RUSB2)
31
32#include "device/dcd.h"
33#include "rusb2_type.h"
34
35#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N)
36 #include "rusb2_rx.h"
37#elif TU_CHECK_MCU(OPT_MCU_RAXXX)
38 #include "rusb2_ra.h"
39 #if defined(RENESAS_CORTEX_M23)
40 #define D0FIFO CFIFO
41 #define D0FIFOSEL CFIFOSEL
42 #define D0FIFOSEL_b CFIFOSEL_b
43 #define D1FIFOSEL CFIFOSEL
44 #define D1FIFOSEL_b CFIFOSEL_b
45 #define D0FIFOCTR CFIFOCTR
46 #define D0FIFOCTR_b CFIFOCTR_b
47 #endif
48
49#else
50 #error "Unsupported MCU"
51#endif
52
53//--------------------------------------------------------------------+
54// MACRO TYPEDEF CONSTANT ENUM
55//--------------------------------------------------------------------+
56enum {
58};
59
60typedef struct {
61 void *buf; /* the start address of a transfer data buffer */
62 uint16_t length; /* the number of bytes in the buffer */
63 uint16_t remaining; /* the number of bytes remaining in the buffer */
64
65 uint8_t ep; /* an assigned endpoint address */
66 uint8_t ff; /* `buf` is TU_FUFO or POD */
68
69typedef struct
70{
72 uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */
73 // Track whether sof has been manually enabled
76
78
79//--------------------------------------------------------------------+
80// INTERNAL OBJECT & FUNCTION DECLARATION
81//--------------------------------------------------------------------+
82
83
84// Transfer conditions specifiable for each pipe for most MCUs
85// - Pipe 0: Control transfer with 64-byte single buffer
86// - Pipes 1 and 2: Bulk or ISO
87// - Pipes 3 to 5: Bulk
88// - Pipes 6 to 9: Interrupt
89//
90// Note: for small mcu such as
91// - RA2A1: only pipe 4-7 are available, and no support for ISO
92static unsigned find_pipe(unsigned xfer_type) {
93 #if defined(BSP_MCU_GROUP_RA2A1)
94 const uint8_t pipe_idx_arr[4][2] = {
95 { 0, 0 }, // Control
96 { 0, 0 }, // Isochronous not supported
97 { 4, 5 }, // Bulk
98 { 6, 7 }, // Interrupt
99 };
100 #else
101 const uint8_t pipe_idx_arr[4][2] = {
102 { 0, 0 }, // Control
103 { 1, 2 }, // Isochronous
104 { 1, 5 }, // Bulk
105 { 6, 9 }, // Interrupt
106 };
107 #endif
108
109 // find backward since only pipe 1, 2 support ISO
110 const uint8_t idx_first = pipe_idx_arr[xfer_type][0];
111 const uint8_t idx_last = pipe_idx_arr[xfer_type][1];
112
113 for (int i = idx_last; i >= idx_first; i--) {
114 if (0 == _dcd.pipe[i].ep) return i;
115 }
116
117 return 0;
118}
119
120static volatile uint16_t* get_pipectr(rusb2_reg_t *rusb, unsigned num) {
121 if (num) {
122 return (volatile uint16_t*)&(rusb->PIPE_CTR[num - 1]);
123 } else {
124 return (volatile uint16_t*)&(rusb->DCPCTR);
125 }
126}
127
128static volatile reg_pipetre_t* get_pipetre(rusb2_reg_t *rusb, unsigned num) {
129 volatile reg_pipetre_t* tre = NULL;
130 if ((1 <= num) && (num <= 5)) {
131 tre = (volatile reg_pipetre_t*)&(rusb->PIPE_TR[num - 1].E);
132 }
133 return tre;
134}
135
136static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) {
137 rusb2_reg_t *rusb = RUSB2_REG(rhport);
138 const unsigned epn = tu_edpt_number(ep_addr);
139
140 if (epn) {
141 const unsigned dir = tu_edpt_dir(ep_addr);
142 const unsigned num = _dcd.ep[dir][epn];
143 return get_pipectr(rusb, num);
144 } else {
145 return get_pipectr(rusb, 0);
146 }
147}
148
149static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb) {
150 return rusb->DCPMAXP_b.MXPS;
151}
152
153static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num) {
154 rusb->PIPESEL = num;
155 return rusb->PIPEMAXP;
156}
157
158static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num) {
159 while ( rusb->D0FIFOSEL_b.CURPIPE != num ) {}
160 while ( !rusb->D0FIFOCTR_b.FRDY ) {}
161}
162
163//--------------------------------------------------------------------+
164// Pipe FIFO
165//--------------------------------------------------------------------+
166
167// Write data buffer --> hw fifo
168static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len)
169{
170 (void) rusb;
171
172 volatile uint16_t *ff16;
173 volatile uint8_t *ff8;
174
175 // Highspeed FIFO is 32-bit
176 if ( rusb2_is_highspeed_reg(rusb) ) {
177 // TODO 32-bit access for better performance
178 ff16 = (volatile uint16_t*) ((uintptr_t) fifo+2);
179 ff8 = (volatile uint8_t *) ((uintptr_t) fifo+3);
180 }else {
181 ff16 = (volatile uint16_t*) fifo;
182 ff8 = ((volatile uint8_t*) fifo);
183 }
184
185 uint8_t const* buf8 = (uint8_t const*) buf;
186
187 while (len >= 2) {
188 *ff16 = tu_unaligned_read16(buf8);
189 buf8 += 2;
190 len -= 2;
191 }
192
193 if (len > 0) {
194 *ff8 = *buf8;
195 ++buf8;
196 }
197}
198
199// Read data buffer <-- hw fifo
200static void pipe_read_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len)
201{
202 (void) rusb;
203
204 // TODO 16/32-bit access for better performance
205
206 uint8_t *p = (uint8_t*)buf;
207 volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */
208 while (len--) *p++ = *reg;
209}
210
211// Write data sw fifo --> hw fifo
212static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) {
215
216 uint16_t count = tu_min16(total_len, info.len_lin);
217 pipe_write_packet(rusb, info.ptr_lin, fifo, count);
218
219 uint16_t rem = total_len - count;
220 if (rem) {
221 rem = tu_min16(rem, info.len_wrap);
222 pipe_write_packet(rusb, info.ptr_wrap, fifo, rem);
223 count += rem;
224 }
225
227}
228
229// Read data sw fifo <-- hw fifo
230static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) {
233
234 uint16_t count = tu_min16(total_len, info.len_lin);
235 pipe_read_packet(rusb, info.ptr_lin, fifo, count);
236
237 uint16_t rem = total_len - count;
238 if (rem) {
239 rem = tu_min16(rem, info.len_wrap);
240 pipe_read_packet(rusb, info.ptr_wrap, fifo, rem);
241 count += rem;
242 }
243
245}
246
247//--------------------------------------------------------------------+
248// Pipe Transfer
249//--------------------------------------------------------------------+
250
251static bool pipe0_xfer_in(rusb2_reg_t* rusb)
252{
253 pipe_state_t *pipe = &_dcd.pipe[0];
254 const unsigned rem = pipe->remaining;
255
256 if (!rem) {
257 pipe->buf = NULL;
258 return true;
259 }
260
261 const uint16_t mps = edpt0_max_packet_size(rusb);
262 const uint16_t len = tu_min16(mps, rem);
263 void *buf = pipe->buf;
264
265 if (len) {
266 if (pipe->ff) {
267 pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len);
268 } else {
269 pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len);
270 pipe->buf = (uint8_t*)buf + len;
271 }
272 }
273
274 if (len < mps) {
275 rusb->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
276 }
277
278 pipe->remaining = rem - len;
279 return false;
280}
281
282static bool pipe0_xfer_out(rusb2_reg_t* rusb)
283{
284 pipe_state_t *pipe = &_dcd.pipe[0];
285 const unsigned rem = pipe->remaining;
286
287 const uint16_t mps = edpt0_max_packet_size(rusb);
288 const uint16_t vld = rusb->CFIFOCTR_b.DTLN;
289 const uint16_t len = tu_min16(tu_min16(rem, mps), vld);
290 void *buf = pipe->buf;
291
292 if (len) {
293 if (pipe->ff) {
294 pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len);
295 } else {
296 pipe_read_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len);
297 pipe->buf = (uint8_t*)buf + len;
298 }
299 }
300
301 if (len < mps) {
302 rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
303 }
304
305 pipe->remaining = rem - len;
306 if ((len < mps) || (rem == len)) {
307 pipe->buf = NULL;
308 return true;
309 }
310
311 return false;
312}
313
314static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num)
315{
316 pipe_state_t *pipe = &_dcd.pipe[num];
317 const unsigned rem = pipe->remaining;
318
319 if (!rem) {
320 pipe->buf = NULL;
321 return true;
322 }
323
324 rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
325 const uint16_t mps = edpt_max_packet_size(rusb, num);
326 pipe_wait_for_ready(rusb, num);
327 const uint16_t len = tu_min16(rem, mps);
328 void *buf = pipe->buf;
329
330 if (len) {
331 if (pipe->ff) {
332 pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len);
333 } else {
334 pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len);
335 pipe->buf = (uint8_t*)buf + len;
336 }
337 }
338
339 if (len < mps) {
340 rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
341 }
342
343 rusb->D0FIFOSEL = 0;
344 while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
345
346 pipe->remaining = rem - len;
347
348 return false;
349}
350
351static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num)
352{
353 pipe_state_t *pipe = &_dcd.pipe[num];
354 const uint16_t rem = pipe->remaining;
355
356 rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
357 const uint16_t mps = edpt_max_packet_size(rusb, num);
358 pipe_wait_for_ready(rusb, num);
359
360 const uint16_t vld = rusb->D0FIFOCTR_b.DTLN;
361 const uint16_t len = tu_min16(tu_min16(rem, mps), vld);
362 void *buf = pipe->buf;
363
364 if (len) {
365 if (pipe->ff) {
366 pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len);
367 } else {
368 pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len);
369 pipe->buf = (uint8_t*)buf + len;
370 }
371 }
372
373 if (len < mps) {
374 rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
375 }
376
377 rusb->D0FIFOSEL = 0;
378 while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
379
380 pipe->remaining = rem - len;
381 if ((len < mps) || (rem == len)) {
382 pipe->buf = NULL;
383 return NULL != buf;
384 }
385
386 return false;
387}
388
389static void process_setup_packet(uint8_t rhport)
390{
391 rusb2_reg_t* rusb = RUSB2_REG(rhport);
392 if (0 == (rusb->INTSTS0 & RUSB2_INTSTS0_VALID_Msk)) return;
393
394 rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
395 uint16_t setup_packet[4] = {
396 tu_htole16(rusb->USBREQ),
397 tu_htole16(rusb->USBVAL),
398 tu_htole16(rusb->USBINDX),
399 tu_htole16(rusb->USBLENG)
400 };
401
402 rusb->INTSTS0 = ~((uint16_t) RUSB2_INTSTS0_VALID_Msk);
403 dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true);
404}
405
406static void process_status_completion(uint8_t rhport)
407{
408 rusb2_reg_t* rusb = RUSB2_REG(rhport);
409 uint8_t ep_addr;
410 /* Check the data stage direction */
411 if (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {
412 /* IN transfer. */
413 ep_addr = tu_edpt_addr(0, TUSB_DIR_IN);
414 } else {
415 /* OUT transfer. */
416 ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT);
417 }
418
419 dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true);
420}
421
422static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
423{
424 /* configure fifo direction and access unit settings */
425 if ( ep_addr ) {
426 /* IN, 2 bytes */
427 rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
428 (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
429 while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {}
430 } else {
431 /* OUT, a byte */
432 rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
433 while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {}
434 }
435
436 pipe_state_t *pipe = &_dcd.pipe[0];
437 pipe->ff = buffer_type;
438 pipe->length = total_bytes;
439 pipe->remaining = total_bytes;
440
441 if ( total_bytes ) {
442 pipe->buf = buffer;
443 if ( ep_addr ) {
444 /* IN */
445 TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80));
446 pipe0_xfer_in(rusb);
447 }
448 rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
449 } else {
450 /* ZLP */
451 pipe->buf = NULL;
452 rusb->DCPCTR = RUSB2_DCPCTR_CCPL_Msk | RUSB2_PIPE_CTR_PID_BUF;
453 }
454
455 return true;
456}
457
458static bool process_pipe_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
459{
460 const unsigned epn = tu_edpt_number(ep_addr);
461 const unsigned dir = tu_edpt_dir(ep_addr);
462 const unsigned num = _dcd.ep[dir][epn];
463
464 TU_ASSERT(num);
465
466 pipe_state_t *pipe = &_dcd.pipe[num];
467 pipe->ff = buffer_type;
468 pipe->buf = buffer;
469 pipe->length = total_bytes;
470 pipe->remaining = total_bytes;
471
472 if (dir) {
473 /* IN */
474 if (total_bytes) {
475 pipe_xfer_in(rusb, num);
476 } else {
477 /* ZLP */
478 rusb->D0FIFOSEL = num;
479 pipe_wait_for_ready(rusb, num);
480 rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
481 rusb->D0FIFOSEL = 0;
482 /* if CURPIPE bits changes, check written value */
483 while (rusb->D0FIFOSEL_b.CURPIPE) {}
484 }
485 } else {
486 // OUT
487 volatile reg_pipetre_t *pt = get_pipetre(rusb, num);
488
489 if (pt) {
490 const uint16_t mps = edpt_max_packet_size(rusb, num);
491 volatile uint16_t *ctr = get_pipectr(rusb, num);
492
493 if (*ctr & 0x3) *ctr = RUSB2_PIPE_CTR_PID_NAK;
494
495 pt->TRE = TU_BIT(8);
496 pt->TRN = (total_bytes + mps - 1) / mps;
497 pt->TRENB = 1;
498 *ctr = RUSB2_PIPE_CTR_PID_BUF;
499 }
500 }
501
502 // TU_LOG2("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type);
503 return true;
504}
505
506static bool process_edpt_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
507{
508 const unsigned epn = tu_edpt_number(ep_addr);
509 if (0 == epn) {
510 return process_pipe0_xfer(rusb, buffer_type, ep_addr, buffer, total_bytes);
511 } else {
512 return process_pipe_xfer(rusb, buffer_type, ep_addr, buffer, total_bytes);
513 }
514}
515
516static void process_pipe0_bemp(uint8_t rhport)
517{
518 rusb2_reg_t* rusb = RUSB2_REG(rhport);
519 bool completed = pipe0_xfer_in(rusb);
520 if (completed) {
521 pipe_state_t *pipe = &_dcd.pipe[0];
523 pipe->length, XFER_RESULT_SUCCESS, true);
524 }
525}
526
527static void process_pipe_brdy(uint8_t rhport, unsigned num)
528{
529 rusb2_reg_t* rusb = RUSB2_REG(rhport);
530 pipe_state_t *pipe = &_dcd.pipe[num];
531 const unsigned dir = tu_edpt_dir(pipe->ep);
532 bool completed;
533
534 if (dir) {
535 /* IN */
536 completed = pipe_xfer_in(rusb, num);
537 } else {
538 // OUT
539 if (num) {
540 completed = pipe_xfer_out(rusb, num);
541 } else {
542 completed = pipe0_xfer_out(rusb);
543 }
544 }
545 if (completed) {
546 dcd_event_xfer_complete(rhport, pipe->ep,
547 pipe->length - pipe->remaining,
548 XFER_RESULT_SUCCESS, true);
549 // TU_LOG1("C %d %d\r\n", num, pipe->length - pipe->remaining);
550 }
551}
552
553static void process_bus_reset(uint8_t rhport)
554{
555 rusb2_reg_t* rusb = RUSB2_REG(rhport);
556
557 rusb->BEMPENB = 1;
558 rusb->BRDYENB = 1;
559 rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
560
561 rusb->D0FIFOSEL = 0;
562 while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
563
564 rusb->D1FIFOSEL = 0;
565 while (rusb->D1FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
566
567 volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t) (&rusb->PIPE_CTR[0]));
568 volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t) (&rusb->PIPE_TR[0].E));
569
570 for (int i = 1; i <= 5; ++i) {
571 rusb->PIPESEL = i;
572 rusb->PIPECFG = 0;
573 *ctr = RUSB2_PIPE_CTR_ACLRM_Msk;
574 *ctr = 0;
575 ++ctr;
576 *tre = TU_BIT(8);
577 tre += 2;
578 }
579
580 for (int i = 6; i <= 9; ++i) {
581 rusb->PIPESEL = i;
582 rusb->PIPECFG = 0;
583 *ctr = RUSB2_PIPE_CTR_ACLRM_Msk;
584 *ctr = 0;
585 ++ctr;
586 }
587 tu_varclr(&_dcd);
588
589 TU_LOG3("Bus reset, RHST = %u\r\n", rusb->DVSTCTR0_b.RHST);
590 tusb_speed_t speed;
591 switch(rusb->DVSTCTR0 & RUSB2_DVSTCTR0_RHST_Msk) {
592 case RUSB2_DVSTCTR0_RHST_LS:
593 speed = TUSB_SPEED_LOW;
594 break;
595
596 case RUSB2_DVSTCTR0_RHST_FS:
597 speed = TUSB_SPEED_FULL;
598 break;
599
600 case RUSB2_DVSTCTR0_RHST_HS:
601 speed = TUSB_SPEED_HIGH;
602 break;
603
604 default:
605 TU_ASSERT(false, );
606 }
607
608 dcd_event_bus_reset(rhport, speed, true);
609}
610
611static void process_set_address(uint8_t rhport)
612{
613 rusb2_reg_t* rusb = RUSB2_REG(rhport);
614 const uint16_t addr = rusb->USBADDR_b.USBADDR;
615 if (!addr) return;
616
617 const tusb_control_request_t setup_packet = {
618#if defined(__CCRX__)
619 .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */
620#else
621 .bmRequestType = 0,
622#endif
623 .bRequest = TUSB_REQ_SET_ADDRESS,
624 .wValue = addr,
625 .wIndex = 0,
626 .wLength = 0,
627 };
628
629 dcd_event_setup_received(rhport, (const uint8_t *) &setup_packet, true);
630}
631
632/*------------------------------------------------------------------*/
633/* Device API
634 *------------------------------------------------------------------*/
635
636#if 0 // previously present in the rx driver before generalization
637static uint32_t disable_interrupt(void)
638{
639 uint32_t pswi;
640#if defined(__CCRX__)
641 pswi = get_psw() & 0x010000;
642 clrpsw_i();
643#else
644 pswi = __builtin_rx_mvfc(0) & 0x010000;
645 __builtin_rx_clrpsw('I');
646#endif
647 return pswi;
648}
649
650static void enable_interrupt(uint32_t pswi)
651{
652#if defined(__CCRX__)
653 set_psw(get_psw() | pswi);
654#else
655 __builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi);
656#endif
657}
658#endif
659
660bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
661 (void) rh_init;
662 rusb2_reg_t* rusb = RUSB2_REG(rhport);
663 rusb2_module_start(rhport, true);
664
665 // We disable SOF for now until needed later on.
666 // Since TinyUSB doesn't use SOF for now, and this interrupt often (1ms interval)
667 _dcd.sof_enabled = false;
668
669#ifdef RUSB2_SUPPORT_HIGHSPEED
670 if ( rusb2_is_highspeed_rhport(rhport) ) {
671 rusb->SYSCFG_b.HSE = 1;
672
673 // leave CLKSEL as default (0x11) 24Mhz
674
675 // Power and reset UTMI Phy
676 uint16_t physet = (rusb->PHYSET | RUSB2_PHYSET_PLLRESET_Msk) & ~RUSB2_PHYSET_DIRPD_Msk;
677 rusb->PHYSET = physet;
678 R_BSP_SoftwareDelay((uint32_t) 1, BSP_DELAY_UNITS_MILLISECONDS);
679 rusb->PHYSET_b.PLLRESET = 0;
680
681 // set UTMI to operating mode and wait for PLL lock confirmation
682 rusb->LPSTS_b.SUSPENDM = 1;
683 while (!rusb->PLLSTA_b.PLLLOCK) {}
684
685 rusb->SYSCFG_b.DRPD = 0;
686 rusb->SYSCFG_b.USBE = 1;
687
688 // Set CPU bus wait time (fine tunne later)
689 // rusb2->BUSWAIT |= 0x0F00U;
690
691 rusb->PHYSET_b.REPSEL = 1;
692 } else
693#endif
694 {
695 rusb->SYSCFG_b.SCKE = 1;
696 while (!rusb->SYSCFG_b.SCKE) {}
697 rusb->SYSCFG_b.DRPD = 0;
698 rusb->SYSCFG_b.DCFM = 0;
699 rusb->SYSCFG_b.USBE = 1;
700
701 // MCU specific PHY init
703
704 rusb->PHYSLEW = 0x5;
705 rusb->DPUSR0R_FS_b.FIXPHY0 = 0u; /* USB_BASE Transceiver Output fixed */
706 }
707
708 /* Setup default control pipe */
709 rusb->DCPMAXP_b.MXPS = 64;
710
711 rusb->INTSTS0 = 0;
712 rusb->INTENB0 = RUSB2_INTSTS0_VBINT_Msk | RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_BEMP_Msk |
713 RUSB2_INTSTS0_DVST_Msk | RUSB2_INTSTS0_CTRT_Msk | (_dcd.sof_enabled ? RUSB2_INTSTS0_SOFR_Msk : 0) |
714 RUSB2_INTSTS0_RESM_Msk;
715 rusb->BEMPENB = 1;
716 rusb->BRDYENB = 1;
717
718 // If VBUS (detect) pin is not used, application need to call tud_connect() manually after tud_init()
719 if (rusb->INTSTS0_b.VBSTS) {
720 dcd_connect(rhport);
721 }
722
723 return true;
724}
725
726void dcd_int_enable(uint8_t rhport) {
727 rusb2_int_enable(rhport);
728}
729
730void dcd_int_disable(uint8_t rhport) {
731 rusb2_int_disable(rhport);
732}
733
734void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
735 (void) rhport;
736 (void) dev_addr;
737}
738
739void dcd_remote_wakeup(uint8_t rhport)
740{
741 rusb2_reg_t* rusb = RUSB2_REG(rhport);
742 rusb->DVSTCTR0_b.WKUP = 1;
743}
744
745void dcd_connect(uint8_t rhport)
746{
747 rusb2_reg_t* rusb = RUSB2_REG(rhport);
748
749 if ( rusb2_is_highspeed_rhport(rhport)) {
750 rusb->SYSCFG_b.CNEN = 1;
751 }
752 rusb->SYSCFG_b.DPRPU = 1;
753}
754
755void dcd_disconnect(uint8_t rhport)
756{
757 rusb2_reg_t* rusb = RUSB2_REG(rhport);
758 rusb->SYSCFG_b.DPRPU = 0;
759}
760
761void dcd_sof_enable(uint8_t rhport, bool en)
762{
763 rusb2_reg_t* rusb = RUSB2_REG(rhport);
764 _dcd.sof_enabled = en;
765 rusb->INTENB0_b.SOFE = en ? 1: 0;
766}
767
768//--------------------------------------------------------------------+
769// Endpoint API
770//--------------------------------------------------------------------+
771bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
772{
773 (void)rhport;
774
775 rusb2_reg_t * rusb = RUSB2_REG(rhport);
776 const unsigned ep_addr = ep_desc->bEndpointAddress;
777 const unsigned epn = tu_edpt_number(ep_addr);
778 const unsigned dir = tu_edpt_dir(ep_addr);
779 const unsigned xfer = ep_desc->bmAttributes.xfer;
780
781 const unsigned mps = tu_edpt_packet_size(ep_desc);
782
784 // Fullspeed ISO is limit to 256 bytes
785 if ( !rusb2_is_highspeed_rhport(rhport) && mps > 256) {
786 return false;
787 }
788 }
789
790 const unsigned num = find_pipe(xfer);
791 TU_ASSERT(num);
792
793 _dcd.pipe[num].ep = ep_addr;
794 _dcd.ep[dir][epn] = num;
795
796 /* setup pipe */
797 dcd_int_disable(rhport);
798
799 if ( rusb2_is_highspeed_rhport(rhport) ) {
800 // FIXME shouldn't be after pipe selection and config, also the BUFNMB should be changed
801 // depending on the allocation scheme
802 rusb->PIPEBUF = 0x7C08;
803 }
804
805 rusb->PIPESEL = num;
806 rusb->PIPEMAXP = mps;
807 volatile uint16_t *ctr = get_pipectr(rusb, num);
808 *ctr = RUSB2_PIPE_CTR_ACLRM_Msk | RUSB2_PIPE_CTR_SQCLR_Msk;
809 *ctr = 0;
810 unsigned cfg = (dir << 4) | epn;
811
812 if (xfer == TUSB_XFER_BULK) {
813 cfg |= (RUSB2_PIPECFG_TYPE_BULK | RUSB2_PIPECFG_SHTNAK_Msk | RUSB2_PIPECFG_DBLB_Msk);
814 } else if (xfer == TUSB_XFER_INTERRUPT) {
815 cfg |= RUSB2_PIPECFG_TYPE_INT;
816 } else {
817 cfg |= (RUSB2_PIPECFG_TYPE_ISO | RUSB2_PIPECFG_DBLB_Msk);
818 }
819
820 rusb->PIPECFG = cfg;
821 rusb->BRDYSTS = 0x3FFu ^ TU_BIT(num);
822 rusb->BRDYENB |= TU_BIT(num);
823
824 if (dir || (xfer != TUSB_XFER_BULK)) {
825 *ctr = RUSB2_PIPE_CTR_PID_BUF;
826 }
827
828 // TU_LOG1("O %d %x %x\r\n", rusb->PIPESEL, rusb->PIPECFG, rusb->PIPEMAXP);
829 dcd_int_enable(rhport);
830
831 return true;
832}
833
834void dcd_edpt_close_all(uint8_t rhport)
835{
836 unsigned i = TU_ARRAY_SIZE(_dcd.pipe);
837 dcd_int_disable(rhport);
838 while (--i) { /* Close all pipes except 0 */
839 const unsigned ep_addr = _dcd.pipe[i].ep;
840 if (!ep_addr) continue;
841 dcd_edpt_close(rhport, ep_addr);
842 }
843 dcd_int_enable(rhport);
844}
845
846void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
847{
848 rusb2_reg_t * rusb = RUSB2_REG(rhport);
849 const unsigned epn = tu_edpt_number(ep_addr);
850 const unsigned dir = tu_edpt_dir(ep_addr);
851 const unsigned num = _dcd.ep[dir][epn];
852
853 rusb->BRDYENB &= ~TU_BIT(num);
854 volatile uint16_t *ctr = get_pipectr(rusb, num);
855 *ctr = 0;
856 rusb->PIPESEL = num;
857 rusb->PIPECFG = 0;
858 _dcd.pipe[num].ep = 0;
859 _dcd.ep[dir][epn] = 0;
860}
861
862bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
863{
864 rusb2_reg_t* rusb = RUSB2_REG(rhport);
865
866 dcd_int_disable(rhport);
867 bool r = process_edpt_xfer(rusb, 0, ep_addr, buffer, total_bytes);
868 dcd_int_enable(rhport);
869
870 return r;
871}
872
873bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
874{
875 // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
876 TU_ASSERT(ff->item_size == 1);
877 rusb2_reg_t* rusb = RUSB2_REG(rhport);
878
879 dcd_int_disable(rhport);
880 bool r = process_edpt_xfer(rusb, 1, ep_addr, ff, total_bytes);
881 dcd_int_enable(rhport);
882
883 return r;
884}
885
886void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
887{
888 volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr);
889 if (!ctr) return;
890 dcd_int_disable(rhport);
891 const uint32_t pid = *ctr & 0x3;
892 *ctr = pid | RUSB2_PIPE_CTR_PID_STALL;
893 *ctr = RUSB2_PIPE_CTR_PID_STALL;
894 dcd_int_enable(rhport);
895}
896
897void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
898{
899 rusb2_reg_t * rusb = RUSB2_REG(rhport);
900 volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr);
901 if (!ctr) return;
902
903 dcd_int_disable(rhport);
904 *ctr = RUSB2_PIPE_CTR_SQCLR_Msk;
905
906 if (tu_edpt_dir(ep_addr)) { /* IN */
907 *ctr = RUSB2_PIPE_CTR_PID_BUF;
908 } else {
909 const unsigned num = _dcd.ep[0][tu_edpt_number(ep_addr)];
910 rusb->PIPESEL = num;
911 if (rusb->PIPECFG_b.TYPE != 1) {
912 *ctr = RUSB2_PIPE_CTR_PID_BUF;
913 }
914 }
915 dcd_int_enable(rhport);
916}
917
918//--------------------------------------------------------------------+
919// ISR
920//--------------------------------------------------------------------+
921
922#if defined(__CCRX__)
923TU_ATTR_ALWAYS_INLINE static inline unsigned __builtin_ctz(unsigned int value) {
924 unsigned int count = 0;
925 while ((value & 1) == 0) {
926 value >>= 1;
927 count++;
928 }
929 return count;
930}
931#endif
932
933void dcd_int_handler(uint8_t rhport)
934{
935 rusb2_reg_t* rusb = RUSB2_REG(rhport);
936
937 uint16_t is0 = rusb->INTSTS0;
938
939 /* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */
940 rusb->INTSTS0 = ~((RUSB2_INTSTS0_CTRT_Msk | RUSB2_INTSTS0_DVST_Msk | RUSB2_INTSTS0_SOFR_Msk |
941 RUSB2_INTSTS0_RESM_Msk | RUSB2_INTSTS0_VBINT_Msk) & is0) | RUSB2_INTSTS0_VALID_Msk;
942
943 // VBUS changes
944 if ( is0 & RUSB2_INTSTS0_VBINT_Msk ) {
945 if ( rusb->INTSTS0_b.VBSTS ) {
946 dcd_connect(rhport);
947 } else {
948 dcd_disconnect(rhport);
949 }
950 }
951
952 // Resumed
953 if ( is0 & RUSB2_INTSTS0_RESM_Msk ) {
954 dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
955 if (!_dcd.sof_enabled) {
956 rusb->INTENB0_b.SOFE = 0;
957 }
958 }
959
960 // SOF received
961 if ( (is0 & RUSB2_INTSTS0_SOFR_Msk) && rusb->INTENB0_b.SOFE ) {
962 // USBD will exit suspended mode when SOF event is received
963 const uint32_t frame = rusb->FRMNUM_b.FRNM;
964 dcd_event_sof(rhport, frame, true);
965 if (!_dcd.sof_enabled) {
966 rusb->INTENB0_b.SOFE = 0;
967 }
968 }
969
970 // Device state changes
971 if ( is0 & RUSB2_INTSTS0_DVST_Msk ) {
972 switch (is0 & RUSB2_INTSTS0_DVSQ_Msk) {
973 case RUSB2_INTSTS0_DVSQ_STATE_DEF:
974 process_bus_reset(rhport);
975 break;
976
977 case RUSB2_INTSTS0_DVSQ_STATE_ADDR:
978 process_set_address(rhport);
979 break;
980
981 case RUSB2_INTSTS0_DVSQ_STATE_SUSP0:
982 case RUSB2_INTSTS0_DVSQ_STATE_SUSP1:
983 case RUSB2_INTSTS0_DVSQ_STATE_SUSP2:
984 case RUSB2_INTSTS0_DVSQ_STATE_SUSP3:
985 dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
986 if (!_dcd.sof_enabled) {
987 rusb->INTENB0_b.SOFE = 1;
988 }
989
990 default: break;
991 }
992 }
993
994// if ( is0 & RUSB2_INTSTS0_NRDY_Msk ) {
995// rusb->NRDYSTS = 0;
996// }
997
998 // Control transfer stage changes
999 if ( is0 & RUSB2_INTSTS0_CTRT_Msk ) {
1000 if ( is0 & RUSB2_INTSTS0_CTSQ_CTRL_RDATA ) {
1001 /* A setup packet has been received. */
1002 process_setup_packet(rhport);
1003 } else if ( 0 == (is0 & RUSB2_INTSTS0_CTSQ_Msk) ) {
1004 /* A ZLP has been sent/received. */
1006 }
1007 }
1008
1009 // Buffer empty
1010 if ( is0 & RUSB2_INTSTS0_BEMP_Msk ) {
1011 const uint16_t s = rusb->BEMPSTS;
1012 rusb->BEMPSTS = 0;
1013 if ( s & 1 ) {
1014 process_pipe0_bemp(rhport);
1015 }
1016 }
1017
1018 // Buffer ready
1019 if ( is0 & RUSB2_INTSTS0_BRDY_Msk ) {
1020 const unsigned m = rusb->BRDYENB;
1021 unsigned s = rusb->BRDYSTS & m;
1022 /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
1023 rusb->BRDYSTS = ~s;
1024 while (s) {
1025 const unsigned num = __builtin_ctz(s);
1026 process_pipe_brdy(rhport, num);
1027 s &= ~TU_BIT(num);
1028 }
1029 }
1030}
1031
1032#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_sof(uint8_t rhport, uint32_t frame_count, bool in_isr)
Definition: dcd.h:232
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
struct TU_ATTR_PACKED pipe_state_t
xfer_td_t xfer[EP_CBI_COUNT+1][2]
Definition: dcd_nrf5x.c:119
uint16_t total_bytes
Definition: dcd_nuc505.c:113
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
static bool process_pipe0_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer, uint16_t total_bytes)
Definition: dcd_rusb2.c:422
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
Definition: dcd_rusb2.c:873
static bool pipe_xfer_in(rusb2_reg_t *rusb, unsigned num)
Definition: dcd_rusb2.c:314
static void process_setup_packet(uint8_t rhport)
Definition: dcd_rusb2.c:389
static bool process_pipe_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer, uint16_t total_bytes)
Definition: dcd_rusb2.c:458
static bool process_edpt_xfer(rusb2_reg_t *rusb, int buffer_type, uint8_t ep_addr, void *buffer, uint16_t total_bytes)
Definition: dcd_rusb2.c:506
static void process_set_address(uint8_t rhport)
Definition: dcd_rusb2.c:611
static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num)
Definition: dcd_rusb2.c:153
static bool pipe_xfer_out(rusb2_reg_t *rusb, unsigned num)
Definition: dcd_rusb2.c:351
static uint16_t edpt0_max_packet_size(rusb2_reg_t *rusb)
Definition: dcd_rusb2.c:149
static TU_ATTR_ALWAYS_INLINE unsigned __builtin_ctz(unsigned int value)
Definition: dcd_rusb2.c:923
static uint32_t disable_interrupt(void)
Definition: dcd_rusb2.c:637
static void process_bus_reset(uint8_t rhport)
Definition: dcd_rusb2.c:553
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_rusb2.c:886
static unsigned find_pipe(unsigned xfer_type)
Definition: dcd_rusb2.c:92
static volatile reg_pipetre_t * get_pipetre(rusb2_reg_t *rusb, unsigned num)
Definition: dcd_rusb2.c:128
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_rusb2.c:846
static void process_pipe0_bemp(uint8_t rhport)
Definition: dcd_rusb2.c:516
void dcd_int_handler(uint8_t rhport)
Definition: dcd_rusb2.c:933
static void pipe_read_packet(rusb2_reg_t *rusb, void *buf, volatile void *fifo, unsigned len)
Definition: dcd_rusb2.c:200
void dcd_disconnect(uint8_t rhport)
Definition: dcd_rusb2.c:755
static dcd_data_t _dcd
Definition: dcd_rusb2.c:77
static void pipe_write_packet(rusb2_reg_t *rusb, void *buf, volatile void *fifo, unsigned len)
Definition: dcd_rusb2.c:168
static void process_status_completion(uint8_t rhport)
Definition: dcd_rusb2.c:406
static void enable_interrupt(uint32_t pswi)
Definition: dcd_rusb2.c:650
void dcd_edpt_close_all(uint8_t rhport)
Definition: dcd_rusb2.c:834
static volatile uint16_t * ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr)
Definition: dcd_rusb2.c:136
void dcd_int_disable(uint8_t rhport)
Definition: dcd_rusb2.c:730
static void pipe_read_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len)
Definition: dcd_rusb2.c:230
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
Definition: dcd_rusb2.c:771
static bool pipe0_xfer_out(rusb2_reg_t *rusb)
Definition: dcd_rusb2.c:282
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
Definition: dcd_rusb2.c:897
void dcd_connect(uint8_t rhport)
Definition: dcd_rusb2.c:745
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: dcd_rusb2.c:862
static void process_pipe_brdy(uint8_t rhport, unsigned num)
Definition: dcd_rusb2.c:527
static void pipe_write_packet_ff(rusb2_reg_t *rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len)
Definition: dcd_rusb2.c:212
static volatile uint16_t * get_pipectr(rusb2_reg_t *rusb, unsigned num)
Definition: dcd_rusb2.c:120
static bool pipe0_xfer_in(rusb2_reg_t *rusb)
Definition: dcd_rusb2.c:251
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
Definition: dcd_rusb2.c:734
@ PIPE_COUNT
Definition: dcd_rusb2.c:57
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: dcd_rusb2.c:660
static void pipe_wait_for_ready(rusb2_reg_t *rusb, unsigned num)
Definition: dcd_rusb2.c:158
void dcd_int_enable(uint8_t rhport)
Definition: dcd_rusb2.c:726
void dcd_remote_wakeup(uint8_t rhport)
Definition: dcd_rusb2.c:739
void dcd_sof_enable(uint8_t rhport, bool en)
Definition: dcd_rusb2.c:761
uint8_t const * buffer
Definition: midi_device.h:100
static TU_ATTR_ALWAYS_INLINE void rusb2_phy_init(void)
Definition: rusb2_ra.h:102
static TU_ATTR_ALWAYS_INLINE void rusb2_int_disable(uint8_t rhport)
Definition: rusb2_ra.h:97
static TU_ATTR_ALWAYS_INLINE void rusb2_module_start(uint8_t rhport, bool start)
Definition: rusb2_ra.h:84
static TU_ATTR_ALWAYS_INLINE void rusb2_int_enable(uint8_t rhport)
Definition: rusb2_ra.h:93
static TU_ATTR_ALWAYS_INLINE rusb2_reg_t * RUSB2_REG(uint8_t rhport)
Definition: rusb2_rx.h:40
TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED _ccrx_evenaccess reg_pipetre_t
volatile uint16_t PIPEBUF
Definition: rusb2_type.h:672
volatile uint16_t BEMPSTS
Definition: rusb2_type.h:518
struct _ccrx_evenaccess::@512::TU_ATTR_PACKED FRMNUM_b
volatile uint16_t USBINDX
Definition: rusb2_type.h:586
struct _ccrx_evenaccess::@500::TU_ATTR_PACKED PHYSET_b
volatile uint16_t DCPCTR
Definition: rusb2_type.h:625
volatile uint16_t D0FIFOSEL
Definition: rusb2_type.h:261
volatile uint16_t DVSTCTR0
Definition: rusb2_type.h:141
volatile uint16_t PIPESEL
Definition: rusb2_type.h:646
volatile uint32_t CFIFO
Definition: rusb2_type.h:171
volatile uint16_t PIPEMAXP
Definition: rusb2_type.h:683
struct _ccrx_evenaccess::@478::TU_ATTR_PACKED CFIFOCTR_b
volatile uint16_t CFIFOSEL
Definition: rusb2_type.h:231
struct _ccrx_evenaccess::@530::TU_ATTR_PACKED DCPCTR_b
volatile uint32_t D0FIFO
Definition: rusb2_type.h:191
volatile uint16_t PHYSET
Definition: rusb2_type.h:423
struct _ccrx_evenaccess::@556::TU_ATTR_PACKED LPSTS_b
struct _ccrx_evenaccess::@482::TU_ATTR_PACKED D0FIFOCTR_b
struct _ccrx_evenaccess::@516::TU_ATTR_PACKED USBADDR_b
volatile uint16_t D1FIFOSEL
Definition: rusb2_type.h:289
volatile RUSB2_PIPE_TR_t PIPE_TR[5]
Definition: rusb2_type.h:724
struct _ccrx_evenaccess::@502::TU_ATTR_PACKED INTSTS0_b
volatile uint16_t USBLENG
Definition: rusb2_type.h:594
volatile uint16_t INTSTS0
Definition: rusb2_type.h:441
volatile uint16_t PIPE_CTR[9]
Definition: rusb2_type.h:704
volatile uint16_t USBREQ
Definition: rusb2_type.h:569
volatile uint16_t PIPECFG
Definition: rusb2_type.h:656
volatile uint16_t INTENB0
Definition: rusb2_type.h:317
struct _ccrx_evenaccess::@488::TU_ATTR_PACKED INTENB0_b
volatile uint16_t USBVAL
Definition: rusb2_type.h:578
struct _ccrx_evenaccess::@464::TU_ATTR_PACKED PLLSTA_b
struct _ccrx_evenaccess::@480::TU_ATTR_PACKED D0FIFOSEL_b
struct _ccrx_evenaccess::@528::TU_ATTR_PACKED DCPMAXP_b
struct _ccrx_evenaccess::@466::TU_ATTR_PACKED DVSTCTR0_b
struct _ccrx_evenaccess::@458::TU_ATTR_PACKED SYSCFG_b
volatile uint16_t BEMPENB
Definition: rusb2_type.h:391
volatile uint16_t D0FIFOCTR
Definition: rusb2_type.h:277
volatile uint32_t PHYSLEW
Definition: rusb2_type.h:784
struct _ccrx_evenaccess::@580::TU_ATTR_PACKED DPUSR0R_FS_b
volatile uint16_t CFIFOCTR
Definition: rusb2_type.h:248
struct _ccrx_evenaccess::@534::TU_ATTR_PACKED PIPECFG_b
volatile uint16_t BRDYSTS
Definition: rusb2_type.h:482
struct _ccrx_evenaccess::@484::TU_ATTR_PACKED D1FIFOSEL_b
volatile uint16_t BRDYENB
Definition: rusb2_type.h:355
volatile uint16_t E
Definition: rusb2_type.h:68
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint8_t bEndpointAddress
Definition: video.h:306
uint8_t bmRequestType
Definition: audio.h:828
bool sof_enabled
Definition: dcd_rusb2.c:74
ep_cmd_sts_t ep[2 *MAX_EP_PAIRS][2]
pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]
Definition: dcd_musb.c:80
uint8_t ff
Definition: dcd_rusb2.c:66
uint16_t length
Definition: dcd_rusb2.c:62
void * buf
Definition: dcd_rusb2.c:61
uint8_t ep
Definition: dcd_rusb2.c:65
uint16_t remaining
Definition: dcd_rusb2.c:63
static TU_ATTR_ALWAYS_INLINE uint16_t tu_min16(uint16_t x, uint16_t y)
Definition: tusb_common.h:155
static TU_ATTR_ALWAYS_INLINE uint16_t tu_unaligned_read16(const void *mem)
Definition: tusb_common.h:219
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_REQ_SET_ADDRESS
Definition: tusb_types.h:127
tusb_speed_t
defined base on EHCI specs value for Endpoint Speed
Definition: tusb_types.h:49
@ TUSB_SPEED_FULL
Definition: tusb_types.h:50
@ TUSB_SPEED_LOW
Definition: tusb_types.h:51
@ 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
@ TUSB_XFER_ISOCHRONOUS
Definition: tusb_types.h:60
@ TUSB_XFER_INTERRUPT
Definition: tusb_types.h:62
@ TUSB_XFER_BULK
Definition: tusb_types.h:61
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