Open FFBoard
Open source force feedback firmware
hcd_rusb2.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2021 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_TUH_ENABLED && defined(TUP_USBIP_RUSB2)
31
32#include "host/hcd.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#else
40 #error "Unsupported MCU"
41#endif
42
43#define TU_RUSB2_HCD_DBG 2
44
45//--------------------------------------------------------------------+
46// MACRO TYPEDEF CONSTANT ENUM DECLARATION
47//--------------------------------------------------------------------+
48enum {
50};
51
52TU_ATTR_PACKED_BEGIN
53TU_ATTR_BIT_FIELD_ORDER_BEGIN
54
55typedef union TU_ATTR_PACKED {
56 struct {
57 volatile uint16_t u8: 8;
58 volatile uint16_t : 0;
59 };
60 volatile uint16_t u16;
62
63typedef struct TU_ATTR_PACKED {
64 void *buf; /* the start address of a transfer data buffer */
65 uint16_t length; /* the number of bytes in the buffer */
66 uint16_t remaining; /* the number of bytes remaining in the buffer */
67 struct {
68 uint32_t ep : 8; /* an assigned endpoint address */
69 uint32_t dev : 8; /* an assigned device address */
70 uint32_t ff : 1; /* `buf` is TU_FUFO or POD */
71 uint32_t : 0;
72 };
74
75TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain)
76TU_ATTR_BIT_FIELD_ORDER_END
77
78typedef struct
79{
80 bool need_reset; /* The device has not been reset after connection. */
82 uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */
83 uint8_t ctl_mps[5]; /* EP0 max packet size for each device */
85
86//--------------------------------------------------------------------+
87// INTERNAL OBJECT & FUNCTION DECLARATION
88//--------------------------------------------------------------------+
90
91// TODO merged with DCD
92// Transfer conditions specifiable for each pipe for most MCUs
93// - Pipe 0: Control transfer with 64-byte single buffer
94// - Pipes 1 and 2: Bulk or ISO
95// - Pipes 3 to 5: Bulk
96// - Pipes 6 to 9: Interrupt
97//
98// Note: for small mcu such as
99// - RA2A1: only pipe 4-7 are available, and no support for ISO
100static unsigned find_pipe(unsigned xfer_type) {
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
108 // find backward since only pipe 1, 2 support ISO
109 const uint8_t idx_first = pipe_idx_arr[xfer_type][0];
110 const uint8_t idx_last = pipe_idx_arr[xfer_type][1];
111
112 for (int i = idx_last; i >= idx_first; i--) {
113 if (0 == _hcd.pipe[i].ep) return i;
114 }
115
116 return 0;
117}
118
119static volatile uint16_t* get_pipectr(rusb2_reg_t *rusb, unsigned num)
120{
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{
130 volatile reg_pipetre_t* tre = NULL;
131 if ((1 <= num) && (num <= 5)) {
132 tre = (volatile reg_pipetre_t*)&(rusb->PIPE_TR[num - 1].E);
133 }
134 return tre;
135}
136
137static volatile uint16_t* addr_to_pipectr(uint8_t rhport, uint8_t dev_addr, unsigned ep_addr)
138{
139 rusb2_reg_t* rusb = RUSB2_REG(rhport);
140 const unsigned epn = tu_edpt_number(ep_addr);
141
142 if (epn) {
143 const unsigned dir_in = tu_edpt_dir(ep_addr);
144 const unsigned num = _hcd.ep[dev_addr][dir_in][epn - 1];
145 return get_pipectr(rusb, num);
146 } else {
147 return get_pipectr(rusb, 0);
148 }
149}
150
151static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb)
152{
153 return rusb->DCPMAXP_b.MXPS;
154}
155
156static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num)
157{
158 rusb->PIPESEL = num;
159 return rusb->PIPEMAXP_b.MXPS;
160}
161
162static inline void pipe_wait_for_ready(rusb2_reg_t* rusb, unsigned num)
163{
164 while (rusb->D0FIFOSEL_b.CURPIPE != num) ;
165 while (!rusb->D0FIFOCTR_b.FRDY) {}
166}
167
168static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
169{
170 // NOTE: unlike DCD, Highspeed 32-bit FIFO does not need to adjust the fifo address
171 volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo;
172 uintptr_t addr = (uintptr_t)buf;
173 while (len >= 2) {
174 reg->u16 = *(const uint16_t *)addr;
175 addr += 2;
176 len -= 2;
177 }
178 if (len) {
179 reg->u8 = *(const uint8_t *)addr;
180 ++addr;
181 }
182}
183
184static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
185{
186 uint8_t *p = (uint8_t*)buf;
187 volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */
188 while (len--) *p++ = *reg;
189}
190
191static bool pipe0_xfer_in(rusb2_reg_t* rusb)
192{
193 pipe_state_t *pipe = &_hcd.pipe[0];
194 const unsigned rem = pipe->remaining;
195
196 const unsigned mps = edpt0_max_packet_size(rusb);
197 const unsigned vld = rusb->CFIFOCTR_b.DTLN;
198 const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
199 void *buf = pipe->buf;
200 if (len) {
201 rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
202 pipe_read_packet(buf, (volatile void*)&rusb->CFIFO, len);
203 pipe->buf = (uint8_t*)buf + len;
204 }
205 if (len < mps) {
206 rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
207 }
208 pipe->remaining = rem - len;
209 if ((len < mps) || (rem == len)) {
210 pipe->buf = NULL;
211 return true;
212 }
213 rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
214 return false;
215}
216
217static bool pipe0_xfer_out(rusb2_reg_t* rusb)
218{
219 pipe_state_t *pipe = &_hcd.pipe[0];
220 const unsigned rem = pipe->remaining;
221 if (!rem) {
222 pipe->buf = NULL;
223 return true;
224 }
225 const unsigned mps = edpt0_max_packet_size(rusb);
226 const unsigned len = TU_MIN(mps, rem);
227 void *buf = pipe->buf;
228 if (len) {
229 pipe_write_packet(buf, (volatile void*)&rusb->CFIFO, len);
230 pipe->buf = (uint8_t*)buf + len;
231 }
232 if (len < mps) {
233 rusb->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
234 }
235 pipe->remaining = rem - len;
236 return false;
237}
238
239static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num)
240{
241 pipe_state_t *pipe = &_hcd.pipe[num];
242 const unsigned rem = pipe->remaining;
243
244 rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
245 const unsigned mps = edpt_max_packet_size(rusb, num);
246 pipe_wait_for_ready(rusb, num);
247 const unsigned vld = rusb->D0FIFOCTR_b.DTLN;
248 const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
249 void *buf = pipe->buf;
250 if (len) {
251 pipe_read_packet(buf, (volatile void*)&rusb->D0FIFO, len);
252 pipe->buf = (uint8_t*)buf + len;
253 }
254 if (len < mps) {
255 rusb->D0FIFOCTR = RUSB2_D0FIFOCTR_BCLR_Msk;
256 }
257 rusb->D0FIFOSEL = 0;
258 while (rusb->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
259 pipe->remaining = rem - len;
260 if ((len < mps) || (rem == len)) {
261 pipe->buf = NULL;
262 return NULL != buf;
263 }
264 return false;
265}
266
267static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num)
268{
269 pipe_state_t *pipe = &_hcd.pipe[num];
270 const unsigned rem = pipe->remaining;
271
272 if (!rem) {
273 pipe->buf = NULL;
274 return true;
275 }
276
277 rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
278 const unsigned mps = edpt_max_packet_size(rusb, num);
279 pipe_wait_for_ready(rusb, num);
280 const unsigned len = TU_MIN(rem, mps);
281 void *buf = pipe->buf;
282 if (len) {
283 pipe_write_packet(buf, (volatile void*)&rusb->D0FIFO, len);
284 pipe->buf = (uint8_t*)buf + len;
285 }
286 if (len < mps) {
287 rusb->D0FIFOCTR = RUSB2_D0FIFOCTR_BVAL_Msk;
288 }
289 rusb->D0FIFOSEL = 0;
290 while (rusb->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
291 pipe->remaining = rem - len;
292 return false;
293}
294
295static bool process_pipe0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen)
296{
297 (void)dev_addr;
298
299 rusb2_reg_t* rusb = RUSB2_REG(rhport);
300 const unsigned dir_in = tu_edpt_dir(ep_addr);
301
302 /* configure fifo direction and access unit settings */
303 if (dir_in) { /* IN, a byte */
304 rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
305 while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ;
306 } else { /* OUT, 2 bytes */
307 rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
308 (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
309 while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ;
310 }
311
312 pipe_state_t *pipe = &_hcd.pipe[0];
313 pipe->ep = ep_addr;
314 pipe->length = buflen;
315 pipe->remaining = buflen;
316 if (buflen) {
317 pipe->buf = buffer;
318 if (!dir_in) { /* OUT */
319 TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80));
320 pipe0_xfer_out(rusb);
321 }
322 } else { /* ZLP */
323 pipe->buf = NULL;
324 if (!dir_in) { /* OUT */
325 rusb->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
326 }
327 if (dir_in == rusb->DCPCFG_b.DIR) {
328 TU_ASSERT(RUSB2_PIPE_CTR_PID_NAK == rusb->DCPCTR_b.PID);
329 rusb->DCPCTR_b.SQSET = 1;
330 rusb->DCPCFG_b.DIR = dir_in ^ 1;
331 }
332 }
333 rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
334 return true;
335}
336
337static bool process_pipe_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void *buffer, uint16_t buflen)
338{
339 rusb2_reg_t* rusb = RUSB2_REG(rhport);
340
341 const unsigned epn = tu_edpt_number(ep_addr);
342 const unsigned dir_in = tu_edpt_dir(ep_addr);
343 const unsigned num = _hcd.ep[dev_addr - 1][dir_in][epn - 1];
344
345 TU_ASSERT(num);
346
347 pipe_state_t *pipe = &_hcd.pipe[num];
348 pipe->buf = buffer;
349 pipe->length = buflen;
350 pipe->remaining = buflen;
351 if (!dir_in) { /* OUT */
352 if (buflen) {
353 pipe_xfer_out(rusb, num);
354 } else { /* ZLP */
355 rusb->D0FIFOSEL = num;
356 pipe_wait_for_ready(rusb, num);
357 rusb->D0FIFOCTR = RUSB2_D0FIFOCTR_BVAL_Msk;
358 rusb->D0FIFOSEL = 0;
359 while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
360 }
361 } else {
362 volatile uint16_t *ctr = get_pipectr(rusb, num);
363 volatile reg_pipetre_t *pt = get_pipetre(rusb, num);
364 if (pt) {
365 const unsigned mps = edpt_max_packet_size(rusb, num);
366 if (*ctr & 0x3) *ctr = RUSB2_PIPE_CTR_PID_NAK;
367 pt->TRE = TU_BIT(8);
368 pt->TRN = (buflen + mps - 1) / mps;
369 pt->TRENB = 1;
370 }
371 *ctr = RUSB2_PIPE_CTR_PID_BUF;
372 }
373 return true;
374}
375
376static bool process_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen)
377{
378 const unsigned epn = tu_edpt_number(ep_addr);
379 if (0 == epn) {
380 return process_pipe0_xfer(rhport, dev_addr, ep_addr, buffer, buflen);
381 } else {
382 return process_pipe_xfer(rhport, dev_addr, ep_addr, buffer, buflen);
383 }
384}
385
386static void process_pipe0_bemp(uint8_t rhport)
387{
388 rusb2_reg_t* rusb = RUSB2_REG(rhport);
389 bool completed = pipe0_xfer_out(rusb);
390 if (completed) {
391 pipe_state_t *pipe = &_hcd.pipe[0];
392 hcd_event_xfer_complete(pipe->dev,
394 pipe->length - pipe->remaining,
395 XFER_RESULT_SUCCESS, true);
396 }
397}
398
399static void process_pipe_nrdy(uint8_t rhport, unsigned num)
400{
401 rusb2_reg_t* rusb = RUSB2_REG(rhport);
402 xfer_result_t result;
403 uint16_t volatile *ctr = get_pipectr(rusb, num);
404 TU_LOG(TU_RUSB2_HCD_DBG, "NRDY %d %x\r\n", num, *ctr);
405 switch (*ctr & RUSB2_PIPE_CTR_PID_Msk) {
406 default: return;
407 case RUSB2_PIPE_CTR_PID_STALL: result = XFER_RESULT_STALLED; break;
408 case RUSB2_PIPE_CTR_PID_STALL2: result = XFER_RESULT_STALLED; break;
409 case RUSB2_PIPE_CTR_PID_NAK: result = XFER_RESULT_FAILED; break;
410 }
411 pipe_state_t *pipe = &_hcd.pipe[num];
412 hcd_event_xfer_complete(pipe->dev, pipe->ep,
413 pipe->length - pipe->remaining,
414 result, true);
415}
416
417static void process_pipe_brdy(uint8_t rhport, unsigned num)
418{
419 rusb2_reg_t* rusb = RUSB2_REG(rhport);
420 pipe_state_t *pipe = &_hcd.pipe[num];
421 const unsigned dir_in = tu_edpt_dir(pipe->ep);
422 bool completed;
423
424 if (dir_in) { /* IN */
425 if (num) {
426 completed = pipe_xfer_in(rusb, num);
427 } else {
428 completed = pipe0_xfer_in(rusb);
429 }
430 } else {
431 completed = pipe_xfer_out(rusb, num);
432 }
433 if (completed) {
434 hcd_event_xfer_complete(pipe->dev, pipe->ep,
435 pipe->length - pipe->remaining,
436 XFER_RESULT_SUCCESS, true);
437 TU_LOG(TU_RUSB2_HCD_DBG, "C %d %d\r\n", num, pipe->length - pipe->remaining);
438 }
439}
440
441/*------------------------------------------------------------------*/
442/* Host API
443 *------------------------------------------------------------------*/
444
445#if 0 // previously present in the rx driver before generalization
446static uint32_t disable_interrupt(void)
447{
448 uint32_t pswi;
449#if defined(__CCRX__)
450 pswi = get_psw() & 0x010000;
451 clrpsw_i();
452#else
453 pswi = __builtin_rx_mvfc(0) & 0x010000;
454 __builtin_rx_clrpsw('I');
455#endif
456 return pswi;
457}
458
459static void enable_interrupt(uint32_t pswi)
460{
461#if defined(__CCRX__)
462 set_psw(get_psw() | pswi);
463#else
464 __builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi);
465#endif
466}
467#endif
468
469bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
470 (void) rh_init;
471 rusb2_reg_t* rusb = RUSB2_REG(rhport);
472 rusb2_module_start(rhport, true);
473
474#ifdef RUSB2_SUPPORT_HIGHSPEED
475 if (rusb2_is_highspeed_rhport(rhport) ) {
476 rusb->SYSCFG_b.HSE = 1;
477 rusb->PHYSET_b.HSEB = 0;
478 rusb->PHYSET_b.DIRPD = 0;
479 R_BSP_SoftwareDelay((uint32_t) 1, BSP_DELAY_UNITS_MILLISECONDS);
480 rusb->PHYSET_b.PLLRESET = 0;
481 rusb->LPSTS_b.SUSPENDM = 1;
482 while ( !rusb->PLLSTA_b.PLLLOCK );
483 rusb->SYSCFG_b.DRPD = 1;
484 rusb->SYSCFG_b.DCFM = 1;
485 rusb->SYSCFG_b.DPRPU = 0;
486 rusb->SYSCFG_b.CNEN = 1;
487 rusb->BUSWAIT |= 0x0F00U;
488 rusb->SOFCFG_b.INTL = 1;
489 rusb->DVSTCTR0_b.VBUSEN = 1;
490 rusb->CFIFOSEL_b.MBW = 1;
491 rusb->D0FIFOSEL_b.MBW = 1;
492 rusb->D1FIFOSEL_b.MBW = 1;
493 rusb->INTSTS0 = 0;
494 for ( volatile int i = 0; i < 30000; ++i );
495 rusb->SYSCFG_b.USBE = 1;
496 } else
497#endif
498 {
499 rusb->SYSCFG_b.SCKE = 1;
500 while ( !rusb->SYSCFG_b.SCKE ) {}
501 rusb->SYSCFG_b.DCFM = 1; // Host function
502 rusb->SYSCFG_b.DPRPU = 0; // Disable D+ pull up
503 rusb->SYSCFG_b.DRPD = 1; // Enable D+/D- pull down
504
505 rusb->DVSTCTR0_b.VBUSEN = 1;
506 for ( volatile int i = 0; i < 30000; ++i ) {} // FIXME do we need to wait here? how long ?
507 //R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
508 rusb->SYSCFG_b.USBE = 1;
509
510 // MCU specific PHY init
512
513 rusb->PHYSLEW = 0x5;
514 rusb->DPUSR0R_FS_b.FIXPHY0 = 0u; /* Transceiver Output fixed */
515 }
516
517 /* Setup default control pipe */
518 rusb->DCPCFG = RUSB2_PIPECFG_SHTNAK_Msk;
519 rusb->DCPMAXP = 64;
520 rusb->INTENB0 = RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk;
521 rusb->INTENB1 = RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk;
522 rusb->BEMPENB = 1;
523 rusb->NRDYENB = 1;
524 rusb->BRDYENB = 1;
525
526 return true;
527}
528
529void hcd_int_enable(uint8_t rhport) {
530 rusb2_int_enable(rhport);
531}
532
533void hcd_int_disable(uint8_t rhport) {
534 rusb2_int_disable(rhport);
535}
536
537uint32_t hcd_frame_number(uint8_t rhport)
538{
539 rusb2_reg_t* rusb = RUSB2_REG(rhport);
540
541 /* The device must be reset at least once after connection
542 * in order to start the frame counter. */
543 if (_hcd.need_reset) hcd_port_reset(rhport);
544 return rusb->FRMNUM_b.FRNM;
545}
546
547/*--------------------------------------------------------------------+
548 * Port API
549 *--------------------------------------------------------------------+*/
550bool hcd_port_connect_status(uint8_t rhport) {
551 rusb2_reg_t* rusb = RUSB2_REG(rhport);
552 return rusb->INTSTS1_b.ATTCH ? true : false;
553}
554
555void hcd_port_reset(uint8_t rhport) {
556 rusb2_reg_t* rusb = RUSB2_REG(rhport);
557 rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
558 while (rusb->DCPCTR_b.PBUSY) {}
559
560 hcd_int_disable(rhport);
561 rusb->DVSTCTR0_b.UACT = 0;
562 if (rusb->DCPCTR_b.SUREQ) {
563 rusb->DCPCTR_b.SUREQCLR = 1;
564 }
565 hcd_int_enable(rhport);
566
567 /* Reset should be asserted 10-20ms. */
568 rusb->DVSTCTR0_b.USBRST = 1;
569 for (volatile int i = 0; i < 2400000; ++i) {}
570 rusb->DVSTCTR0_b.USBRST = 0;
571
572 rusb->DVSTCTR0_b.UACT = 1;
573 _hcd.need_reset = false;
574}
575
576void hcd_port_reset_end(uint8_t rhport) {
577 (void) rhport;
578}
579
581 rusb2_reg_t* rusb = RUSB2_REG(rhport);
582 switch (rusb->DVSTCTR0_b.RHST) {
583 case RUSB2_DVSTCTR0_RHST_HS: return TUSB_SPEED_HIGH;
584 case RUSB2_DVSTCTR0_RHST_FS: return TUSB_SPEED_FULL;
585 case RUSB2_DVSTCTR0_RHST_LS: return TUSB_SPEED_LOW;
586 default: return TUSB_SPEED_INVALID;
587 }
588}
589
590void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
591 rusb2_reg_t* rusb = RUSB2_REG(rhport);
592 uint16_t volatile *ctr;
593
594 TU_ASSERT(dev_addr < 6,); /* USBa can only handle addresses from 0 to 5. */
595 if (!dev_addr) return;
596
597 _hcd.ctl_mps[dev_addr] = 0;
598 uint8_t *ep = &_hcd.ep[dev_addr - 1][0][0];
599
600 for (int i = 0; i < 2 * 15; ++i, ++ep) {
601 unsigned num = *ep;
602 if (!num || (dev_addr != _hcd.pipe[num].dev)) continue;
603
604 ctr = (uint16_t volatile*)&rusb->PIPE_CTR[num - 1];
605 *ctr = 0;
606 rusb->NRDYENB &= ~TU_BIT(num);
607 rusb->BRDYENB &= ~TU_BIT(num);
608 rusb->PIPESEL = num;
609 rusb->PIPECFG = 0;
610 rusb->PIPEMAXP = 0;
611
612 _hcd.pipe[num].ep = 0;
613 _hcd.pipe[num].dev = 0;
614 *ep = 0;
615 }
616}
617
618/*--------------------------------------------------------------------+
619 * Endpoints API
620 *--------------------------------------------------------------------+*/
621bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
622{
623 TU_ASSERT(dev_addr < 6); /* USBa can only handle addresses from 0 to 5. */
624
625 rusb2_reg_t* rusb = RUSB2_REG(rhport);
626 TU_LOG(TU_RUSB2_HCD_DBG, "S %d %x\r\n", dev_addr, rusb->DCPCTR);
627
628 TU_ASSERT(0 == rusb->DCPCTR_b.SUREQ);
629
630 rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
631
632 _hcd.pipe[0].buf = NULL;
633 _hcd.pipe[0].length = 8;
634 _hcd.pipe[0].remaining = 0;
635 _hcd.pipe[0].dev = dev_addr;
636
637 while (rusb->DCPCTR_b.PBUSY) ;
638 rusb->DCPMAXP = (dev_addr << 12) | _hcd.ctl_mps[dev_addr];
639
640 /* Set direction in advance for DATA stage */
641 uint8_t const bmRequesttype = setup_packet[0];
642 rusb->DCPCFG_b.DIR = tu_edpt_dir(bmRequesttype) ? 0: 1;
643
644 uint16_t const* p = (uint16_t const*)(uintptr_t)&setup_packet[0];
645 rusb->USBREQ = tu_htole16(p[0]);
646 rusb->USBVAL = p[1];
647 rusb->USBINDX = p[2];
648 rusb->USBLENG = p[3];
649
650 rusb->DCPCTR_b.SUREQ = 1;
651 return true;
652}
653
654bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc)
655{
656 TU_ASSERT(dev_addr < 6); /* USBa can only handle addresses from 0 to 5. */
657 rusb2_reg_t* rusb = RUSB2_REG(rhport);
658
659 const unsigned ep_addr = ep_desc->bEndpointAddress;
660 const unsigned epn = tu_edpt_number(ep_addr);
661 const unsigned mps = tu_edpt_packet_size(ep_desc);
662
663 if (0 == epn) {
664 rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
665 hcd_devtree_info_t devtree;
667 uint16_t volatile *devadd = (uint16_t volatile *)(uintptr_t) &rusb->DEVADD[0];
668 devadd += dev_addr;
669 while (rusb->DCPCTR_b.PBUSY) {}
670 rusb->DCPMAXP = (dev_addr << 12) | mps;
671 *devadd = (TUSB_SPEED_FULL == devtree.speed) ? RUSB2_DEVADD_USBSPD_FS : RUSB2_DEVADD_USBSPD_LS;
672 _hcd.ctl_mps[dev_addr] = mps;
673 return true;
674 }
675
676 const unsigned dir_in = tu_edpt_dir(ep_addr);
677 const unsigned xfer = ep_desc->bmAttributes.xfer;
678 if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) {
679 /* USBa supports up to 256 bytes */
680 return false;
681 }
682 const unsigned num = find_pipe(xfer);
683 if (!num) return false;
684
685 _hcd.pipe[num].dev = dev_addr;
686 _hcd.pipe[num].ep = ep_addr;
687 _hcd.ep[dev_addr - 1][dir_in][epn - 1] = num;
688
689 /* setup pipe */
690 hcd_int_disable(rhport);
691
692 rusb->PIPESEL = num;
693 rusb->PIPEMAXP = (dev_addr << 12) | mps;
694 volatile uint16_t *ctr = get_pipectr(rusb, num);
695 *ctr = RUSB2_PIPE_CTR_ACLRM_Msk | RUSB2_PIPE_CTR_SQCLR_Msk;
696 *ctr = 0;
697
698 unsigned cfg = ((1 ^ dir_in) << 4) | epn;
699 if (xfer == TUSB_XFER_BULK) {
700 cfg |= RUSB2_PIPECFG_TYPE_BULK | RUSB2_PIPECFG_SHTNAK_Msk | RUSB2_PIPECFG_DBLB_Msk;
701 } else if (xfer == TUSB_XFER_INTERRUPT) {
702 cfg |= RUSB2_PIPECFG_TYPE_INT;
703 } else {
704 cfg |= RUSB2_PIPECFG_TYPE_ISO | RUSB2_PIPECFG_DBLB_Msk;
705 }
706
707 rusb->PIPECFG = cfg;
708 rusb->BRDYSTS = 0x3FFu ^ TU_BIT(num);
709 rusb->NRDYENB |= TU_BIT(num);
710 rusb->BRDYENB |= TU_BIT(num);
711
712 if (!dir_in) {
713 *ctr = RUSB2_PIPE_CTR_PID_BUF;
714 }
715
716 hcd_int_enable(rhport);
717
718 return true;
719}
720
721bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
722{
723 bool r;
724 hcd_int_disable(rhport);
725 TU_LOG(TU_RUSB2_HCD_DBG, "X %d %x %u\r\n", dev_addr, ep_addr, buflen);
726 r = process_edpt_xfer(rhport, dev_addr, ep_addr, buffer, buflen);
727 hcd_int_enable(rhport);
728 return r;
729}
730
731bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
732 (void) rhport;
733 (void) dev_addr;
734 (void) ep_addr;
735 // TODO not implemented yet
736 return false;
737}
738
739bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
740 uint16_t volatile *ctr = addr_to_pipectr(rhport, dev_addr, ep_addr);
741 TU_ASSERT(ctr);
742
743 const uint32_t pid = *ctr & 0x3;
744 if (pid & 2) {
745 *ctr = pid & 2;
746 *ctr = 0;
747 }
748 *ctr = RUSB2_PIPE_CTR_SQCLR_Msk;
749 unsigned const epn = tu_edpt_number(ep_addr);
750 if (!epn) return true;
751
752 if (!tu_edpt_dir(ep_addr)) { /* OUT */
753 *ctr = RUSB2_PIPE_CTR_PID_BUF;
754 }
755 return true;
756}
757
758//--------------------------------------------------------------------+
759// ISR
760//--------------------------------------------------------------------+
761#if defined(__CCRX__)
762TU_ATTR_ALWAYS_INLINE static inline unsigned __builtin_ctz(unsigned int value) {
763 unsigned int count = 0;
764 while ((value & 1) == 0) {
765 value >>= 1;
766 count++;
767 }
768 return count;
769}
770#endif
771
772void hcd_int_handler(uint8_t rhport, bool in_isr) {
773 (void) in_isr;
774
775 rusb2_reg_t* rusb = RUSB2_REG(rhport);
776 unsigned is0 = rusb->INTSTS0;
777 unsigned is1 = rusb->INTSTS1;
778
779 /* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */
780 rusb->INTSTS1 = ~((RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk) & is1);
781 rusb->INTSTS0 = ~((RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk) & is0);
782
783 TU_LOG3("IS %04x %04x\r\n", is0, is1);
784 is1 &= rusb->INTENB1;
785 is0 &= rusb->INTENB0;
786
787 if (is1 & RUSB2_INTSTS1_SACK_Msk) {
788 /* Set DATA1 in advance for the next transfer. */
789 rusb->DCPCTR_b.SQSET = 1;
791 }
792
793 if (is1 & RUSB2_INTSTS1_SIGN_Msk) {
795 }
796
797 if (is1 & RUSB2_INTSTS1_ATTCH_Msk) {
798 rusb->DVSTCTR0_b.UACT = 1;
799 _hcd.need_reset = true;
800 rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk;
801 hcd_event_device_attach(rhport, true);
802 }
803
804 if (is1 & RUSB2_INTSTS1_DTCH_Msk) {
805 rusb->DVSTCTR0_b.UACT = 0;
806 if (rusb->DCPCTR_b.SUREQ) {
807 rusb->DCPCTR_b.SUREQCLR = 1;
808 }
809 rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_DTCH_Msk) | RUSB2_INTSTS1_ATTCH_Msk;
810 hcd_event_device_remove(rhport, true);
811 }
812
813 if (is0 & RUSB2_INTSTS0_BEMP_Msk) {
814 const unsigned s = rusb->BEMPSTS;
815 rusb->BEMPSTS = 0;
816 if (s & 1) {
817 process_pipe0_bemp(rhport);
818 }
819 }
820
821 if (is0 & RUSB2_INTSTS0_NRDY_Msk) {
822 const unsigned m = rusb->NRDYENB;
823 unsigned s = rusb->NRDYSTS & m;
824 rusb->NRDYSTS = ~s;
825 while (s) {
826 const unsigned num = __builtin_ctz(s);
827 process_pipe_nrdy(rhport, num);
828 s &= ~TU_BIT(num);
829 }
830 }
831 if (is0 & RUSB2_INTSTS0_BRDY_Msk) {
832 const unsigned m = rusb->BRDYENB;
833 unsigned s = rusb->BRDYSTS & m;
834 /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
835 rusb->BRDYSTS = ~s;
836 while (s) {
837 const unsigned num = __builtin_ctz(s);
838 process_pipe_brdy(rhport, num);
839 s &= ~TU_BIT(num);
840 }
841 }
842}
843
844#endif
static bool in_isr
xfer_td_t xfer[EP_CBI_COUNT+1][2]
Definition: dcd_nrf5x.c:119
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_remove(uint8_t rhport, bool in_isr)
Definition: hcd.h:209
static TU_ATTR_ALWAYS_INLINE void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
Definition: hcd.h:221
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_attach(uint8_t rhport, bool in_isr)
Definition: hcd.h:197
void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t *devtree_info)
Definition: usbh.c:949
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
Definition: hcd_rusb2.c:621
static volatile uint16_t * addr_to_pipectr(uint8_t rhport, uint8_t dev_addr, unsigned ep_addr)
Definition: hcd_rusb2.c:137
static bool pipe_xfer_in(rusb2_reg_t *rusb, unsigned num)
Definition: hcd_rusb2.c:239
struct TU_ATTR_PACKED pipe_state_t
void hcd_int_disable(uint8_t rhport)
Definition: hcd_rusb2.c:533
static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num)
Definition: hcd_rusb2.c:156
static bool pipe_xfer_out(rusb2_reg_t *rusb, unsigned num)
Definition: hcd_rusb2.c:267
static uint16_t edpt0_max_packet_size(rusb2_reg_t *rusb)
Definition: hcd_rusb2.c:151
static TU_ATTR_ALWAYS_INLINE unsigned __builtin_ctz(unsigned int value)
Definition: hcd_rusb2.c:762
static uint32_t disable_interrupt(void)
Definition: hcd_rusb2.c:446
static unsigned find_pipe(unsigned xfer_type)
Definition: hcd_rusb2.c:100
static volatile reg_pipetre_t * get_pipetre(rusb2_reg_t *rusb, unsigned num)
Definition: hcd_rusb2.c:128
static void process_pipe0_bemp(uint8_t rhport)
Definition: hcd_rusb2.c:386
static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
Definition: hcd_rusb2.c:168
@ PIPE_COUNT
Definition: hcd_rusb2.c:49
static void process_pipe_nrdy(uint8_t rhport, unsigned num)
Definition: hcd_rusb2.c:399
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_rusb2.c:739
static void enable_interrupt(uint32_t pswi)
Definition: hcd_rusb2.c:459
void hcd_int_enable(uint8_t rhport)
Definition: hcd_rusb2.c:529
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
Definition: hcd_rusb2.c:721
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
Definition: hcd_rusb2.c:590
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_rusb2.c:731
static bool pipe0_xfer_out(rusb2_reg_t *rusb)
Definition: hcd_rusb2.c:217
TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN union TU_ATTR_PACKED hw_fifo_t
void hcd_port_reset_end(uint8_t rhport)
Definition: hcd_rusb2.c:576
void hcd_port_reset(uint8_t rhport)
Definition: hcd_rusb2.c:555
static bool process_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void *buffer, uint16_t buflen)
Definition: hcd_rusb2.c:376
static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
Definition: hcd_rusb2.c:184
bool hcd_port_connect_status(uint8_t rhport)
Definition: hcd_rusb2.c:550
static bool process_pipe_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void *buffer, uint16_t buflen)
Definition: hcd_rusb2.c:337
static void process_pipe_brdy(uint8_t rhport, unsigned num)
Definition: hcd_rusb2.c:417
uint32_t hcd_frame_number(uint8_t rhport)
Definition: hcd_rusb2.c:537
static volatile uint16_t * get_pipectr(rusb2_reg_t *rusb, unsigned num)
Definition: hcd_rusb2.c:119
static bool pipe0_xfer_in(rusb2_reg_t *rusb)
Definition: hcd_rusb2.c:191
static hcd_data_t _hcd
Definition: hcd_rusb2.c:89
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
Definition: hcd_rusb2.c:580
void hcd_int_handler(uint8_t rhport, bool in_isr)
Definition: hcd_rusb2.c:772
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: hcd_rusb2.c:469
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc)
Definition: hcd_rusb2.c:654
static void pipe_wait_for_ready(rusb2_reg_t *rusb, unsigned num)
Definition: hcd_rusb2.c:162
static bool process_pipe0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void *buffer, uint16_t buflen)
Definition: hcd_rusb2.c:295
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 BEMPSTS
Definition: rusb2_type.h:518
struct _ccrx_evenaccess::@512::TU_ATTR_PACKED FRMNUM_b
volatile uint16_t DEVADD[10]
Definition: rusb2_type.h:771
struct _ccrx_evenaccess::@504::TU_ATTR_PACKED INTSTS1_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 PIPESEL
Definition: rusb2_type.h:646
volatile uint32_t CFIFO
Definition: rusb2_type.h:171
struct _ccrx_evenaccess::@538::TU_ATTR_PACKED PIPEMAXP_b
volatile uint16_t PIPEMAXP
Definition: rusb2_type.h:683
struct _ccrx_evenaccess::@478::TU_ATTR_PACKED CFIFOCTR_b
volatile uint16_t BUSWAIT
Definition: rusb2_type.h:109
volatile uint16_t CFIFOSEL
Definition: rusb2_type.h:231
volatile uint16_t INTENB1
Definition: rusb2_type.h:333
struct _ccrx_evenaccess::@530::TU_ATTR_PACKED DCPCTR_b
volatile uint16_t DCPMAXP
Definition: rusb2_type.h:615
volatile uint32_t D0FIFO
Definition: rusb2_type.h:191
struct _ccrx_evenaccess::@476::TU_ATTR_PACKED CFIFOSEL_b
struct _ccrx_evenaccess::@556::TU_ATTR_PACKED LPSTS_b
volatile uint16_t NRDYSTS
Definition: rusb2_type.h:500
struct _ccrx_evenaccess::@482::TU_ATTR_PACKED D0FIFOCTR_b
volatile RUSB2_PIPE_TR_t PIPE_TR[5]
Definition: rusb2_type.h:724
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
struct _ccrx_evenaccess::@498::TU_ATTR_PACKED SOFCFG_b
volatile uint16_t NRDYENB
Definition: rusb2_type.h:373
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
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
volatile uint16_t DCPCFG
Definition: rusb2_type.h:602
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::@526::TU_ATTR_PACKED DCPCFG_b
struct _ccrx_evenaccess::@580::TU_ATTR_PACKED DPUSR0R_FS_b
volatile uint16_t CFIFOCTR
Definition: rusb2_type.h:248
volatile uint16_t INTSTS1
Definition: rusb2_type.h:460
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
uint32_t dev
Definition: hcd_rusb2.c:69
uint32_t ff
Definition: hcd_rusb2.c:70
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
volatile uint16_t u16
Definition: hcd_rusb2.c:60
uint16_t length
Definition: dcd_ci_fs.c:94
uint32_t ep
Definition: hcd_rusb2.c:68
volatile uint16_t
Definition: hcd_rusb2.c:58
void * buf
Definition: dcd_musb.c:69
uint16_t remaining
Definition: dcd_ci_fs.c:95
uint8_t bEndpointAddress
Definition: video.h:306
volatile uint16_t u8
Definition: hcd_rusb2.c:57
uint8_t ep[4][2][15]
Definition: hcd_rusb2.c:82
uint8_t ctl_mps[7]
Definition: hcd_musb.c:111
bool need_reset
Definition: hcd_musb.c:109
pipe_state_t pipe[7][2]
Definition: hcd_musb.c:113
uint8_t speed
Definition: hcd.h:97
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
@ TUSB_DIR_OUT
Definition: tusb_types.h:66
tusb_speed_t
defined base on EHCI specs value for Endpoint Speed
Definition: tusb_types.h:49
@ TUSB_SPEED_INVALID
Definition: tusb_types.h:54
@ 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_t
Definition: tusb_types.h:236
@ XFER_RESULT_FAILED
Definition: tusb_types.h:238
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
@ XFER_RESULT_STALLED
Definition: tusb_types.h:239
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
volatile uint16_t u16
Definition: dcd_musb.c:63
volatile uint8_t u8
Definition: dcd_musb.c:62