Skip to content

Commit

Permalink
Wait for PRE to finish. Comment timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
tannewt committed Feb 27, 2025
1 parent 36f008d commit 6d14098
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/pio_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,21 @@ static void __no_inline_not_in_flash_func(send_pre)(pio_port_t *pp) {
SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_fs_tx);

pio_sm_exec(pp->pio_usb_tx, pp->sm_tx, pp->tx_start_instr);
pp->pio_usb_tx->irq = IRQ_TX_ALL_MASK; // clear complete flag
dma_channel_transfer_from_buffer_now(pp->tx_ch, pre_encoded,
sizeof(pre_encoded));
pp->pio_usb_tx->irq = IRQ_TX_ALL_MASK; // clear complete flag

while ((pp->pio_usb_tx->irq & IRQ_TX_EOP_MASK) == 0) {
continue;
}
pio_sm_clear_fifos(pp->pio_usb_tx, pp->sm_tx);
// Wait for complete transmission of the PRE packet. We don't want to
// accidentally send trailing Ks in low speed mode due to an early start
// instruction that re-enables the outputs.
uint32_t stall_mask = 1 << (PIO_FDEBUG_TXSTALL_LSB + pp->sm_tx);
pp->pio_usb_tx->fdebug = stall_mask; // clear sticky stall mask bit
while (!(pp->pio_usb_tx->fdebug & stall_mask)) {
continue;
}

// change bus speed to low-speed
pp->low_speed = true;
Expand Down Expand Up @@ -149,8 +156,15 @@ static uint8_t __no_inline_not_in_flash_func(pio_usb_bus_wait_packet)(pio_port_t

const uint16_t rx_buf_len = sizeof(pp->usb_rx_buffer) / sizeof(pp->usb_rx_buffer[0]);

// USB 2.0 specs: 7.1.19.1: handshake timeout
// Full-Speed (12 Mbps): 1 bit time = 1 / 12 MHz = 83.3 ns --> 16 bit times = 1.33 µs
// Low-Speed (1.5 Mbps): 1 bit time = 1 / 1.5 MHz = 666.7 ns --> 16 bit times = 10.67 µs

// We're starting the timing somewhere in the current microsecond so always assume the first one
// is less than a full microsecond. For example, a wait of 2 could actually be 1.1 microseconds.
// We will use 3 us (24 bit time) for Full speed and 12us (18 bit time) for Lowspeed.
uint32_t start = time_us_32();
uint32_t timeout = pp->low_speed ? 20 : 3;
uint32_t timeout = pp->low_speed ? 12 : 3;
while (time_us_32() - start <= timeout) {
if ((pp->pio_usb_rx->irq & IRQ_RX_START_MASK) != 0) {
break;
Expand Down

0 comments on commit 6d14098

Please sign in to comment.