Skip to content

Commit 334ac80

Browse files
authored
Merge pull request #2937 from pschatzmann/rp2040-iso
rp2040 correct dcd_edpt_iso_activate
2 parents fd3290c + 102c199 commit 334ac80

File tree

1 file changed

+35
-22
lines changed

1 file changed

+35
-22
lines changed

src/portable/raspberrypi/rp2040/dcd_rp2040.c

+35-22
Original file line numberDiff line numberDiff line change
@@ -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+
151177
static 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
496507
bool 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

Comments
 (0)