Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0f3c90b
draft: hcd control work
hathach Jan 15, 2026
084ef43
refactor hcd, get both control and interrupt endpoint working
hathach Jan 16, 2026
0c9a170
implement hcd_device_close()
hathach Jan 16, 2026
292f334
rename
hathach Jan 16, 2026
edcc95d
rename
hathach Jan 16, 2026
0dd509a
revert back to shared hw_endpoint_t
hathach Jan 16, 2026
0fd8fd4
Merge branch 'refs/heads/master' into rp2040-hcd-epx
hathach Mar 19, 2026
0c6fa9b
Add EPX transfer scheduling when hcd_edpt_xfer() is called while epx …
hathach Mar 19, 2026
f7d1c10
Add support for EPX preemption on RP2350 during NAK conditions
hathach Mar 19, 2026
99d70e2
Add dd command to MSC file explorer for sector read and speed reporti…
hathach Mar 20, 2026
f7cf6bc
clean up
hathach Mar 20, 2026
3c2627e
update host msc hil test
hathach Mar 23, 2026
15eef94
add rp2040 sof + stop_trans on nak. increase nak_poll fs/ls delay to …
hathach Mar 23, 2026
09197ed
handle buf_status in per buffer basic (INTERRUPT_PER_BUFFER), this al…
hathach Mar 24, 2026
aeac28e
update hcd to handle interrupt per buf
hathach Mar 25, 2026
e81faa2
fix e4 incorrect buf with incorrect buf_id = 1
hathach Mar 25, 2026
94f4827
implement ping-pong double buffered for both tx and rx
hathach Mar 26, 2026
9b3d517
clean up hw_endpoint_open(), still has issue with E15 and ping-pong (…
hathach Mar 26, 2026
dd08939
fix E15 workaround issue with out of order in double buffer. device b…
hathach Mar 27, 2026
d9d28b7
rename and clean up
hathach Mar 27, 2026
a9eb36b
refactor
hathach Mar 27, 2026
7d00425
host epx clean up
hathach Mar 28, 2026
dfcd271
rp2 common refactor
hathach Mar 28, 2026
31ec5a7
hcd rp2 add double buffered for control endpoint transfers.
hathach Mar 30, 2026
660c8ca
host abort transfer on short packet in double buffer.
hathach Mar 31, 2026
9ac343a
finally get rp2040 host epx working with 2-sof solution for switching
hathach Mar 31, 2026
78d34d5
reduce code size, use state to replace active + pending
hathach Apr 1, 2026
d205048
fix hil uid typo
hathach Apr 1, 2026
087ceb7
fix issue caused by merging active + pending state
hathach Apr 1, 2026
b6f04f8
add msc device to hil rp2040 host pool
hathach Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 36 additions & 11 deletions src/portable/raspberrypi/rp2040/dcd_rp2040.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,27 @@ TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get_by_addr(uint8
return hw_endpoint_get(num, dir);
}

TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_device(struct hw_endpoint *ep) {
const uint8_t epnum = tu_edpt_number(ep->ep_addr);
const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr);
if (epnum == 0) {
// EP0 has no endpoint control register because the buffer offsets are fixed and always enabled
return NULL;
}
return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_ctrl[epnum - 1].in : &usb_dpram->ep_ctrl[epnum - 1].out;
}

TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_device(struct hw_endpoint *ep) {
const uint8_t epnum = tu_edpt_number(ep->ep_addr);
const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr);
return (dir == TUSB_DIR_IN) ? &usb_dpram->ep_buf_ctrl[epnum].in : &usb_dpram->ep_buf_ctrl[epnum].out;
}

// main processing for dcd_edpt_iso_activate
static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) {
ep->ep_addr = ep_addr;
ep->next_pid = 0u;
ep->wMaxPacketSize = wMaxPacketSize;
ep->max_packet_size = wMaxPacketSize;

// Clear existing buffer control state
io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep);
Expand All @@ -83,7 +99,7 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa
const uint8_t epnum = tu_edpt_number(ep_addr);
if (epnum == 0) {
// Buffer offset is fixed (also double buffered)
ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0];
ep->dpram_buf = (uint8_t *)&usb_dpram->ep0_buf_a[0];
} else {
// round up size to multiple of 64
uint16_t size = (uint16_t)tu_round_up(wMaxPacketSize, 64);
Expand All @@ -100,11 +116,11 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa
}

// assign buffer
ep->hw_data_buf = hw_buffer_ptr;
ep->dpram_buf = hw_buffer_ptr;
hw_buffer_ptr += size;

hard_assert(hw_buffer_ptr < usb_dpram->epx_data + sizeof(usb_dpram->epx_data));
pico_info(" Allocated %d bytes (0x%p)\r\n", size, ep->hw_data_buf);
pico_info(" Allocated %d bytes (0x%p)\r\n", size, ep->dpram_buf);
}
}

Expand All @@ -113,7 +129,7 @@ static void hw_endpoint_enable(hw_endpoint_t *ep, uint8_t transfer_type) {
// Set endpoint control register to enable (EP0 has no endpoint control register)
if (ctrl_reg != NULL) {
const uint32_t ctrl_value =
EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hw_data_buf);
EP_CTRL_ENABLE_BITS | ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->dpram_buf);
*ctrl_reg = ctrl_value;
}
}
Expand Down Expand Up @@ -170,7 +186,10 @@ static void __tusb_irq_path_func(handle_hw_buff_status)(void) {
const tusb_dir_t dir = (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN;
hw_endpoint_t *ep = hw_endpoint_get(epnum, dir);

const bool done = hw_endpoint_xfer_continue(ep);
io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep);
io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep);
const bool done = hw_endpoint_xfer_continue(ep, ep_reg, buf_reg);

if (done) {
// Notify usbd
const uint16_t xferred_len = ep->xferred_len;
Expand Down Expand Up @@ -232,7 +251,9 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) {
hw_endpoint_lock_update(ep, 1);
if (ep->pending) {
ep->pending = 0;
hw_endpoint_start_next_buffer(ep);
io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep);
io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep);
hw_endpoint_start_next_buffer(ep, ep_reg, buf_reg);
}
hw_endpoint_lock_update(ep, -1);
}
Expand Down Expand Up @@ -480,12 +501,12 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc)
const uint8_t epnum = tu_edpt_number(ep_desc->bEndpointAddress);
const tusb_dir_t dir = tu_edpt_dir(ep_desc->bEndpointAddress);
struct hw_endpoint *ep = hw_endpoint_get(epnum, dir);
TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and allocated previously
TU_ASSERT(ep->dpram_buf != NULL); // must be inited and allocated previously

if (ep->active) {
hw_endpoint_abort_xfer(ep); // abort any pending transfer
}
ep->wMaxPacketSize = ep_desc->wMaxPacketSize;
ep->max_packet_size = ep_desc->wMaxPacketSize;

hw_endpoint_enable(ep, TUSB_XFER_ISOCHRONOUS);
return true;
Expand All @@ -501,7 +522,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
(void)rhport;
(void)is_isr;
hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr);
hw_endpoint_xfer_start(ep, buffer, NULL, total_bytes);
io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep);
io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep);
hw_endpoint_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, total_bytes);
return true;
}

Expand All @@ -510,7 +533,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t
(void)rhport;
(void)is_isr;
hw_endpoint_t *ep = hw_endpoint_get_by_addr(ep_addr);
hw_endpoint_xfer_start(ep, NULL, ff, total_bytes);
io_rw_32 *ep_reg = hwep_ctrl_reg_device(ep);
io_rw_32 *buf_reg = hwbuf_ctrl_reg_device(ep);
hw_endpoint_xfer_start(ep, ep_reg, buf_reg, NULL, ff, total_bytes);
return true;
}
#endif
Expand Down
Loading
Loading