diff options
| author | hathach <[email protected]> | 2026-01-09 18:40:55 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-01-09 18:40:55 +0700 |
| commit | 4c86cbdc822ccf0f71a67c5f2d627e18ecbad46f (patch) | |
| tree | e4e69b79d725c53c35a24fa066f231d21675a9c2 /src/portable | |
| parent | 085ec06874f5680604a75e3a721a51f962d66973 (diff) | |
enable dedicated hwfifo for rp2
Diffstat (limited to 'src/portable')
| -rw-r--r-- | src/portable/raspberrypi/rp2040/dcd_rp2040.c | 10 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/hcd_rp2040.c | 4 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/rp2040_usb.c | 55 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/rp2040_usb.h | 35 |
4 files changed, 69 insertions, 35 deletions
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 71d5cf19c..f25d808d4 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -502,7 +502,15 @@ 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, total_bytes); + hw_endpoint_xfer_start(ep, buffer, NULL, total_bytes); + return true; +} + +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { + (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); return true; } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 7bf247ced..06c0ce340 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -511,7 +511,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b // sie ctrl registers. Otherwise, interrupt ep registers should // already be configured if (ep == &epx) { - hw_endpoint_xfer_start(ep, buffer, buflen); + hw_endpoint_xfer_start(ep, buffer, NULL, buflen); // That has set up buffer control, endpoint control etc // for host we have to initiate the transfer @@ -527,7 +527,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b busy_wait_at_least_cycles(12); usb_hw->sie_ctrl = flags; } else { - hw_endpoint_xfer_start(ep, buffer, buflen); + hw_endpoint_xfer_start(ep, buffer, NULL, buflen); } return true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 8f91ecf22..bde45db1b 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPE //--------------------------------------------------------------------+ -static void hwep_xfer_sync(hw_endpoint_t *ep); +static void sync_xfer(hw_endpoint_t *ep); #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX static bool e15_is_critical_frame_period(struct hw_endpoint *ep); @@ -55,6 +55,16 @@ static void unaligned_memcpy(void *dst, const void *src, size_t n) { } } +void tu_hwfifo_write(volatile void *hwfifo, const uint8_t *src, uint16_t len, const tu_hwfifo_access_t *access_mode) { + (void)access_mode; + unaligned_memcpy((void *)(uintptr_t)hwfifo, src, len); +} + +void tu_hwfifo_read(const volatile void *hwfifo, uint8_t *dest, uint16_t len, const tu_hwfifo_access_t *access_mode) { + (void)access_mode; + unaligned_memcpy(dest, (const void *)(uintptr_t)hwfifo, len); +} + void rp2usb_init(void) { // Reset usb controller reset_block(RESETS_RESET_USBCTRL_BITS); @@ -127,9 +137,16 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, ep->next_pid ^= 1u; if (!is_rx) { - // Copy data from user buffer to hw buffer - unaligned_memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen); - ep->user_buf += buflen; + if (buflen) { + // Copy data from user buffer/fifo to hw buffer + uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + if (ep->is_xfer_fifo) { + tu_hwfifo_write_from_fifo(hw_buf, ep->user_fifo, buflen, NULL); + } else { + unaligned_memcpy(hw_buf, ep->user_buf, buflen); + ep->user_buf += buflen; + } + } // Mark as full buf_ctrl |= USB_BUF_CTRL_FULL; @@ -152,7 +169,6 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, // Prepare buffer control register value void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) { const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); - bool is_rx; bool is_host = false; io_rw_32 *ep_ctrl_reg; @@ -211,7 +227,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); } -void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t total_len) { +void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) { hw_endpoint_lock_update(ep, 1); if (ep->active) { @@ -224,7 +240,14 @@ void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t to ep->remaining_len = total_len; ep->xferred_len = 0; ep->active = true; - ep->user_buf = buffer; + + if (ff != NULL) { + ep->user_fifo = ff; + ep->is_xfer_fifo = true; + } else { + ep->user_buf = buffer; + ep->is_xfer_fifo = false; + } #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX if (ep->e15_bulk_in) { @@ -256,17 +279,20 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 // We are continuing a transfer here. If we are TX, we have successfully // sent some data can increase the length we have sent assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); - - ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes); } else { // If we have received some data, so can increase the length // we have received AFTER we have copied it to the user buffer at the appropriate offset assert(buf_ctrl & USB_BUF_CTRL_FULL); - unaligned_memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes); - ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes); - ep->user_buf += xferred_bytes; + uint8_t *hw_buf = ep->hw_data_buf + buf_id * 64; + if (ep->is_xfer_fifo) { + tu_hwfifo_read_to_fifo(hw_buf, ep->user_fifo, xferred_bytes, NULL); + } else { + unaligned_memcpy(ep->user_buf, hw_buf, xferred_bytes); + ep->user_buf += xferred_bytes; + } } + ep->xferred_len += xferred_bytes; // Short packet if (xferred_bytes < ep->wMaxPacketSize) { @@ -278,7 +304,7 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(hw_endpoint_t *ep, io_rw_32 } // Update hw endpoint struct with info from hardware after a buff status interrupt -static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { +static void __tusb_irq_path_func(sync_xfer)(hw_endpoint_t *ep) { // const uint8_t ep_num = tu_edpt_number(ep->ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep->ep_addr); @@ -350,8 +376,7 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) { panic("Can't continue xfer on inactive ep %02X", ep->ep_addr); } - // Update EP struct from hardware state - hwep_xfer_sync(ep); + sync_xfer(ep); // Update EP struct from hardware state // Now we have synced our state with the hardware. Is there more data to transfer? // If we are done then notify tinyusb diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 944d604bc..cce868540 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -1,14 +1,16 @@ #ifndef RP2040_COMMON_H_ #define RP2040_COMMON_H_ -#include "common/tusb_common.h" - #include "pico.h" #include "hardware/structs/usb.h" #include "hardware/irq.h" #include "hardware/resets.h" #include "hardware/timer.h" +#include "common/tusb_common.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" + #if defined(RP2040_USB_HOST_MODE) && defined(RP2040_USB_DEVICE_MODE) #error TinyUSB device and host mode not supported at the same time #endif @@ -63,32 +65,31 @@ typedef struct hw_endpoint { uint8_t ep_addr; uint8_t next_pid; uint8_t transfer_type; - - bool active; // transferring data + bool active; // transferring data + bool is_xfer_fifo; // transfer using fifo #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX bool e15_bulk_in; // Errata15 device bulk in uint8_t pending; // Transfer scheduled but not active #endif +#if CFG_TUH_ENABLED + bool configured; // Is this a valid struct + uint8_t dev_addr; + uint8_t interrupt_num; // for host interrupt endpoints +#endif + uint16_t wMaxPacketSize; uint8_t *hw_data_buf; // Buffer pointer in usb dpram - // Current transfer information - uint8_t *user_buf; // User buffer in main memory + // transfer info + union { + uint8_t *user_buf; // User buffer in main memory + tu_fifo_t *user_fifo; + }; uint16_t remaining_len; uint16_t xferred_len; -#if CFG_TUH_ENABLED - // Is this a valid struct - bool configured; - - // Only needed for host - uint8_t dev_addr; - - // If interrupt endpoint - uint8_t interrupt_num; -#endif } hw_endpoint_t; #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX @@ -102,7 +103,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool rp2usb_is_host_mode(void) { return (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) ? true : false; } -void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); +void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len); bool hw_endpoint_xfer_continue(struct hw_endpoint *ep); void hw_endpoint_reset_transfer(struct hw_endpoint *ep); void hw_endpoint_start_next_buffer(struct hw_endpoint *ep); |
