pio_usb_host.c
1 /** 2 * Copyright (c) 2021 sekigon-gonnoc 3 * Ha Thach (thach@tinyusb.org) 4 */ 5 6 #pragma GCC push_options 7 #pragma GCC optimize("-O3") 8 9 #include <stdbool.h> 10 #include <stdint.h> 11 #include <stdio.h> 12 #include <string.h> 13 14 #include "hardware/sync.h" 15 #include "hardware/pio.h" 16 #include "hardware/gpio.h" 17 18 #include "pio_usb.h" 19 #include "pio_usb_ll.h" 20 #include "usb_crc.h" 21 #include "usb_rx.pio.h" 22 #include "usb_tx.pio.h" 23 24 static alarm_pool_t *_alarm_pool = NULL; 25 static repeating_timer_t sof_rt; 26 // The sof_count may be incremented and then read on different cores. 27 static volatile uint32_t sof_count = 0; 28 static bool timer_active; 29 30 static volatile bool cancel_timer_flag; 31 static volatile bool start_timer_flag; 32 static __unused uint32_t int_stat; 33 static uint8_t sof_packet[4] = {USB_SYNC, USB_PID_SOF, 0x00, 0x10}; 34 static uint8_t sof_packet_encoded[4 * 2 * 7 / 6 + 2]; 35 static uint8_t sof_packet_encoded_len; 36 37 static bool sof_timer(repeating_timer_t *_rt); 38 39 //--------------------------------------------------------------------+ 40 // Application API 41 //--------------------------------------------------------------------+ 42 43 static void start_timer(alarm_pool_t *alarm_pool) { 44 if (timer_active) { 45 return; 46 } 47 48 if (alarm_pool != NULL) { 49 alarm_pool_add_repeating_timer_us(alarm_pool, -1000, sof_timer, NULL, 50 &sof_rt); 51 } 52 53 timer_active = true; 54 } 55 56 static __unused void stop_timer(void) { 57 cancel_repeating_timer(&sof_rt); 58 timer_active = false; 59 } 60 61 usb_device_t *pio_usb_host_init(const pio_usb_configuration_t *c) { 62 pio_port_t *pp = PIO_USB_PIO_PORT(0); 63 root_port_t *root = PIO_USB_ROOT_PORT(0); 64 65 pio_usb_bus_init(pp, c, root); 66 root->mode = PIO_USB_MODE_HOST; 67 68 float const cpu_freq = (float)clock_get_hz(clk_sys); 69 pio_calculate_clkdiv_from_float(cpu_freq / 48000000, 70 &pp->clk_div_fs_tx.div_int, 71 &pp->clk_div_fs_tx.div_frac); 72 pio_calculate_clkdiv_from_float(cpu_freq / 6000000, 73 &pp->clk_div_ls_tx.div_int, 74 &pp->clk_div_ls_tx.div_frac); 75 76 pio_calculate_clkdiv_from_float(cpu_freq / 96000000, 77 &pp->clk_div_fs_rx.div_int, 78 &pp->clk_div_fs_rx.div_frac); 79 pio_calculate_clkdiv_from_float(cpu_freq / 12000000, 80 &pp->clk_div_ls_rx.div_int, 81 &pp->clk_div_ls_rx.div_frac); 82 83 sof_packet_encoded_len = 84 pio_usb_ll_encode_tx_data(sof_packet, sizeof(sof_packet), sof_packet_encoded); 85 86 if (!c->skip_alarm_pool) { 87 _alarm_pool = c->alarm_pool; 88 if (!_alarm_pool) { 89 _alarm_pool = alarm_pool_create(2, 1); 90 } 91 } 92 start_timer(_alarm_pool); 93 94 return &pio_usb_device[0]; 95 } 96 97 void pio_usb_host_stop(void) { 98 cancel_timer_flag = true; 99 while (cancel_timer_flag) { 100 continue; 101 } 102 } 103 104 void pio_usb_host_restart(void) { 105 start_timer_flag = true; 106 while (start_timer_flag) { 107 continue; 108 } 109 } 110 111 //--------------------------------------------------------------------+ 112 // Bus functions 113 //--------------------------------------------------------------------+ 114 115 static void __no_inline_not_in_flash_func(override_pio_program)(PIO pio, const pio_program_t* program, uint offset) { 116 for (uint i = 0; i < program->length; ++i) { 117 uint16_t instr = program->instructions[i]; 118 pio->instr_mem[offset + i] = 119 pio_instr_bits_jmp != _pio_major_instr_bits(instr) ? instr 120 : instr + offset; 121 } 122 } 123 124 static __always_inline void override_pio_rx_program(PIO pio, 125 const pio_program_t *program, 126 const pio_program_t *debug_program, 127 uint offset, int debug_pin) { 128 if (debug_pin < 0) { 129 override_pio_program(pio, program, offset); 130 } else { 131 override_pio_program(pio, debug_program, offset); 132 } 133 } 134 135 static void 136 __no_inline_not_in_flash_func(configure_tx_program)(pio_port_t *pp, 137 root_port_t *port) { 138 if (port->pinout == PIO_USB_PINOUT_DPDM) { 139 pp->fs_tx_program = &usb_tx_dpdm_program; 140 pp->fs_tx_pre_program = &usb_tx_pre_dpdm_program; 141 pp->ls_tx_program = &usb_tx_dmdp_program; 142 } else { 143 pp->fs_tx_program = &usb_tx_dmdp_program; 144 pp->fs_tx_pre_program = &usb_tx_pre_dmdp_program; 145 pp->ls_tx_program = &usb_tx_dpdm_program; 146 } 147 } 148 149 static void __no_inline_not_in_flash_func(configure_fullspeed_host)( 150 pio_port_t *pp, root_port_t *port) { 151 configure_tx_program(pp, port); 152 pio_sm_clear_fifos(pp->pio_usb_tx, pp->sm_tx); 153 override_pio_program(pp->pio_usb_tx, pp->fs_tx_program, pp->offset_tx); 154 SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_fs_tx); 155 usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp, port->pin_dm); 156 pio_sm_exec(pp->pio_usb_tx, pp->sm_tx, pp->tx_reset_instr); 157 158 pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_rx, port->pin_dp); 159 SM_SET_CLKDIV_MAXSPEED(pp->pio_usb_rx, pp->sm_rx); 160 161 pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_eop, port->pin_dm); 162 pio_sm_set_in_pins(pp->pio_usb_rx, pp->sm_eop, port->pin_dp); 163 SM_SET_CLKDIV(pp->pio_usb_rx, pp->sm_eop, pp->clk_div_fs_rx); 164 } 165 166 static void __no_inline_not_in_flash_func(configure_lowspeed_host)( 167 pio_port_t *pp, root_port_t *port) { 168 configure_tx_program(pp, port); 169 pio_sm_clear_fifos(pp->pio_usb_tx, pp->sm_tx); 170 override_pio_program(pp->pio_usb_tx, pp->ls_tx_program, pp->offset_tx); 171 SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_ls_tx); 172 usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp, port->pin_dm); 173 pio_sm_exec(pp->pio_usb_tx, pp->sm_tx, pp->tx_reset_instr); 174 175 pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_rx, port->pin_dm); 176 SM_SET_CLKDIV_MAXSPEED(pp->pio_usb_rx, pp->sm_rx); 177 178 pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_eop, port->pin_dp); 179 pio_sm_set_in_pins(pp->pio_usb_rx, pp->sm_eop, port->pin_dm); 180 SM_SET_CLKDIV(pp->pio_usb_rx, pp->sm_eop, pp->clk_div_ls_rx); 181 } 182 183 static void __no_inline_not_in_flash_func(configure_root_port)( 184 pio_port_t *pp, root_port_t *root) { 185 if (root->is_fullspeed) { 186 configure_fullspeed_host(pp, root); 187 } else { 188 configure_lowspeed_host(pp, root); 189 } 190 } 191 192 static void __no_inline_not_in_flash_func(restore_fs_bus)(const pio_port_t *pp) { 193 // change bus speed to full-speed 194 pio_sm_set_enabled(pp->pio_usb_tx, pp->sm_tx, false); 195 SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_fs_tx); 196 pio_sm_set_enabled(pp->pio_usb_tx, pp->sm_tx, true); 197 198 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, false); 199 SM_SET_CLKDIV_MAXSPEED(pp->pio_usb_rx, pp->sm_rx); 200 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, true); 201 202 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_eop, false); 203 SM_SET_CLKDIV(pp->pio_usb_rx, pp->sm_eop, pp->clk_div_fs_rx); 204 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_eop, true); 205 } 206 207 // Time about 1us ourselves so it lives in RAM. 208 static void __not_in_flash_func(busy_wait_1_us)(void) { 209 uint32_t start = timer_hw->timerawl; 210 while (timer_hw->timerawl == start) { 211 tight_loop_contents(); 212 } 213 } 214 215 static bool __no_inline_not_in_flash_func(connection_check)(root_port_t *port) { 216 if (pio_usb_bus_get_line_state(port) == PORT_PIN_SE0) { 217 busy_wait_1_us(); 218 219 if (pio_usb_bus_get_line_state(port) == PORT_PIN_SE0) { 220 busy_wait_1_us(); 221 // device disconnect 222 port->connected = false; 223 port->suspended = true; 224 port->ints |= PIO_USB_INTS_DISCONNECT_BITS; 225 226 // failed/retired all queuing transfer in this root 227 uint8_t root_idx = port - PIO_USB_ROOT_PORT(0); 228 for (int ep_idx = 0; ep_idx < PIO_USB_EP_POOL_CNT; ep_idx++) { 229 endpoint_t *ep = PIO_USB_ENDPOINT(ep_idx); 230 if ((ep->root_idx == root_idx) && ep->size && ep->has_transfer) { 231 pio_usb_ll_transfer_complete(ep, PIO_USB_INTS_ENDPOINT_ERROR_BITS); 232 } 233 } 234 235 return false; 236 } 237 } 238 239 return true; 240 } 241 242 //--------------------------------------------------------------------+ 243 // SOF 244 //--------------------------------------------------------------------+ 245 static int usb_setup_transaction(pio_port_t *pp, endpoint_t *ep); 246 static int usb_in_transaction(pio_port_t *pp, endpoint_t *ep); 247 static int usb_out_transaction(pio_port_t *pp, endpoint_t *ep); 248 249 void __not_in_flash_func(pio_usb_host_frame)(void) { 250 if (!timer_active) { 251 return; 252 } 253 254 pio_port_t *pp = PIO_USB_PIO_PORT(0); 255 256 // Send SOF 257 for (int root_idx = 0; root_idx < PIO_USB_ROOT_PORT_CNT; root_idx++) { 258 root_port_t *root = PIO_USB_ROOT_PORT(root_idx); 259 if (!(root->initialized && root->connected && !root->suspended && 260 connection_check(root))) { 261 continue; 262 } 263 configure_root_port(pp, root); 264 pio_usb_bus_usb_transfer(pp, sof_packet_encoded, sof_packet_encoded_len); 265 } 266 267 // Carry out all queued endpoint transaction 268 for (int root_idx = 0; root_idx < PIO_USB_ROOT_PORT_CNT; root_idx++) { 269 root_port_t *root = PIO_USB_ROOT_PORT(root_idx); 270 if (!(root->initialized && root->connected && !root->suspended)) { 271 continue; 272 } 273 274 configure_root_port(pp, root); 275 276 for (int ep_pool_idx = 0; ep_pool_idx < PIO_USB_EP_POOL_CNT; 277 ep_pool_idx++) { 278 endpoint_t *ep = PIO_USB_ENDPOINT(ep_pool_idx); 279 if ((ep->root_idx == root_idx) && ep->size) { 280 bool const is_periodic = ((ep->attr & 0x03) == EP_ATTR_INTERRUPT); 281 282 if (is_periodic && (ep->interval_counter > 0)) { 283 ep->interval_counter--; 284 continue; 285 } 286 287 if (ep->has_transfer && !ep->transfer_aborted) { 288 ep->transfer_started = true; 289 290 if (ep->need_pre) { 291 pp->need_pre = true; 292 } 293 294 if (ep->ep_num == 0 && ep->data_id == USB_PID_SETUP) { 295 usb_setup_transaction(pp, ep); 296 } else { 297 if (ep->ep_num & EP_IN) { 298 usb_in_transaction(pp, ep); 299 } else { 300 usb_out_transaction(pp, ep); 301 } 302 303 if (is_periodic) { 304 ep->interval_counter = ep->interval - 1; 305 } 306 } 307 308 if (ep->need_pre) { 309 pp->need_pre = false; 310 restore_fs_bus(pp); 311 } 312 313 ep->transfer_started = false; 314 } 315 } 316 } 317 } 318 319 // check for new connection to root hub 320 for (int root_idx = 0; root_idx < PIO_USB_ROOT_PORT_CNT; root_idx++) { 321 root_port_t *root = PIO_USB_ROOT_PORT(root_idx); 322 if (root->initialized && !root->connected) { 323 port_pin_status_t const line_state = pio_usb_bus_get_line_state(root); 324 if (line_state == PORT_PIN_FS_IDLE || line_state == PORT_PIN_LS_IDLE) { 325 root->is_fullspeed = (line_state == PORT_PIN_FS_IDLE); 326 root->connected = true; 327 root->suspended = true; // need a bus reset before operating 328 root->ints |= PIO_USB_INTS_CONNECT_BITS; 329 } 330 } 331 } 332 333 // Invoke IRQHandler if interrupt status is set 334 for (uint8_t root_idx = 0; root_idx < PIO_USB_ROOT_PORT_CNT; root_idx++) { 335 if (PIO_USB_ROOT_PORT(root_idx)->ints) { 336 pio_usb_host_irq_handler(root_idx); 337 } 338 } 339 340 sof_count++; 341 342 // SOF counter is 11-bit 343 uint16_t const sof_count_11b = sof_count & 0x7ff; 344 sof_packet[2] = sof_count_11b & 0xff; 345 sof_packet[3] = (calc_usb_crc5(sof_count_11b) << 3) | (sof_count_11b >> 8); 346 sof_packet_encoded_len = 347 pio_usb_ll_encode_tx_data(sof_packet, sizeof(sof_packet), sof_packet_encoded); 348 } 349 350 static bool __no_inline_not_in_flash_func(sof_timer)(repeating_timer_t *_rt) { 351 (void)_rt; 352 353 pio_usb_host_frame(); 354 355 return true; 356 } 357 358 //--------------------------------------------------------------------+ 359 // Host Controller functions 360 //--------------------------------------------------------------------+ 361 362 uint32_t pio_usb_host_get_frame_number(void) { 363 return sof_count; 364 } 365 366 void pio_usb_host_port_reset_start(uint8_t root_idx) { 367 root_port_t *root = PIO_USB_ROOT_PORT(root_idx); 368 369 // bus is not operating while in reset 370 root->suspended = true; 371 372 // Force line state to SE0 373 gpio_set_outover(root->pin_dp, GPIO_OVERRIDE_LOW); 374 gpio_set_outover(root->pin_dm, GPIO_OVERRIDE_LOW); 375 gpio_set_oeover(root->pin_dp, GPIO_OVERRIDE_HIGH); 376 gpio_set_oeover(root->pin_dm, GPIO_OVERRIDE_HIGH); 377 } 378 379 void pio_usb_host_port_reset_end(uint8_t root_idx) { 380 root_port_t *root = PIO_USB_ROOT_PORT(root_idx); 381 382 // line state to input 383 gpio_set_oeover(root->pin_dp, GPIO_OVERRIDE_NORMAL); 384 gpio_set_oeover(root->pin_dm, GPIO_OVERRIDE_NORMAL); 385 gpio_set_outover(root->pin_dp, GPIO_OVERRIDE_NORMAL); 386 gpio_set_outover(root->pin_dm, GPIO_OVERRIDE_NORMAL); 387 busy_wait_us(100); // TODO check if this is neccessary 388 389 // bus back to operating 390 root->suspended = false; 391 } 392 393 void pio_usb_host_close_device(uint8_t root_idx, uint8_t device_address) { 394 for (int ep_pool_idx = 0; ep_pool_idx < PIO_USB_EP_POOL_CNT; ep_pool_idx++) { 395 endpoint_t *ep = PIO_USB_ENDPOINT(ep_pool_idx); 396 if ((ep->root_idx == root_idx) && (ep->dev_addr == device_address) && 397 ep->size) { 398 ep->size = 0; 399 ep->has_transfer = false; 400 } 401 } 402 } 403 404 static inline __force_inline endpoint_t * _find_ep(uint8_t root_idx, 405 uint8_t device_address, uint8_t ep_address) { 406 for (int ep_pool_idx = 0; ep_pool_idx < PIO_USB_EP_POOL_CNT; ep_pool_idx++) { 407 endpoint_t *ep = PIO_USB_ENDPOINT(ep_pool_idx); 408 // note 0x00 and 0x80 are matched as control endpoint of opposite direction 409 if ((ep->root_idx == root_idx) && (ep->dev_addr == device_address) && 410 ep->size && 411 ((ep->ep_num == ep_address) || 412 (((ep_address & 0x7f) == 0) && ((ep->ep_num & 0x7f) == 0)))) { 413 return ep; 414 } 415 } 416 417 return NULL; 418 } 419 420 bool pio_usb_host_endpoint_open(uint8_t root_idx, uint8_t device_address, 421 uint8_t const *desc_endpoint, bool need_pre) { 422 const endpoint_descriptor_t *d = (const endpoint_descriptor_t *)desc_endpoint; 423 for (int ep_pool_idx = 0; ep_pool_idx < PIO_USB_EP_POOL_CNT; ep_pool_idx++) { 424 endpoint_t *ep = PIO_USB_ENDPOINT(ep_pool_idx); 425 // ep size is used as valid indicator 426 if (ep->size == 0) { 427 pio_usb_ll_configure_endpoint(ep, desc_endpoint); 428 ep->root_idx = root_idx; 429 ep->dev_addr = device_address; 430 ep->need_pre = need_pre; 431 ep->is_tx = (d->epaddr & 0x80) ? false : true; // host endpoint out is tx 432 return true; 433 } 434 } 435 436 return false; 437 } 438 439 bool pio_usb_host_send_setup(uint8_t root_idx, uint8_t device_address, 440 uint8_t const setup_packet[8]) { 441 endpoint_t *ep = _find_ep(root_idx, device_address, 0); 442 if (!ep) { 443 printf("cannot find ep 0x00\r\n"); 444 return false; 445 } 446 447 ep->ep_num = 0; // setup is is OUT 448 ep->data_id = USB_PID_SETUP; 449 ep->is_tx = true; 450 451 return pio_usb_ll_transfer_start(ep, (uint8_t *)setup_packet, 8); 452 } 453 454 bool pio_usb_host_endpoint_transfer(uint8_t root_idx, uint8_t device_address, 455 uint8_t ep_address, uint8_t *buffer, 456 uint16_t buflen) { 457 endpoint_t *ep = _find_ep(root_idx, device_address, ep_address); 458 if (!ep) { 459 printf("no endpoint 0x%02X\r\n", ep_address); 460 return false; 461 } 462 463 // Control endpoint, address may switch between 0x00 <-> 0x80 464 // therefore we need to update ep_num and is_tx 465 if ((ep_address & 0x7f) == 0) { 466 ep->ep_num = ep_address; 467 ep->is_tx = ep_address == 0; 468 ep->data_id = 1; // data and status always start with DATA1 469 } 470 471 return pio_usb_ll_transfer_start(ep, buffer, buflen); 472 } 473 474 bool pio_usb_host_endpoint_abort_transfer(uint8_t root_idx, uint8_t device_address, 475 uint8_t ep_address) { 476 endpoint_t *ep = _find_ep(root_idx, device_address, ep_address); 477 if (!ep) { 478 printf("no endpoint 0x%02X\r\n", ep_address); 479 return false; 480 } 481 482 if (!ep->has_transfer) { 483 return false; // no transfer to abort 484 } 485 486 // mark transfer as aborted 487 ep->transfer_aborted = true; 488 489 // Race potential: SOF timer can be called before transfer_aborted is actually set 490 // and started the transfer. Wait 1 usb frame for transaction to complete. 491 // On the next SOF timer, transfer_aborted will be checked and skipped 492 while (ep->has_transfer && ep->transfer_started) { 493 busy_wait_ms(1); 494 } 495 496 // check if transfer is still active (could be completed) 497 bool const still_active = ep->has_transfer; 498 if (still_active) { 499 ep->has_transfer = false; 500 } 501 ep->transfer_aborted = false; 502 503 return still_active; // still active means transfer is successfully aborted 504 } 505 506 //--------------------------------------------------------------------+ 507 // Transaction helper 508 //--------------------------------------------------------------------+ 509 510 static int __no_inline_not_in_flash_func(usb_in_transaction)(pio_port_t *pp, 511 endpoint_t *ep) { 512 int res = 0; 513 uint8_t expect_pid = (ep->data_id == 1) ? USB_PID_DATA1 : USB_PID_DATA0; 514 515 pio_usb_bus_prepare_receive(pp); 516 pio_usb_bus_send_token(pp, USB_PID_IN, ep->dev_addr, ep->ep_num); 517 pio_usb_bus_start_receive(pp); 518 519 int receive_len = pio_usb_bus_receive_packet_and_handshake(pp, USB_PID_ACK); 520 uint8_t const receive_pid = pp->usb_rx_buffer[1]; 521 522 if (receive_len >= 0) { 523 if (receive_pid == expect_pid) { 524 memcpy(ep->app_buf, &pp->usb_rx_buffer[2], receive_len); 525 pio_usb_ll_transfer_continue(ep, receive_len); 526 } else { 527 // DATA0/1 mismatched, 0 for re-try next frame 528 } 529 } else if (receive_pid == USB_PID_NAK) { 530 // NAK try again next frame 531 } else if (receive_pid == USB_PID_STALL) { 532 pio_usb_ll_transfer_complete(ep, PIO_USB_INTS_ENDPOINT_STALLED_BITS); 533 } else { 534 res = -1; 535 if ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0) { 536 res = -2; 537 } 538 pio_usb_ll_transfer_complete(ep, PIO_USB_INTS_ENDPOINT_ERROR_BITS); 539 } 540 541 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, false); 542 pp->usb_rx_buffer[0] = 0; 543 pp->usb_rx_buffer[1] = 0; 544 545 return res; 546 } 547 548 static int __no_inline_not_in_flash_func(usb_out_transaction)(pio_port_t *pp, 549 endpoint_t *ep) { 550 int res = 0; 551 552 uint16_t const xact_len = pio_usb_ll_get_transaction_len(ep); 553 554 pio_usb_bus_prepare_receive(pp); 555 pio_usb_bus_send_token(pp, USB_PID_OUT, ep->dev_addr, ep->ep_num); 556 557 pio_usb_bus_usb_transfer(pp, ep->buffer, ep->encoded_data_len); 558 pio_usb_bus_start_receive(pp); 559 560 pio_usb_bus_wait_handshake(pp); 561 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, false); 562 563 uint8_t const receive_token = pp->usb_rx_buffer[1]; 564 565 if (receive_token == USB_PID_ACK) { 566 pio_usb_ll_transfer_continue(ep, xact_len); 567 } else if (receive_token == USB_PID_NAK) { 568 // NAK try again next frame 569 } else if (receive_token == USB_PID_STALL) { 570 pio_usb_ll_transfer_complete(ep, PIO_USB_INTS_ENDPOINT_STALLED_BITS); 571 } else { 572 pio_usb_ll_transfer_complete(ep, PIO_USB_INTS_ENDPOINT_ERROR_BITS); 573 } 574 575 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, false); 576 pp->usb_rx_buffer[0] = 0; 577 pp->usb_rx_buffer[1] = 0; 578 579 return res; 580 } 581 582 static int __no_inline_not_in_flash_func(usb_setup_transaction)( 583 pio_port_t *pp, endpoint_t *ep) { 584 585 int res = 0; 586 587 // Setup token 588 pio_usb_bus_prepare_receive(pp); 589 590 pio_usb_bus_send_token(pp, USB_PID_SETUP, ep->dev_addr, 0); 591 592 // Data 593 ep->data_id = 0; // set to DATA0 594 pio_usb_bus_usb_transfer(pp, ep->buffer, ep->encoded_data_len); 595 596 // Handshake 597 pio_usb_bus_start_receive(pp); 598 pio_usb_bus_wait_handshake(pp); 599 pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, false); 600 601 ep->actual_len = 8; 602 603 if (pp->usb_rx_buffer[0] == USB_SYNC && pp->usb_rx_buffer[1] == USB_PID_ACK) { 604 pio_usb_ll_transfer_complete(ep, PIO_USB_INTS_ENDPOINT_COMPLETE_BITS); 605 } else { 606 res = -1; 607 pio_usb_ll_transfer_complete(ep, PIO_USB_INTS_ENDPOINT_ERROR_BITS); 608 } 609 610 pp->usb_rx_buffer[1] = 0; // reset buffer 611 612 return res; 613 } 614 615 616 static void __no_inline_not_in_flash_func(handle_endpoint_irq)( 617 root_port_t *root, uint32_t flag, volatile uint32_t *ep_reg) { 618 (void)root; 619 const uint32_t ep_all = *ep_reg; 620 621 for (uint8_t ep_idx = 0; ep_idx < PIO_USB_EP_POOL_CNT; ep_idx++) { 622 if (ep_all & (1u << ep_idx)) { 623 endpoint_t *ep = PIO_USB_ENDPOINT(ep_idx); 624 usb_device_t *device = NULL; 625 626 // find device this endpoint belongs to 627 for (int idx = 0; idx < PIO_USB_DEVICE_CNT; idx++) { 628 usb_device_t *dev = &pio_usb_device[idx]; 629 if (dev->connected && (ep->dev_addr == dev->address)) { 630 device = dev; 631 break; 632 } 633 } 634 635 if (device) { 636 // control endpoint is either 0x00 or 0x80 637 if ((ep->ep_num & 0x7f) == 0) { 638 control_pipe_t *pipe = &device->control_pipe; 639 640 if (flag != PIO_USB_INTS_ENDPOINT_COMPLETE_BITS) { 641 pipe->stage = STAGE_SETUP; 642 pipe->operation = CONTROL_ERROR; 643 } else { 644 ep->data_id = 1; // both data and status have DATA1 645 if (pipe->stage == STAGE_SETUP) { 646 if (pipe->operation == CONTROL_IN) { 647 pipe->stage = STAGE_IN; 648 ep->ep_num = 0x80; 649 ep->is_tx = false; 650 pio_usb_ll_transfer_start(ep, 651 (uint8_t *)(uintptr_t)pipe->rx_buffer, 652 pipe->request_length); 653 } else if (pipe->operation == CONTROL_OUT) { 654 if (pipe->out_data_packet.tx_address != NULL) { 655 pipe->stage = STAGE_OUT; 656 ep->ep_num = 0x00; 657 ep->is_tx = true; 658 pio_usb_ll_transfer_start(ep, 659 pipe->out_data_packet.tx_address, 660 pipe->out_data_packet.tx_length); 661 } else { 662 pipe->stage = STAGE_STATUS; 663 ep->ep_num = 0x80; 664 ep->is_tx = false; 665 pio_usb_ll_transfer_start(ep, NULL, 0); 666 } 667 } 668 } else if (pipe->stage == STAGE_IN) { 669 pipe->stage = STAGE_STATUS; 670 ep->ep_num = 0x00; 671 ep->is_tx = true; 672 pio_usb_ll_transfer_start(ep, NULL, 0); 673 } else if (pipe->stage == STAGE_OUT) { 674 pipe->stage = STAGE_STATUS; 675 ep->ep_num = 0x80; 676 ep->is_tx = false; 677 pio_usb_ll_transfer_start(ep, NULL, 0); 678 } else if (pipe->stage == STAGE_STATUS) { 679 pipe->stage = STAGE_SETUP; 680 pipe->operation = CONTROL_COMPLETE; 681 } 682 } 683 } else if (device->device_class == CLASS_HUB && (ep->ep_num & EP_IN)) { 684 // hub interrupt endpoint 685 device->event = EVENT_HUB_PORT_CHANGE; 686 } 687 } 688 } 689 } 690 691 // clear all 692 (*ep_reg) &= ~ep_all; 693 } 694 695 // IRQ Handler 696 static void __no_inline_not_in_flash_func(__pio_usb_host_irq_handler)(uint8_t root_id) { 697 root_port_t *root = PIO_USB_ROOT_PORT(root_id); 698 uint32_t const ints = root->ints; 699 700 if (ints & PIO_USB_INTS_CONNECT_BITS) { 701 root->event = EVENT_CONNECT; 702 } 703 704 if (ints & PIO_USB_INTS_DISCONNECT_BITS) { 705 root->event = EVENT_DISCONNECT; 706 } 707 708 if (ints & PIO_USB_INTS_ENDPOINT_COMPLETE_BITS) { 709 handle_endpoint_irq(root, PIO_USB_INTS_ENDPOINT_COMPLETE_BITS, 710 &root->ep_complete); 711 } 712 713 if (ints & PIO_USB_INTS_ENDPOINT_STALLED_BITS) { 714 handle_endpoint_irq(root, PIO_USB_INTS_ENDPOINT_STALLED_BITS, 715 &root->ep_stalled); 716 } 717 718 if (ints & PIO_USB_INTS_ENDPOINT_ERROR_BITS) { 719 handle_endpoint_irq(root, PIO_USB_INTS_ENDPOINT_ERROR_BITS, 720 &root->ep_error); 721 } 722 723 // clear all 724 root->ints &= ~ints; 725 } 726 727 // weak alias to __pio_usb_host_irq_handler 728 void pio_usb_host_irq_handler(uint8_t root_id) __attribute__ ((weak, alias("__pio_usb_host_irq_handler"))); 729 730 #pragma GCC pop_options