@@ -148,6 +148,32 @@ static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t* buffer, uint16_t total_by
148148 hw_endpoint_xfer_start (ep , buffer , total_bytes );
149149}
150150
151+ static void hw_endpoint_abort_xfer (struct hw_endpoint * ep ) {
152+ // Abort any pending transfer
153+ // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1).
154+ // Which means we are not guaranteed to safely abort pending transfer on B0 and B1.
155+ const uint8_t dir = tu_edpt_dir (ep -> ep_addr );
156+ const uint8_t epnum = tu_edpt_number (ep -> ep_addr );
157+ const uint32_t abort_mask = TU_BIT ((epnum << 1 ) | (dir ? 0 : 1 ));
158+ if (rp2040_chip_version () >= 2 ) {
159+ usb_hw_set -> abort = abort_mask ;
160+ while ((usb_hw -> abort_done & abort_mask ) != abort_mask ) {}
161+ }
162+
163+ uint32_t buf_ctrl = USB_BUF_CTRL_SEL ; // reset to buffer 0
164+ if (ep -> next_pid ) {
165+ buf_ctrl |= USB_BUF_CTRL_DATA1_PID ;
166+ }
167+
168+ _hw_endpoint_buffer_control_set_value32 (ep , buf_ctrl );
169+ hw_endpoint_reset_transfer (ep );
170+
171+ if (rp2040_chip_version () >= 2 ) {
172+ usb_hw_clear -> abort_done = abort_mask ;
173+ usb_hw_clear -> abort = abort_mask ;
174+ }
175+ }
176+
151177static void __tusb_irq_path_func (hw_handle_buff_status )(void ) {
152178 uint32_t remaining_buffers = usb_hw -> buf_status ;
153179 pico_trace ("buf_status = 0x%08lx\r\n" , remaining_buffers );
@@ -178,25 +204,10 @@ TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) {
178204 // setup transfer. Also clear a stall in case
179205 for (uint8_t dir = 0 ; dir < 2 ; dir ++ ) {
180206 struct hw_endpoint * ep = hw_endpoint_get_by_num (0 , dir );
207+ ep -> next_pid = 1u ;
181208 if (ep -> active ) {
182- // Abort any pending transfer from a prior control transfer per USB specs
183- // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1).
184- // Which means we are not guaranteed to safely abort pending transfer on B0 and B1.
185- uint32_t const abort_mask = (dir ? USB_EP_ABORT_EP0_IN_BITS : USB_EP_ABORT_EP0_OUT_BITS );
186- if (rp2040_chip_version () >= 2 ) {
187- usb_hw_set -> abort = abort_mask ;
188- while ((usb_hw -> abort_done & abort_mask ) != abort_mask ) {}
189- }
190-
191- _hw_endpoint_buffer_control_set_value32 (ep , USB_BUF_CTRL_DATA1_PID | USB_BUF_CTRL_SEL );
192- hw_endpoint_reset_transfer (ep );
193-
194- if (rp2040_chip_version () >= 2 ) {
195- usb_hw_clear -> abort_done = abort_mask ;
196- usb_hw_clear -> abort = abort_mask ;
197- }
209+ hw_endpoint_abort_xfer (ep ); // Abort any pending transfer per USB specs
198210 }
199- ep -> next_pid = 1u ;
200211 }
201212}
202213
@@ -495,12 +506,14 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
495506// New API: Configure and enable an ISO endpoint according to descriptor
496507bool dcd_edpt_iso_activate (uint8_t rhport , tusb_desc_endpoint_t const * ep_desc ) {
497508 (void ) rhport ;
498- const uint8_t ep_addr = ep_desc -> bEndpointAddress ;
499- // Fill in endpoint control register with buffer offset
500- struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
501- TU_ASSERT (ep -> hw_data_buf != NULL ); // must be inited and buffer allocated
502- ep -> wMaxPacketSize = ep_desc -> wMaxPacketSize ;
509+ struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_desc -> bEndpointAddress );
510+ TU_ASSERT (ep -> hw_data_buf != NULL ); // must be inited and allocated previously
511+
512+ if (ep -> active ) {
513+ hw_endpoint_abort_xfer (ep ); // abort any pending transfer
514+ }
503515
516+ ep -> wMaxPacketSize = ep_desc -> wMaxPacketSize ;
504517 hw_endpoint_enable (ep );
505518 return true;
506519}
0 commit comments