Skip to content

Commit 93ff3da

Browse files
committed
fix(hcd_rp2040) assert/panic endpoint already active: when a device reset while having on-going control transfer
1 parent a29e114 commit 93ff3da

File tree

2 files changed

+27
-23
lines changed

2 files changed

+27
-23
lines changed

src/portable/raspberrypi/rp2040/hcd_rp2040.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -459,28 +459,33 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport)
459459
}
460460

461461
// Close all opened endpoint belong to this device
462-
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
463-
{
462+
void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
464463
pico_trace("hcd_device_close %d\n", dev_addr);
465464
(void) rhport;
466465

467-
if (dev_addr == 0) return;
468-
469-
for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++)
470-
{
471-
hw_endpoint_t* ep = &ep_pool[i];
466+
// reset epx if it is currently active with unplugged device
467+
if (epx.configured && epx.active && epx.dev_addr == dev_addr) {
468+
epx.configured = false;
469+
*epx.endpoint_control = 0;
470+
*epx.buffer_control = 0;
471+
hw_endpoint_reset_transfer(&epx);
472+
}
472473

473-
if (ep->dev_addr == dev_addr && ep->configured)
474-
{
475-
// in case it is an interrupt endpoint, disable it
476-
usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
477-
usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
478-
479-
// unconfigure the endpoint
480-
ep->configured = false;
481-
*ep->endpoint_control = 0;
482-
*ep->buffer_control = 0;
483-
hw_endpoint_reset_transfer(ep);
474+
// dev0 only has ep0
475+
if (dev_addr != 0) {
476+
for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) {
477+
hw_endpoint_t *ep = &ep_pool[i];
478+
if (ep->dev_addr == dev_addr && ep->configured) {
479+
// in case it is an interrupt endpoint, disable it
480+
usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
481+
usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
482+
483+
// unconfigure the endpoint
484+
ep->configured = false;
485+
*ep->endpoint_control = 0;
486+
*ep->buffer_control = 0;
487+
hw_endpoint_reset_transfer(ep);
488+
}
484489
}
485490
}
486491
}
@@ -557,7 +562,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
557562
}
558563

559564
// If a normal transfer (non-interrupt) then initiate using
560-
// sie ctrl registers. Otherwise interrupt ep registers should
565+
// sie ctrl registers. Otherwise, interrupt ep registers should
561566
// already be configured
562567
if ( ep == &epx )
563568
{
@@ -597,13 +602,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
597602
(void) rhport;
598603

599604
// Copy data into setup packet buffer
600-
for ( uint8_t i = 0; i < 8; i++ )
601-
{
605+
for (uint8_t i = 0; i < 8; i++) {
602606
usbh_dpram->setup_packet[i] = setup_packet[i];
603607
}
604608

605609
// Configure EP0 struct with setup info for the trans complete
606-
struct hw_endpoint * ep = _hw_endpoint_allocate(0);
610+
struct hw_endpoint * ep = _hw_endpoint_allocate( (uint8_t) TUSB_XFER_CONTROL);
607611
TU_ASSERT(ep);
608612

609613
// EPX should be inactive

src/portable/raspberrypi/rp2040/rp2040_usb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoi
110110
*ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL;
111111
// 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control
112112
// Don't need delay in host mode as host is in charge
113-
if ( !is_host_mode()) {
113+
if (!is_host_mode()) {
114114
busy_wait_at_least_cycles(12);
115115
}
116116
}

0 commit comments

Comments
 (0)