@@ -97,7 +97,7 @@ void __not_in_flash_func(pio_usb_bus_usb_transfer)(pio_port_t *pp,
97
97
continue ;
98
98
}
99
99
pp -> pio_usb_tx -> irq = IRQ_TX_ALL_MASK ; // clear complete flag
100
- while (* pc < PIO_USB_TX_ENCODED_DATA_COMP ) {
100
+ while (* pc <= PIO_USB_TX_ENCODED_DATA_COMP ) {
101
101
continue ;
102
102
}
103
103
}
@@ -206,6 +206,19 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
206
206
const uint16_t rx_buf_len = sizeof (pp -> usb_rx_buffer ) / sizeof (pp -> usb_rx_buffer [0 ]);
207
207
int16_t idx = 0 ;
208
208
209
+ // Per USB Specs 7.1.18 for turnaround: We must wait at least 2 bit times for inter-packet delay.
210
+ // This is essential for working with LS device specially when we overlocked the mcu.
211
+ // Pre-calculate number of cycle per bit time
212
+ // - Lowspeed: 1 bit time = (cpufreq / 1.5 Mhz) = clk_div_ls_tx.div_int*6Mhz / 1.5 Mhz = 4 * clk_div_ls_tx.div_int
213
+ // - Fullspeed 1 bit time = (cpufreq / 12 Mhz) = clk_div_fs_tx.div_int*48Mhz / 12 Mhz = 4 * clk_div_fs_tx.div_int
214
+ // Since there is also overhead, we only wait 1.5 bit for LS and 1 bit for FS
215
+ uint32_t turnaround_in_cycle ;
216
+ if (pp -> low_speed ) {
217
+ turnaround_in_cycle = 6 * pp -> clk_div_ls_tx .div_int ; // 1.5 bit time
218
+ } else {
219
+ turnaround_in_cycle = 4 * pp -> clk_div_fs_tx .div_int ; // 1 bit time
220
+ }
221
+
209
222
// Timeout in seven microseconds. That is enough time to receive one byte at low speed.
210
223
// This is to detect packets without an EOP because the device was unplugged.
211
224
uint32_t start = get_time_us_32 ();
@@ -227,8 +240,10 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
227
240
}
228
241
idx ++ ;
229
242
} else if ((pp -> pio_usb_rx -> irq & IRQ_RX_COMP_MASK ) != 0 ) {
230
- // Exit early if we've gotten an EOP. There *might* be a race between EOP
231
- // detection and NRZI decoding but it is unlikely.
243
+ // Exit since we've gotten an EOP.
244
+ // Timing critical: pre specs handshake must be sent within 2-7 bit-time strictly
245
+ busy_wait_at_least_cycles (turnaround_in_cycle ); // wait for turnaround
246
+
232
247
if (handshake == USB_PID_ACK ) {
233
248
// Only ACK if crc matches
234
249
if (idx >= 4 && crc_match ) {
0 commit comments