summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class/video/video_device.c2
-rw-r--r--src/common/tusb_common.h1
-rw-r--r--src/common/tusb_mcu.h1
-rw-r--r--src/portable/raspberrypi/rp2040/dcd_rp2040.c108
4 files changed, 57 insertions, 55 deletions
diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c
index a7451c577..86513ddf0 100644
--- a/src/class/video/video_device.c
+++ b/src/class/video/video_device.c
@@ -1307,7 +1307,7 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
#ifdef TUP_DCD_EDPT_ISO_ALLOC
/* Allocate ISO endpoints */
uint16_t ep_size = 0;
- uint16_t ep_addr = 0;
+ uint8_t ep_addr = 0;
uint8_t const *p_desc = (uint8_t const*)itf_desc + stm->desc.beg;
uint8_t const *p_desc_end = (uint8_t const*)itf_desc + stm->desc.end;
while (p_desc < p_desc_end) {
diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h
index d05032d00..74cac965d 100644
--- a/src/common/tusb_common.h
+++ b/src/common/tusb_common.h
@@ -177,6 +177,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned64(uint64_t value) { retur
//------------- Mathematics -------------//
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return TU_DIV_CEIL(v, d); }
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_round_up(uint32_t v, uint32_t f) { return tu_div_ceil(v, f) * f; }
// log2 of a value is its MSB's position
// TODO use clz TODO remove
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index 0c64c041c..d282c890d 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -400,6 +400,7 @@
// Raspberry Pi
//--------------------------------------------------------------------+
#elif TU_CHECK_MCU(OPT_MCU_RP2040)
+ #define TUP_DCD_EDPT_ISO_ALLOC
#define TUP_DCD_ENDPOINT_MAX 16
#define TU_ATTR_FAST_FUNC __attribute__((section(".time_critical.tinyusb")))
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
index 2e177d5cb..af08b549d 100644
--- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
@@ -46,7 +46,6 @@
/*------------------------------------------------------------------*/
/* Low level controller
*------------------------------------------------------------------*/
-
// Init these in dcd_init
static uint8_t* next_buffer_ptr;
@@ -66,58 +65,31 @@ TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_addr(
return hw_endpoint_get_by_num(num, dir);
}
-static void _hw_endpoint_alloc(struct hw_endpoint* ep, uint8_t transfer_type) {
- // size must be multiple of 64
- uint size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u;
+// Allocate from the USB buffer space (max 3840 bytes)
+static void hw_endpoint_alloc(struct hw_endpoint* ep, size_t size) {
+ // round up size to multiple of 64
+ size = tu_round_up(ep->wMaxPacketSize, 64);
// double buffered Bulk endpoint
- if (transfer_type == TUSB_XFER_BULK) {
+ if (ep->transfer_type == TUSB_XFER_BULK) {
size *= 2u;
}
+ // assign buffer
ep->hw_data_buf = next_buffer_ptr;
next_buffer_ptr += size;
- assert(((uintptr_t) next_buffer_ptr & 0b111111u) == 0);
- uint dpram_offset = hw_data_offset(ep->hw_data_buf);
- hard_assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
-
- pico_info(" Allocated %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf);
-
- // Fill in endpoint control register with buffer offset
- uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint) transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset;
-
- *ep->endpoint_control = reg;
-}
-
-static void _hw_endpoint_close(struct hw_endpoint* ep) {
- // Clear hardware registers and then zero the struct
- // Clears endpoint enable
- *ep->endpoint_control = 0;
- // Clears buffer available, etc
- *ep->buffer_control = 0;
- // Clear any endpoint state
- memset(ep, 0, sizeof(struct hw_endpoint));
-
- // Reclaim buffer space if all endpoints are closed
- bool reclaim_buffers = true;
- for (uint8_t i = 1; i < USB_MAX_ENDPOINTS; i++) {
- if (hw_endpoint_get_by_num(i, TUSB_DIR_OUT)->hw_data_buf != NULL ||
- hw_endpoint_get_by_num(i, TUSB_DIR_IN)->hw_data_buf != NULL) {
- reclaim_buffers = false;
- break;
- }
- }
- if (reclaim_buffers) {
- next_buffer_ptr = &usb_dpram->epx_data[0];
- }
+ hard_assert(next_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);
}
-static void hw_endpoint_close(uint8_t ep_addr) {
- struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
- _hw_endpoint_close(ep);
+// Enable endpoint
+TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_enable(struct hw_endpoint* ep) {
+ uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint) ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | hw_data_offset(ep->hw_data_buf);
+ *ep->endpoint_control = reg;
}
+// main processing for dcd_edpt_iso_activate
static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) {
struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
@@ -156,9 +128,18 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t
} else {
ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out;
}
+ }
+}
- // alloc a buffer and fill in endpoint control register
- _hw_endpoint_alloc(ep, transfer_type);
+// Init, allocate buffer and enable endpoint
+static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) {
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
+ hw_endpoint_init(ep_addr, wMaxPacketSize, transfer_type);
+ const uint8_t num = tu_edpt_number(ep_addr);
+ if (num != 0) {
+ // EP0 is already enabled
+ hw_endpoint_alloc(ep, ep->wMaxPacketSize);
+ hw_endpoint_enable(ep);
}
}
@@ -387,8 +368,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
// Init control endpoints
tu_memclr(hw_endpoints[0], 2 * sizeof(hw_endpoint_t));
- hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL);
- hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL);
+ hw_endpoint_open(0x0, 64, TUSB_XFER_CONTROL);
+ hw_endpoint_open(0x80, 64, TUSB_XFER_CONTROL);
// Init non-control endpoints
reset_non_control_endpoints();
@@ -493,9 +474,34 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req
}
}
-bool dcd_edpt_open(__unused uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
- assert(rhport == 0);
- hw_endpoint_init(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), desc_edpt->bmAttributes.xfer);
+bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
+ (void) rhport;
+ const uint8_t xfer_type = desc_edpt->bmAttributes.xfer;
+ TU_VERIFY(xfer_type != TUSB_XFER_ISOCHRONOUS);
+ hw_endpoint_open(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), xfer_type);
+ return true;
+}
+
+// New API: Allocate packet buffer used by ISO endpoints
+// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering
+bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
+ (void) rhport;
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
+ hw_endpoint_init(ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS);
+ hw_endpoint_alloc(ep, largest_packet_size);
+ return true;
+}
+
+// New API: Configure and enable an ISO endpoint according to descriptor
+bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
+ (void) rhport;
+ const uint8_t ep_addr = ep_desc->bEndpointAddress;
+ // Fill in endpoint control register with buffer offset
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
+ TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and buffer allocated
+ ep->wMaxPacketSize = ep_desc->wMaxPacketSize;
+
+ hw_endpoint_enable(ep);
return true;
}
@@ -540,12 +546,6 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
}
}
-void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
- (void) rhport;
- pico_trace("dcd_edpt_close %02x\r\n", ep_addr);
- hw_endpoint_close(ep_addr);
-}
-
void __tusb_irq_path_func(dcd_int_handler)(uint8_t rhport) {
(void) rhport;
dcd_rp2040_irq();