summaryrefslogtreecommitdiff
path: root/src/portable
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-01-09 18:40:55 +0700
committerhathach <[email protected]>2026-01-09 18:40:55 +0700
commit4c86cbdc822ccf0f71a67c5f2d627e18ecbad46f (patch)
treee4e69b79d725c53c35a24fa066f231d21675a9c2 /src/portable
parent085ec06874f5680604a75e3a721a51f962d66973 (diff)
enable dedicated hwfifo for rp2
Diffstat (limited to 'src/portable')
-rw-r--r--src/portable/raspberrypi/rp2040/dcd_rp2040.c10
-rw-r--r--src/portable/raspberrypi/rp2040/hcd_rp2040.c4
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.c55
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.h35
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);