Open FFBoard
Open source force feedback firmware
hcd_khci.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2021 Koji Kitayama
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#include "tusb_option.h"
28
29#if CFG_TUH_ENABLED && defined(TUP_USBIP_CHIPIDEA_FS)
30
31#ifdef TUP_USBIP_CHIPIDEA_FS_KINETIS
32 #include "fsl_device_registers.h"
33 #define KHCI USB0
34#else
35 #error "MCU is not supported"
36#endif
37
38#include "host/hcd.h"
39
40//--------------------------------------------------------------------+
41// MACRO TYPEDEF CONSTANT ENUM DECLARATION
42//--------------------------------------------------------------------+
43
44enum {
46 TOK_PID_IN = 0x9u,
55};
56
57typedef struct TU_ATTR_PACKED
58{
59 union {
60 uint32_t head;
61 struct {
62 union {
63 struct {
64 uint16_t : 2;
65 __IO uint16_t tok_pid : 4;
66 uint16_t data : 1;
67 __IO uint16_t own : 1;
68 uint16_t : 8;
69 };
70 struct {
71 uint16_t : 2;
73 uint16_t dts : 1;
74 uint16_t ninc : 1;
75 uint16_t keep : 1;
76 uint16_t : 10;
77 };
78 };
79 __IO uint16_t bc : 10;
80 uint16_t : 6;
81 };
82 };
83 uint8_t *addr;
85
86TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" );
87
88typedef struct TU_ATTR_PACKED
89{
90 union {
91 uint32_t state;
92 struct {
93 uint32_t pipenum:16;
94 uint32_t odd : 1;
95 uint32_t : 0;
96 };
97 };
98 uint8_t *buffer;
102
103typedef struct TU_ATTR_PACKED
104{
105 uint8_t dev_addr;
106 uint8_t ep_addr;
108 union {
109 uint8_t flags;
110 struct {
111 uint8_t data : 1;
112 uint8_t xfer : 2;
113 uint8_t : 0;
114 };
115 };
116 uint8_t *buffer;
120
121
122typedef struct
123{
124 union {
125 /* [OUT,IN][EVEN,ODD] */
127 uint16_t bda[2*2];
128 };
129 endpoint_state_t endpoint[2];
130 pipe_state_t pipe[CFG_TUH_ENDPOINT_MAX * 2];
131 uint32_t in_progress; /* Bitmap. Each bit indicates that a transfer of the corresponding pipe is in progress */
132 uint32_t pending; /* Bitmap. Each bit indicates that a transfer of the corresponding pipe will be resume the next frame */
133 bool need_reset; /* The device has not been reset after connection. */
134} hcd_data_t;
135
136//--------------------------------------------------------------------+
137// INTERNAL OBJECT & FUNCTION DECLARATION
138//--------------------------------------------------------------------+
139// BDT(Buffer Descriptor Table) must be 256-byte aligned
140CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(512) static hcd_data_t _hcd;
141//CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _rx_buf[1024];
142
143int find_pipe(uint8_t dev_addr, uint8_t ep_addr)
144{
145 /* Find the target pipe */
146 int num;
147 for (num = 0; num < CFG_TUH_ENDPOINT_MAX * 2; ++num) {
148 pipe_state_t *p = &_hcd.pipe[num];
149 if ((p->dev_addr == dev_addr) && (p->ep_addr == ep_addr))
150 return num;
151 }
152 return -1;
153}
154
155static int prepare_packets(int pipenum)
156{
157 pipe_state_t *pipe = &_hcd.pipe[pipenum];
158 unsigned const dir_tx = tu_edpt_dir(pipe->ep_addr) ? 0 : 1;
159 endpoint_state_t *ep = &_hcd.endpoint[dir_tx];
160 unsigned const odd = ep->odd;
161 buffer_descriptor_t *bd = _hcd.bdt[dir_tx];
162 TU_ASSERT(0 == bd[odd].own, -1);
163
164 // TU_LOG1(" %p dir %d odd %d data %d\r\n", &bd[odd], dir_tx, odd, pipe->data);
165
166 ep->pipenum = pipenum;
167
168 bd[odd ].data = pipe->data;
169 bd[odd ^ 1].data = pipe->data ^ 1;
170 bd[odd ^ 1].own = 0;
171 /* reset values for a next transfer */
172
173 int num_tokens = 0; /* The number of prepared packets */
174 unsigned const mps = pipe->max_packet_size;
175 unsigned const rem = pipe->remaining;
176 if (rem > mps) {
177 /* When total_bytes is greater than the max packet size,
178 * it prepares to the next transfer to avoid NAK in advance. */
179 bd[odd ^ 1].bc = rem >= 2 * mps ? mps: rem - mps;
180 bd[odd ^ 1].addr = pipe->buffer + mps;
181 bd[odd ^ 1].own = 1;
182 if (dir_tx) ++num_tokens;
183 }
184 bd[odd].bc = rem >= mps ? mps: rem;
185 bd[odd].addr = pipe->buffer;
186 __DSB();
187 bd[odd].own = 1; /* This bit must be set last */
188 ++num_tokens;
189 return num_tokens;
190}
191
192static int select_next_pipenum(int pipenum)
193{
194 unsigned wip = _hcd.in_progress & ~_hcd.pending;
195 if (!wip) return -1;
196 unsigned msk = TU_GENMASK(31, pipenum);
197 int next = __builtin_ctz(wip & msk);
198 if (next) return next;
199 msk = TU_GENMASK(pipenum, 0);
200 next = __builtin_ctz(wip & msk);
201 return next;
202}
203
204/* When transfer is completed, return true. */
205static bool continue_transfer(int pipenum, buffer_descriptor_t *bd)
206{
207 pipe_state_t *pipe = &_hcd.pipe[pipenum];
208 unsigned const bc = bd->bc;
209 unsigned const rem = pipe->remaining - bc;
210
211 pipe->remaining = rem;
212 if (rem && bc == pipe->max_packet_size) {
213 int const next_rem = rem - pipe->max_packet_size;
214 if (next_rem > 0) {
215 /* Prepare to the after next transfer */
216 bd->addr += pipe->max_packet_size * 2;
217 bd->bc = next_rem > pipe->max_packet_size ? pipe->max_packet_size: next_rem;
218 __DSB();
219 bd->own = 1; /* This bit must be set last */
220 while (KHCI->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) ;
221 KHCI->TOKEN = KHCI->TOKEN; /* Queue the same token as the last */
222 } else if (TUSB_DIR_IN == tu_edpt_dir(pipe->ep_addr)) { /* IN */
223 while (KHCI->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) ;
224 KHCI->TOKEN = KHCI->TOKEN;
225 }
226 return true;
227 }
228 pipe->data = bd->data ^ 1;
229 return false;
230}
231
232static bool resume_transfer(int pipenum)
233{
234 int num_tokens = prepare_packets(pipenum);
235 TU_ASSERT(0 <= num_tokens);
236
237 const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
238 NVIC_DisableIRQ(USB0_IRQn);
239 pipe_state_t *pipe = &_hcd.pipe[pipenum];
240
241 unsigned flags = KHCI->ENDPOINT[0].ENDPT & USB_ENDPT_HOSTWOHUB_MASK;
242 flags |= USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK;
243 switch (pipe->xfer) {
245 flags |= USB_ENDPT_EPHSHK_MASK;
246 break;
248 flags |= USB_ENDPT_EPCTLDIS_MASK | USB_ENDPT_RETRYDIS_MASK;
249 break;
250 default:
251 flags |= USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPCTLDIS_MASK | USB_ENDPT_RETRYDIS_MASK;
252 break;
253 }
254 // TU_LOG1(" resume pipenum %d flags %x\r\n", pipenum, flags);
255
256 KHCI->ENDPOINT[0].ENDPT = flags;
257 KHCI->ADDR = (KHCI->ADDR & USB_ADDR_LSEN_MASK) | pipe->dev_addr;
258
259 unsigned const token = tu_edpt_number(pipe->ep_addr) |
260 ((tu_edpt_dir(pipe->ep_addr) ? TOK_PID_IN: TOK_PID_OUT) << USB_TOKEN_TOKENPID_SHIFT);
261 do {
262 while (KHCI->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) ;
263 KHCI->TOKEN = token;
264 } while (--num_tokens);
265 if (ie) NVIC_EnableIRQ(USB0_IRQn);
266 return true;
267}
268
269static void suspend_transfer(int pipenum, buffer_descriptor_t *bd)
270{
271 pipe_state_t *pipe = &_hcd.pipe[pipenum];
272 pipe->buffer = bd->addr;
273 pipe->data = bd->data ^ 1;
274 if ((TUSB_XFER_INTERRUPT == pipe->xfer) ||
275 (TUSB_XFER_BULK == pipe->xfer)) {
276 _hcd.pending |= TU_BIT(pipenum);
277 KHCI->INTEN |= USB_ISTAT_SOFTOK_MASK;
278 }
279}
280
281static void process_tokdne(uint8_t rhport)
282{
283 (void)rhport;
284 const unsigned s = KHCI->STAT;
285 KHCI->ISTAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */
286 uint8_t const dir_in = (s & USB_STAT_TX_MASK) ? TUSB_DIR_OUT: TUSB_DIR_IN;
287 unsigned const odd = (s & USB_STAT_ODD_MASK) ? 1 : 0;
288
290 endpoint_state_t *ep = &_hcd.endpoint[s >> 3];
291
292 /* fetch status before discarded by the next steps */
293 const unsigned pid = bd->tok_pid;
294
295 /* reset values for a next transfer */
296 bd->bdt_stall = 0;
297 bd->dts = 1;
298 bd->ninc = 0;
299 bd->keep = 0;
300 /* Update the odd variable to prepare for the next transfer */
301 ep->odd = odd ^ 1;
302
303 int pipenum = ep->pipenum;
304 int next_pipenum;
305 // TU_LOG1("TOKDNE %x PID %x pipe %d\r\n", s, pid, pipenum);
306
307 xfer_result_t result;
308 switch (pid) {
309 default:
310 if (continue_transfer(pipenum, bd))
311 return;
312 result = XFER_RESULT_SUCCESS;
313 break;
314 case TOK_PID_NAK:
315 suspend_transfer(pipenum, bd);
316 next_pipenum = select_next_pipenum(pipenum);
317 if (0 <= next_pipenum)
318 resume_transfer(next_pipenum);
319 return;
320 case TOK_PID_STALL:
321 result = XFER_RESULT_STALLED;
322 break;
323 case TOK_PID_ERR: /* mismatch toggle bit */
324 case TOK_PID_BUSTO:
325 result = XFER_RESULT_FAILED;
326 break;
327 }
328 _hcd.in_progress &= ~TU_BIT(pipenum);
329 pipe_state_t *pipe = &_hcd.pipe[ep->pipenum];
330 hcd_event_xfer_complete(pipe->dev_addr,
331 tu_edpt_addr(KHCI->TOKEN & USB_TOKEN_TOKENENDPT_MASK, dir_in),
332 pipe->length - pipe->remaining,
333 result, true);
334 next_pipenum = select_next_pipenum(pipenum);
335 if (0 <= next_pipenum)
336 resume_transfer(next_pipenum);
337}
338
339static void process_attach(uint8_t rhport)
340{
341 unsigned ctl = KHCI->CTL;
342 if (!(ctl & USB_CTL_JSTATE_MASK)) {
343 /* The attached device is a low speed device. */
344 KHCI->ADDR = USB_ADDR_LSEN_MASK;
345 KHCI->ENDPOINT[0].ENDPT = USB_ENDPT_HOSTWOHUB_MASK;
346 }
347 hcd_event_device_attach(rhport, true);
348}
349
350static void process_bus_reset(uint8_t rhport)
351{
352 KHCI->ISTAT = USB_ISTAT_TOKDNE_MASK;
353 KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK;
354 KHCI->CTL &= ~USB_CTL_USBENSOFEN_MASK;
355 KHCI->ADDR = 0;
356 KHCI->ENDPOINT[0].ENDPT = 0;
357
358 hcd_event_device_remove(rhport, true);
359
360 _hcd.in_progress = 0;
361 _hcd.pending = 0;
362 buffer_descriptor_t *bd = &_hcd.bdt[0][0];
363 for (unsigned i = 0; i < 2; ++i, ++bd) {
364 bd->head = 0;
365 }
366}
367
368/*------------------------------------------------------------------*/
369/* Host API
370 *------------------------------------------------------------------*/
371bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
372 (void) rhport;
373 (void) rh_init;
374 KHCI->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
375 while (KHCI->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
376
377 tu_memclr(&_hcd, sizeof(_hcd));
378 KHCI->USBTRC0 |= TU_BIT(6); /* software must set this bit to 1 */
379 KHCI->BDTPAGE1 = (uint8_t)((uintptr_t)_hcd.bdt >> 8);
380 KHCI->BDTPAGE2 = (uint8_t)((uintptr_t)_hcd.bdt >> 16);
381 KHCI->BDTPAGE3 = (uint8_t)((uintptr_t)_hcd.bdt >> 24);
382
383 KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK;
384 KHCI->CTL |= USB_CTL_ODDRST_MASK;
385 for (unsigned i = 0; i < 16; ++i) {
386 KHCI->ENDPOINT[i].ENDPT = 0;
387 }
388 KHCI->CTL &= ~USB_CTL_ODDRST_MASK;
389
390 KHCI->SOFTHLD = 74; /* for 64-byte packets */
391 // KHCI->SOFTHLD = 144; /* for low speed 8-byte packets */
392 KHCI->CTL = USB_CTL_HOSTMODEEN_MASK | USB_CTL_SE0_MASK;
393 KHCI->USBCTRL = USB_USBCTRL_PDE_MASK;
394
395 NVIC_ClearPendingIRQ(USB0_IRQn);
396 KHCI->INTEN = USB_INTEN_ATTACHEN_MASK | USB_INTEN_TOKDNEEN_MASK |
397 USB_INTEN_USBRSTEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK;
398 KHCI->ERREN = 0xff;
399
400 return true;
401}
402
403void hcd_int_enable(uint8_t rhport)
404{
405 (void)rhport;
406 NVIC_EnableIRQ(USB0_IRQn);
407}
408
409void hcd_int_disable(uint8_t rhport)
410{
411 (void)rhport;
412 NVIC_DisableIRQ(USB0_IRQn);
413}
414
415uint32_t hcd_frame_number(uint8_t rhport)
416{
417 (void)rhport;
418 /* The device must be reset at least once after connection
419 * in order to start the frame counter. */
420 if (_hcd.need_reset) hcd_port_reset(rhport);
421 uint32_t frmnum = KHCI->FRMNUML;
422 frmnum |= KHCI->FRMNUMH << 8u;
423 return frmnum;
424}
425
426/*--------------------------------------------------------------------+
427 * Port API
428 *--------------------------------------------------------------------+ */
429bool hcd_port_connect_status(uint8_t rhport)
430{
431 (void)rhport;
432 if (KHCI->ISTAT & USB_ISTAT_ATTACH_MASK)
433 return true;
434 return false;
435}
436
437void hcd_port_reset(uint8_t rhport)
438{
439 (void)rhport;
440 KHCI->CTL &= ~USB_CTL_USBENSOFEN_MASK;
441 KHCI->CTL |= USB_CTL_RESET_MASK;
442 unsigned cnt = SystemCoreClock / 100;
443 while (cnt--) __NOP();
444 KHCI->CTL &= ~USB_CTL_RESET_MASK;
445 KHCI->CTL |= USB_CTL_USBENSOFEN_MASK;
446 _hcd.need_reset = false;
447}
448
449void hcd_port_reset_end(uint8_t rhport) {
450 (void) rhport;
451}
452
454{
455 (void)rhport;
457 const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
458 NVIC_DisableIRQ(USB0_IRQn);
459 if (KHCI->ADDR & USB_ADDR_LSEN_MASK)
460 speed = TUSB_SPEED_LOW;
461 if (ie) NVIC_EnableIRQ(USB0_IRQn);
462 return speed;
463}
464
465void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
466{
467 (void)rhport;
468 const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
469 NVIC_DisableIRQ(USB0_IRQn);
470 pipe_state_t *p = &_hcd.pipe[0];
471 pipe_state_t *end = &_hcd.pipe[CFG_TUH_ENDPOINT_MAX * 2];
472 for (;p != end; ++p) {
473 if (p->dev_addr == dev_addr)
474 tu_memclr(p, sizeof(*p));
475 }
476 if (ie) NVIC_EnableIRQ(USB0_IRQn);
477}
478
479//--------------------------------------------------------------------+
480// Endpoints API
481//--------------------------------------------------------------------+
482bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
483{
484 (void)rhport;
485 // TU_LOG1("SETUP %u\r\n", dev_addr);
486 TU_ASSERT(0 == (_hcd.in_progress & TU_BIT(0)));
487
488 int pipenum = find_pipe(dev_addr, 0);
489 if (pipenum < 0) return false;
490
491 pipe_state_t *pipe = &_hcd.pipe[pipenum];
492 pipe[0].data = 0;
493 pipe[0].buffer = (uint8_t*)(uintptr_t)setup_packet;
494 pipe[0].length = 8;
495 pipe[0].remaining = 8;
496 pipe[1].data = 1;
497
498 if (1 != prepare_packets(pipenum))
499 return false;
500
501 _hcd.in_progress |= TU_BIT(pipenum);
502
503 unsigned hostwohub = KHCI->ENDPOINT[0].ENDPT & USB_ENDPT_HOSTWOHUB_MASK;
504 KHCI->ENDPOINT[0].ENDPT = hostwohub |
505 USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK;
506 KHCI->ADDR = (KHCI->ADDR & USB_ADDR_LSEN_MASK) | dev_addr;
507 while (KHCI->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) ;
508 KHCI->TOKEN = (TOK_PID_SETUP << USB_TOKEN_TOKENPID_SHIFT);
509 return true;
510}
511
512bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
513{
514 (void)rhport;
515 uint8_t const ep_addr = ep_desc->bEndpointAddress;
516 // TU_LOG1("O %u %x\r\n", dev_addr, ep_addr);
517 /* Find a free pipe */
518 pipe_state_t *p = &_hcd.pipe[0];
519 pipe_state_t *end = &_hcd.pipe[CFG_TUH_ENDPOINT_MAX * 2];
520 if (dev_addr || ep_addr) {
521 p += 2;
522 for (; p < end && (p->dev_addr || p->ep_addr); ++p) ;
523 if (p == end) return false;
524 }
525 p->dev_addr = dev_addr;
526 p->ep_addr = ep_addr;
527 p->max_packet_size = ep_desc->wMaxPacketSize;
528 p->xfer = ep_desc->bmAttributes.xfer;
529 p->data = 0;
530 if (!ep_addr) {
531 /* Open one more pipe for Control IN transfer */
532 TU_ASSERT(TUSB_XFER_CONTROL == p->xfer);
533 pipe_state_t *q = p + 1;
534 TU_ASSERT(!q->dev_addr && !q->ep_addr);
535 q->dev_addr = dev_addr;
536 q->ep_addr = tu_edpt_addr(0, TUSB_DIR_IN);
537 q->max_packet_size = ep_desc->wMaxPacketSize;
538 q->xfer = ep_desc->bmAttributes.xfer;
539 q->data = 1;
540 }
541 return true;
542}
543
544/* The address of buffer must be aligned to 4 byte boundary. And it must be at least 4 bytes long.
545 * DMA writes data in 4 byte unit */
546bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
547{
548 (void)rhport;
549 // TU_LOG1("X %u %x %x %d\r\n", dev_addr, ep_addr, (uintptr_t)buffer, buflen);
550
551 int pipenum = find_pipe(dev_addr, ep_addr);
552 TU_ASSERT(0 <= pipenum);
553
554 TU_ASSERT(0 == (_hcd.in_progress & TU_BIT(pipenum)));
555 unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
556 NVIC_DisableIRQ(USB0_IRQn);
557 pipe_state_t *pipe = &_hcd.pipe[pipenum];
558 pipe->buffer = buffer;
559 pipe->length = buflen;
560 pipe->remaining = buflen;
561 _hcd.in_progress |= TU_BIT(pipenum);
562 _hcd.pending |= TU_BIT(pipenum); /* Send at the next Frame */
563 KHCI->INTEN |= USB_ISTAT_SOFTOK_MASK;
564 if (ie) NVIC_EnableIRQ(USB0_IRQn);
565 return true;
566}
567
568bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
569 (void) rhport;
570 (void) dev_addr;
571 (void) ep_addr;
572 // TODO not implemented yet
573 return false;
574}
575
576bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
577 (void) rhport;
578 if (!tu_edpt_number(ep_addr)) return true;
579 int num = find_pipe(dev_addr, ep_addr);
580 if (num < 0) return false;
581 pipe_state_t *p = &_hcd.pipe[num];
582 p->data = 0; /* Reset data toggle */
583 return true;
584}
585
586/*--------------------------------------------------------------------+
587 * ISR
588 *--------------------------------------------------------------------+*/
589void hcd_int_handler(uint8_t rhport, bool in_isr)
590{
591 (void) in_isr;
592 uint32_t is = KHCI->ISTAT;
593 uint32_t msk = KHCI->INTEN;
594
595 // TU_LOG1("S %lx\r\n", is);
596
597 /* clear disabled interrupts */
598 KHCI->ISTAT = (is & ~msk & ~USB_ISTAT_TOKDNE_MASK) | USB_ISTAT_SOFTOK_MASK;
599 is &= msk;
600
601 if (is & USB_ISTAT_ERROR_MASK) {
602 unsigned err = KHCI->ERRSTAT;
603 if (err) {
604 TU_LOG1(" ERR %x\r\n", err);
605 KHCI->ERRSTAT = err;
606 } else {
607 KHCI->INTEN &= ~USB_ISTAT_ERROR_MASK;
608 }
609 }
610
611 if (is & USB_ISTAT_USBRST_MASK) {
612 KHCI->INTEN = (msk & ~USB_INTEN_USBRSTEN_MASK) | USB_INTEN_ATTACHEN_MASK;
613 process_bus_reset(rhport);
614 return;
615 }
616 if (is & USB_ISTAT_ATTACH_MASK) {
617 KHCI->INTEN = (msk & ~USB_INTEN_ATTACHEN_MASK) | USB_INTEN_USBRSTEN_MASK;
618 _hcd.need_reset = true;
619 process_attach(rhport);
620 return;
621 }
622 if (is & USB_ISTAT_STALL_MASK) {
623 KHCI->ISTAT = USB_ISTAT_STALL_MASK;
624 }
625 if (is & USB_ISTAT_SOFTOK_MASK) {
626 msk &= ~USB_ISTAT_SOFTOK_MASK;
627 KHCI->INTEN = msk;
628 if (_hcd.pending) {
629 int pipenum = __builtin_ctz(_hcd.pending);
630 _hcd.pending = 0;
631 if (!(is & USB_ISTAT_TOKDNE_MASK))
632 resume_transfer(pipenum);
633 }
634 }
635 if (is & USB_ISTAT_TOKDNE_MASK) {
636 process_tokdne(rhport);
637 }
638}
639
640#endif
u32 SystemCoreClock
static bool in_isr
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
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
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
Definition: hcd_khci.c:482
CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(512)
Definition: hcd_khci.c:140
struct TU_ATTR_PACKED pipe_state_t
void hcd_int_disable(uint8_t rhport)
Definition: hcd_khci.c:409
static void process_attach(uint8_t rhport)
Definition: hcd_khci.c:339
static int prepare_packets(int pipenum)
Definition: hcd_khci.c:155
@ TOK_PID_DATA0
Definition: hcd_khci.c:48
@ TOK_PID_ERR
Definition: hcd_khci.c:54
@ TOK_PID_SETUP
Definition: hcd_khci.c:47
@ TOK_PID_NAK
Definition: hcd_khci.c:52
@ TOK_PID_ACK
Definition: hcd_khci.c:50
@ TOK_PID_BUSTO
Definition: hcd_khci.c:53
@ TOK_PID_STALL
Definition: hcd_khci.c:51
@ TOK_PID_IN
Definition: hcd_khci.c:46
@ TOK_PID_OUT
Definition: hcd_khci.c:45
@ TOK_PID_DATA1
Definition: hcd_khci.c:49
static void process_bus_reset(uint8_t rhport)
Definition: hcd_khci.c:350
struct TU_ATTR_PACKED endpoint_state_t
static int select_next_pipenum(int pipenum)
Definition: hcd_khci.c:192
static void suspend_transfer(int pipenum, buffer_descriptor_t *bd)
Definition: hcd_khci.c:269
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_khci.c:576
void hcd_int_enable(uint8_t rhport)
Definition: hcd_khci.c:403
static void process_tokdne(uint8_t rhport)
Definition: hcd_khci.c:281
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
Definition: hcd_khci.c:546
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
Definition: hcd_khci.c:465
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
Definition: hcd_khci.c:568
void hcd_port_reset_end(uint8_t rhport)
Definition: hcd_khci.c:449
TU_VERIFY_STATIC(sizeof(buffer_descriptor_t)==8, "size is not correct")
void hcd_port_reset(uint8_t rhport)
Definition: hcd_khci.c:437
bool hcd_port_connect_status(uint8_t rhport)
Definition: hcd_khci.c:429
uint32_t hcd_frame_number(uint8_t rhport)
Definition: hcd_khci.c:415
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
Definition: hcd_khci.c:453
struct TU_ATTR_PACKED buffer_descriptor_t
void hcd_int_handler(uint8_t rhport, bool in_isr)
Definition: hcd_khci.c:589
static bool resume_transfer(int pipenum)
Definition: hcd_khci.c:232
static bool continue_transfer(int pipenum, buffer_descriptor_t *bd)
Definition: hcd_khci.c:205
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
Definition: hcd_khci.c:371
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc)
Definition: hcd_khci.c:512
static unsigned find_pipe(uint_fast8_t dev_addr, uint_fast8_t ep_addr)
Definition: hcd_musb.c:226
static hcd_data_t _hcd
Definition: hcd_musb.c:120
uint8_t const * buffer
Definition: midi_device.h:100
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
__IO uint16_t tok_pid
Definition: dcd_ci_fs.c:60
uint8_t * addr
Definition: dcd_ci_fs.c:78
uint16_t ninc
Definition: dcd_ci_fs.c:69
uint16_t bdt_stall
Definition: dcd_ci_fs.c:67
uint8_t ep_addr
Definition: hcd_khci.c:106
uint16_t dts
Definition: dcd_ci_fs.c:68
uint16_t max_packet_size
Definition: hcd_khci.c:107
uint16_t wMaxPacketSize
Definition: tusb_types.h:371
__IO uint16_t bc
Definition: dcd_ci_fs.c:74
uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]
Definition: ncm.h:147
uint8_t dev_addr
Definition: hcd_khci.c:105
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint16_t length
Definition: dcd_ci_fs.c:94
volatile uint16_t
Definition: hcd_rusb2.c:58
uint32_t odd
Definition: dcd_ci_fs.c:90
uint8_t * buffer
Definition: video_device.c:111
uint32_t pipenum
Definition: hcd_khci.c:93
uint16_t keep
Definition: dcd_ci_fs.c:70
uint16_t remaining
Definition: dcd_ci_fs.c:95
uint8_t xfer
Definition: hcd_khci.c:112
__IO uint16_t own
Definition: dcd_ci_fs.c:62
uint8_t bEndpointAddress
Definition: video.h:306
uint32_t head
Definition: dcd_ci_fs.c:55
uint8_t flags
Definition: hcd_khci.c:109
endpoint_state_t endpoint[2]
Definition: hcd_khci.c:129
uint32_t in_progress
Definition: hcd_khci.c:131
uint16_t bda[2 *2]
Definition: hcd_khci.c:127
uint32_t pending
Definition: hcd_khci.c:132
buffer_descriptor_t bdt[2][2]
Definition: hcd_khci.c:126
bool need_reset
Definition: hcd_musb.c:109
pipe_state_t pipe[7][2]
Definition: hcd_musb.c:113
uint16_t length
Definition: dcd_rusb2.c:62
uint16_t remaining
Definition: dcd_rusb2.c:63
@ TUSB_DIR_IN
Definition: tusb_types.h:67
@ 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_FULL
Definition: tusb_types.h:50
@ TUSB_SPEED_LOW
Definition: tusb_types.h:51
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
@ TUSB_XFER_CONTROL
Definition: tusb_types.h:59
@ 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