@@ -97,7 +97,7 @@ void __not_in_flash_func(pio_usb_bus_usb_transfer)(pio_port_t *pp,
9797 continue ;
9898 }
9999 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 ) {
101101 continue ;
102102 }
103103}
@@ -146,76 +146,50 @@ void __no_inline_not_in_flash_func(pio_usb_bus_prepare_receive)(const pio_port_t
146146 pio_sm_set_enabled (pp -> pio_usb_rx , pp -> sm_rx , true);
147147}
148148
149- static uint8_t __no_inline_not_in_flash_func (pio_usb_bus_wait_packet )(pio_port_t * pp ) {
150- uint16_t crc = 0xffff ;
151- uint16_t crc_prev = 0xffff ;
152- uint16_t crc_prev2 = 0xffff ;
153- uint16_t crc_receive = 0xffff ;
154- uint16_t crc_receive_inverse = 0 ;
155- bool crc_match = false;
156-
157- const uint16_t rx_buf_len = sizeof (pp -> usb_rx_buffer ) / sizeof (pp -> usb_rx_buffer [0 ]);
158-
149+ static inline __force_inline bool pio_usb_bus_wait_for_rx_start (const pio_port_t * pp ) {
159150 // USB 2.0 specs: 7.1.19.1: handshake timeout
160151 // Full-Speed (12 Mbps): 1 bit time = 1 / 12 MHz = 83.3 ns --> 16 bit times = 1.33 µs
161152 // Low-Speed (1.5 Mbps): 1 bit time = 1 / 1.5 MHz = 666.7 ns --> 16 bit times = 10.67 µs
162153
163154 // We're starting the timing somewhere in the current microsecond so always assume the first one
164155 // is less than a full microsecond. For example, a wait of 2 could actually be 1.1 microseconds.
165- // We will use 3 us (24 bit time) for Full speed and 12us (18 bit time) for Lowspeed .
166- uint32_t start = time_us_32 ();
156+ // We will use 3 us (24 bit time) for Full speed and 12us (18 bit time) for Low speed .
157+ uint32_t start = get_time_us_32 ();
167158 uint32_t timeout = pp -> low_speed ? 12 : 3 ;
168- while (time_us_32 () - start <= timeout ) {
159+ while (get_time_us_32 () - start <= timeout ) {
169160 if ((pp -> pio_usb_rx -> irq & IRQ_RX_START_MASK ) != 0 ) {
170- break ;
161+ return true ;
171162 }
172163 }
164+ return false;
165+ };
173166
174- // Timeout if we're not started.
175- if ((pp -> pio_usb_rx -> irq & IRQ_RX_START_MASK ) == 0 ) {
167+ uint8_t __no_inline_not_in_flash_func ( pio_usb_bus_wait_handshake )( pio_port_t * pp ) {
168+ if (! pio_usb_bus_wait_for_rx_start (pp ) ) {
176169 return 0 ;
177170 }
178171
179172 int16_t idx = 0 ;
180- // Timeout in seven microseconds. That is enough time to receive one byte at
181- // low speed. This is to detect packets without an EOP because the device was
182- // unplugged.
183- start = time_us_32 ();
184- while (time_us_32 () - start <= 7 ) {
173+ // Timeout in seven microseconds. That is enough time to receive one byte at low speed.
174+ // This is to detect packets without an EOP because the device was unplugged.
175+ uint32_t start = get_time_us_32 ();
176+ while (get_time_us_32 () - start <= 7 ) {
185177 if (pio_sm_get_rx_fifo_level (pp -> pio_usb_rx , pp -> sm_rx )) {
186178 uint8_t data = pio_sm_get (pp -> pio_usb_rx , pp -> sm_rx ) >> 24 ;
187- if (idx < rx_buf_len ) {
188- pp -> usb_rx_buffer [idx ] = data ;
189- }
190- start = time_us_32 ();
179+ pp -> usb_rx_buffer [idx ++ ] = data ;
191180
192- if (idx >= 2 ) {
193- crc_prev2 = crc_prev ;
194- crc_prev = crc ;
195- crc = update_usb_crc16 (crc , data );
196- crc_receive = (crc_receive >> 8 ) | (data << 8 );
197- crc_receive_inverse = crc_receive ^ 0xffff ;
198- crc_match = (crc_receive_inverse == crc_prev2 );
181+ start = get_time_us_32 (); // reset timeout when a byte is received
182+ if (idx == 2 ) {
183+ break ;
199184 }
200- idx ++ ;
201185 } else if ((pp -> pio_usb_rx -> irq & IRQ_RX_COMP_MASK ) != 0 ) {
202186 // Exit early if we've gotten an EOP. There *might* be a race between EOP
203187 // detection and NRZI decoding but it is unlikely.
204188 break ;
205189 }
206190 }
207191
208- if (idx >= 4 && !crc_match ) {
209- // CRC failed, discard the packet.
210- return 0 ;
211- }
212- return idx ;
213- }
214-
215- uint8_t __no_inline_not_in_flash_func (pio_usb_bus_wait_handshake )(pio_port_t * pp ) {
216-
217- uint8_t len = pio_usb_bus_wait_packet (pp );
218- if (len != 2 ) {
192+ if (idx != 2 ) {
219193 return 0 ;
220194 }
221195
@@ -224,18 +198,54 @@ uint8_t __no_inline_not_in_flash_func(pio_usb_bus_wait_handshake)(pio_port_t* pp
224198
225199int __no_inline_not_in_flash_func (pio_usb_bus_receive_packet_and_handshake )(
226200 pio_port_t * pp , uint8_t handshake ) {
227- uint8_t len = pio_usb_bus_wait_packet (pp );
228- if (len == 0 ) {
229- // Return and don't respond with a handshake.
201+ if (!pio_usb_bus_wait_for_rx_start (pp )) {
230202 return -1 ;
231203 }
232- // Only handshake if the other end gave data.
233- if (len >= 4 ) {
234- pio_usb_bus_send_handshake (pp , handshake );
235- }
236204
237- if (handshake == USB_PID_ACK ) {
238- return len - 4 ;
205+ uint16_t crc = 0xffff ;
206+ uint16_t crc_prev = 0xffff ;
207+ uint16_t crc_prev2 = 0xffff ;
208+ uint16_t crc_receive = 0xffff ;
209+ uint16_t crc_receive_inverse = 0 ;
210+ bool crc_match = false;
211+ const uint16_t rx_buf_len = sizeof (pp -> usb_rx_buffer ) / sizeof (pp -> usb_rx_buffer [0 ]);
212+ int16_t idx = 0 ;
213+
214+ // Timeout in seven microseconds. That is enough time to receive one byte at low speed.
215+ // This is to detect packets without an EOP because the device was unplugged.
216+ uint32_t start = get_time_us_32 ();
217+ while (get_time_us_32 () - start <= 7 ) {
218+ if (pio_sm_get_rx_fifo_level (pp -> pio_usb_rx , pp -> sm_rx )) {
219+ uint8_t data = pio_sm_get (pp -> pio_usb_rx , pp -> sm_rx ) >> 24 ;
220+ if (idx < rx_buf_len ) {
221+ pp -> usb_rx_buffer [idx ] = data ;
222+ }
223+ start = get_time_us_32 (); // reset timeout when a byte is received
224+
225+ if (idx >= 2 ) {
226+ crc_prev2 = crc_prev ;
227+ crc_prev = crc ;
228+ crc = update_usb_crc16 (crc , data );
229+ crc_receive = (crc_receive >> 8 ) | (data << 8 );
230+ crc_receive_inverse = crc_receive ^ 0xffff ;
231+ crc_match = (crc_receive_inverse == crc_prev2 );
232+ }
233+ idx ++ ;
234+ } else if ((pp -> pio_usb_rx -> irq & IRQ_RX_COMP_MASK ) != 0 ) {
235+ // Exit early if we've gotten an EOP. There *might* be a race between EOP
236+ // detection and NRZI decoding but it is unlikely.
237+ if (handshake == USB_PID_ACK ) {
238+ // Only ACK if crc matches
239+ if (idx >= 4 && crc_match ) {
240+ pio_usb_bus_send_handshake (pp , USB_PID_ACK );
241+ return idx - 4 ;
242+ }
243+ } else {
244+ // always send other handshake NAK/STALL
245+ pio_usb_bus_send_handshake (pp , handshake );
246+ }
247+ break ;
248+ }
239249 }
240250
241251 return -1 ;
0 commit comments