From 592d047936544af03e7704ad7a88acef88fd6aee Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 22 Feb 2021 20:53:16 -0600 Subject: rp2040: correctly size variables to reduce RAM usage --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 10 +++++----- src/portable/raspberrypi/rp2040/rp2040_usb.c | 9 ++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 12 ++++++++---- 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 95b0963a3..d329d40c3 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -48,8 +48,8 @@ // Init these in dcd_init static uint8_t *next_buffer_ptr; -// Endpoints 0-15, direction 0 for out and 1 for in. -static struct hw_endpoint hw_endpoints[16][2] = {0}; +// Endpoints 0-TUD_OPT_RP2040_USB_MAX_ENDPOINTS, direction 0 for out and 1 for in. +static struct hw_endpoint hw_endpoints[TUD_OPT_RP2040_USB_MAX_ENDPOINTS][2] = {0}; static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) { @@ -64,7 +64,7 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) } static void _hw_endpoint_alloc(struct hw_endpoint *ep) { - uint size = TU_MIN(64, ep->wMaxPacketSize); + uint16_t size = TU_MIN(64, ep->wMaxPacketSize); // Assumes single buffered for now ep->hw_data_buf = next_buffer_ptr; @@ -99,7 +99,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) *ep->endpoint_control = reg; } -static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type) +static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { uint8_t num = tu_edpt_number(ep_addr); bool in = ep_addr & TUSB_DIR_IN_MASK; @@ -194,7 +194,7 @@ static void hw_endpoint_close(uint8_t ep_addr) } #endif -static void hw_endpoint_init(uint8_t ep_addr, uint wMaxPacketSize, uint8_t bmAttributes) +static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t bmAttributes) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 339297ad6..ecd474695 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -30,7 +30,6 @@ #include #include "rp2040_usb.h" -#include "hardware/clocks.h" // Direction strings for debug const char *ep_dir_string[] = { @@ -153,7 +152,7 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t // Fill in info now that we're kicking off the hw ep->total_len = total_len; ep->len = 0; - ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize); + ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); ep->active = true; ep->user_buf = buffer; // Recalculate if this is the last buffer @@ -172,7 +171,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // Get the buffer state and amount of bytes we have // transferred uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); - uint transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; #ifdef RP2040_USB_HOST_MODE // tag::host_buf_sel_fix[] @@ -230,8 +229,8 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) _hw_endpoint_xfer_sync(ep); // Now we have synced our state with the hardware. Is there more data to transfer? - uint remaining_bytes = ep->total_len - ep->len; - ep->transfer_size = tu_min32(remaining_bytes, ep->wMaxPacketSize); + uint16_t remaining_bytes = ep->total_len - ep->len; + ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); _hw_endpoint_update_last_buf(ep); // Can happen because of programmer error so check for it diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 7c3234e8d..be9b507c2 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -16,6 +16,10 @@ #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif +#if !defined(TUD_OPT_RP2040_USB_MAX_ENDPOINTS) +#define TUD_OPT_RP2040_USB_MAX_ENDPOINTS 16 +#endif + // For memset #include @@ -67,10 +71,10 @@ struct hw_endpoint // Current transfer information bool active; - uint total_len; - uint len; + uint16_t total_len; + uint16_t len; // Amount of data with the hardware - uint transfer_size; + uint16_t transfer_size; // Only needed for host mode bool last_buf; // HOST BUG. Host will incorrect write status to top half of buffer @@ -80,7 +84,7 @@ struct hw_endpoint uint8_t *user_buf; // Data needed from EP descriptor - uint wMaxPacketSize; + uint16_t wMaxPacketSize; // Interrupt, bulk, etc uint8_t transfer_type; -- cgit v1.3.1 From 5a8ae31316ed30937e910e376dc6f62e8e4e3433 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 23 Feb 2021 10:08:38 -0600 Subject: rp2040: leverage existing macro for capping endpoints in pico-sdk --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 ++-- src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index d329d40c3..9c43b6fdb 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -48,8 +48,8 @@ // Init these in dcd_init static uint8_t *next_buffer_ptr; -// Endpoints 0-TUD_OPT_RP2040_USB_MAX_ENDPOINTS, direction 0 for out and 1 for in. -static struct hw_endpoint hw_endpoints[TUD_OPT_RP2040_USB_MAX_ENDPOINTS][2] = {0}; +// USB_MAX_ENDPOINTS Endpoints, direction 0 for out and 1 for in. +static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2] = {0}; static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) { diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index be9b507c2..522d7d701 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -16,10 +16,6 @@ #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif -#if !defined(TUD_OPT_RP2040_USB_MAX_ENDPOINTS) -#define TUD_OPT_RP2040_USB_MAX_ENDPOINTS 16 -#endif - // For memset #include -- cgit v1.3.1 From c5422a5c48984f4ea2a5fb6b22f6778183002f68 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 23 Feb 2021 12:06:41 -0600 Subject: rp2040: use TU endpoint conventions and remove redundant variables --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 31 ++++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 12 +++++------ src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 ---- 3 files changed, 21 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 95b0963a3..1e67726ac 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -48,20 +48,21 @@ // Init these in dcd_init static uint8_t *next_buffer_ptr; -// Endpoints 0-15, direction 0 for out and 1 for in. +// Endpoints 0-15, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in. static struct hw_endpoint hw_endpoints[16][2] = {0}; -static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) +static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir) { - return &hw_endpoints[num][in]; + return &hw_endpoints[num][dir]; } static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) { uint8_t num = tu_edpt_number(ep_addr); - uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; - return hw_endpoint_get_by_num(num, in); + tusb_dir_t dir = tu_edpt_dir(ep_addr); + return hw_endpoint_get_by_num(num, dir); } + static void _hw_endpoint_alloc(struct hw_endpoint *ep) { uint size = TU_MIN(64, ep->wMaxPacketSize); @@ -102,12 +103,10 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type) { uint8_t num = tu_edpt_number(ep_addr); - bool in = ep_addr & TUSB_DIR_IN_MASK; + tusb_dir_t dir = tu_edpt_dir(ep_addr); ep->ep_addr = ep_addr; - ep->in = in; // For device, IN is a tx transfer and OUT is an rx transfer - ep->rx = in == false; - ep->num = num; + ep->rx = (dir == TUSB_DIR_OUT); // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = num == 0 ? 1u : 0u; @@ -131,7 +130,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMax ep->transfer_type = transfer_type; // Every endpoint has a buffer control register in dpram - if (ep->in) + if (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) { ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; } @@ -143,7 +142,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMax // Clear existing buffer control state *ep->buffer_control = 0; - if (ep->num == 0) + if (tu_edpt_number(ep->ep_addr) == 0) { // EP0 has no endpoint control register because // the buffer offsets are fixed @@ -155,7 +154,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMax else { // Set the endpoint control register (starts at EP1, hence num-1) - if (in) + if (dir == TUSB_DIR_IN) { ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].in; } @@ -259,10 +258,10 @@ static void ep0_0len_status(void) static void _hw_endpoint_stall(struct hw_endpoint *ep) { assert(!ep->stalled); - if (ep->num == 0) + if (tu_edpt_number(ep->ep_addr) == 0) { // A stall on EP0 has to be armed so it can be cleared on the next setup packet - usb_hw_set->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; } _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL); ep->stalled = true; @@ -276,10 +275,10 @@ static void hw_endpoint_stall(uint8_t ep_addr) static void _hw_endpoint_clear_stall(struct hw_endpoint *ep) { - if (ep->num == 0) + if (tu_edpt_number(ep->ep_addr) == 0) { // Probably already been cleared but no harm - usb_hw_clear->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + usb_hw_clear->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; } _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL); ep->stalled = false; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 339297ad6..6c6911f2f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -84,7 +84,7 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m value |= or_mask; if (or_mask & USB_BUF_CTRL_AVAIL) { if (*ep->buffer_control & USB_BUF_CTRL_AVAIL) { - panic("ep %d %s was already available", ep->num, ep_dir_string[ep->in]); + panic("ep %d %s was already available", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); } *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; // 12 cycle delay.. (should be good for 48*12Mhz = 576Mhz) @@ -141,11 +141,11 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) { _hw_endpoint_lock_update(ep, 1); - pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, ep->num, ep_dir_string[ep->in]); + pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); if (ep->active) { // TODO: Is this acceptable for interrupt packets? - pico_warn("WARN: starting new transfer on already active ep %d %s\n", ep->num, ep_dir_string[ep->in]); + pico_warn("WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); hw_endpoint_reset_transfer(ep); } @@ -223,7 +223,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Part way through a transfer if (!ep->active) { - panic("Can't continue xfer on inactive ep %d %s", ep->num, ep_dir_string); + panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string); } // Update EP struct from hardware state @@ -244,7 +244,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) if (ep->len == ep->total_len) { pico_trace("Completed transfer of %d bytes on ep %d %s\n", - ep->len, ep->num, ep_dir_string[ep->in]); + ep->len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); // Notify caller we are done so it can notify the tinyusb // stack _hw_endpoint_lock_update(ep, -1); @@ -263,7 +263,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start) { // Trace - pico_trace("hw_endpoint_xfer ep %d %s", ep->num, ep_dir_string[ep->in]); + pico_trace("hw_endpoint_xfer ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); pico_trace(" total_len %d, start=%d\n", total_len, start); assert(ep->configured); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 7c3234e8d..40b845a88 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -42,10 +42,6 @@ struct hw_endpoint { // Is this a valid struct bool configured; - // EP direction - bool in; - // EP num (not including direction) - uint8_t num; // Transfer direction (i.e. IN is rx for host but tx for device) // allows us to common up transfer functions -- cgit v1.3.1 From e00178a1afefc9b0b2d4fc440a6db536a4bb7afe Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 23 Feb 2021 14:04:56 -0600 Subject: rp2040: don't compile in host code when in device mode --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 10 ++++++++++ src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 ++++ 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 339297ad6..80d4c2990 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -44,10 +44,12 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } +#ifdef RP2040_USB_HOST_MODE static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) { ep->last_buf = ep->len + ep->transfer_size == ep->total_len; } +#endif void rp2040_usb_init(void) { @@ -68,7 +70,9 @@ void hw_endpoint_reset_transfer(struct hw_endpoint *ep) { ep->stalled = false; ep->active = false; +#ifdef RP2040_USB_HOST_MODE ep->sent_setup = false; +#endif ep->total_len = 0; ep->len = 0; ep->transfer_size = 0; @@ -122,6 +126,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; ep->next_pid ^= 1u; +#ifdef RP2040_USB_HOST_MODE // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about // trans complete for setup packets being sent @@ -130,6 +135,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) pico_trace("Last buf (%d bytes left)\n", ep->transfer_size); val |= USB_BUF_CTRL_LAST; } +#endif // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address @@ -156,9 +162,11 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize); ep->active = true; ep->user_buf = buffer; +#ifdef RP2040_USB_HOST_MODE // Recalculate if this is the last buffer _hw_endpoint_update_last_buf(ep); ep->buf_sel = 0; +#endif _hw_endpoint_start_next_buffer(ep); _hw_endpoint_lock_update(ep, -1); @@ -232,7 +240,9 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Now we have synced our state with the hardware. Is there more data to transfer? uint remaining_bytes = ep->total_len - ep->len; ep->transfer_size = tu_min32(remaining_bytes, ep->wMaxPacketSize); +#ifdef RP2040_USB_HOST_MODE _hw_endpoint_update_last_buf(ep); +#endif // Can happen because of programmer error so check for it if (ep->len > ep->total_len) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 7c3234e8d..db9845491 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -71,11 +71,13 @@ struct hw_endpoint uint len; // Amount of data with the hardware uint transfer_size; +#ifdef RP2040_USB_HOST_MODE // Only needed for host mode bool last_buf; // HOST BUG. Host will incorrect write status to top half of buffer // control register when doing transfers > 1 packet uint8_t buf_sel; +#endif // User buffer in main memory uint8_t *user_buf; @@ -84,11 +86,13 @@ struct hw_endpoint // Interrupt, bulk, etc uint8_t transfer_type; +#ifdef RP2040_USB_HOST_MODE // Only needed for host uint8_t dev_addr; bool sent_setup; // If interrupt endpoint uint8_t interrupt_num; +#endif }; void rp2040_usb_init(void); -- cgit v1.3.1 From 762f262be76480717227a6f32bd4a190a9d263ea Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Thu, 25 Feb 2021 07:58:54 -0600 Subject: rp2040: requested change from TU_MIN to tu_min16 --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 9c43b6fdb..9d36734b6 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -64,7 +64,7 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) } static void _hw_endpoint_alloc(struct hw_endpoint *ep) { - uint16_t size = TU_MIN(64, ep->wMaxPacketSize); + uint16_t size = tu_min16(64, ep->wMaxPacketSize); // Assumes single buffered for now ep->hw_data_buf = next_buffer_ptr; -- cgit v1.3.1 From 999ef227d0151bae5db09da7a9b3ed3be20ef891 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Thu, 25 Feb 2021 08:45:47 -0600 Subject: rp2040: requested code mode in rp2040_usb.h --- src/portable/raspberrypi/rp2040/rp2040_usb.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index db9845491..3448d2539 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -71,13 +71,6 @@ struct hw_endpoint uint len; // Amount of data with the hardware uint transfer_size; -#ifdef RP2040_USB_HOST_MODE - // Only needed for host mode - bool last_buf; - // HOST BUG. Host will incorrect write status to top half of buffer - // control register when doing transfers > 1 packet - uint8_t buf_sel; -#endif // User buffer in main memory uint8_t *user_buf; @@ -87,6 +80,11 @@ struct hw_endpoint uint8_t transfer_type; #ifdef RP2040_USB_HOST_MODE + // Only needed for host mode + bool last_buf; + // HOST BUG. Host will incorrect write status to top half of buffer + // control register when doing transfers > 1 packet + uint8_t buf_sel; // Only needed for host uint8_t dev_addr; bool sent_setup; -- cgit v1.3.1 From e6e7c73f6e5ff53e3b4869fdc9abfd809d1e50a8 Mon Sep 17 00:00:00 2001 From: Liam Fraser Date: Thu, 25 Feb 2021 15:48:19 +0000 Subject: Update RP2040 hcd_init to have rhport argument. --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index efb2bd430..0f2779453 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -363,9 +363,10 @@ static void hw_endpoint_init(uint8_t dev_addr, const tusb_desc_endpoint_t *ep_de //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(void) +bool hcd_init(uint8_t rhport) { - pico_trace("hcd_init\n"); + pico_trace("hcd_init %d\n", rhport); + assert(rhport == 0); // Reset any previous state rp2040_usb_init(); -- cgit v1.3.1 From 07a04255da4442fb0790130ac65c648d0884255a Mon Sep 17 00:00:00 2001 From: amit verma Date: Thu, 25 Feb 2021 23:13:21 +0530 Subject: initial break request handling --- src/class/cdc/cdc_device.c | 11 +++++++++++ src/class/cdc/cdc_device.h | 3 +++ 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 58f485a5d..5a74b4876 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -396,6 +396,17 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; + case CDC_REQUEST_SEND_BREAK: + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + TU_LOG2(" Send Break\r\n"); + if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + } + break; default: return false; // stall unsupported request } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 62dcd3c0a..d10fe68db 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -133,6 +133,9 @@ static inline bool tud_cdc_write_clear (void); // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t wait_ms); + // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); -- cgit v1.3.1 From 55a46a5c3b7ad3afb70a995954baa6148381b3a5 Mon Sep 17 00:00:00 2001 From: boggyb Date: Fri, 26 Feb 2021 11:00:34 +0530 Subject: Update cdc_device.h Minor api callback change as requested --- src/class/cdc/cdc_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index d10fe68db..0885922c6 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -133,9 +133,6 @@ static inline bool tud_cdc_write_clear (void); // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); -// Invoked when received send break -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t wait_ms); - // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); @@ -148,6 +145,9 @@ TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); // Invoked when line coding is change via SET_LINE_CODING TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ -- cgit v1.3.1 From f6b48c07fca039ea49be49062298e1dc8cc78471 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Feb 2021 14:05:08 +0700 Subject: add rp2040 to host example build --- examples/host/cdc_msc_hid/.only.MCU_RP2040 | 0 examples/host/cdc_msc_hid/CMakeLists.txt | 46 ++++++++++++++++++++++++++++ hw/bsp/rp2040/family.cmake | 9 +++++- src/host/usbh.c | 2 ++ src/osal/osal.h | 1 - src/osal/osal_none.h | 9 +----- src/osal/osal_pico.h | 4 +-- src/portable/raspberrypi/rp2040/rp2040_usb.c | 14 ++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 2 +- 9 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 examples/host/cdc_msc_hid/.only.MCU_RP2040 create mode 100644 examples/host/cdc_msc_hid/CMakeLists.txt (limited to 'src') diff --git a/examples/host/cdc_msc_hid/.only.MCU_RP2040 b/examples/host/cdc_msc_hid/.only.MCU_RP2040 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt new file mode 100644 index 000000000..dc2effde9 --- /dev/null +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -0,0 +1,46 @@ +# use directory name for project id +get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME) +set(PROJECT ${BOARD}-${PROJECT}) + +# TOP is absolute path to root directory of TinyUSB git repo +set(TOP "../../..") +get_filename_component(TOP "${TOP}" REALPATH) + +# Check for -DFAMILY= +if(FAMILY STREQUAL "esp32s2") + cmake_minimum_required(VERSION 3.5) + include(${TOP}/hw/bsp/${FAMILY}/family.cmake) + project(${PROJECT}) + +elseif(FAMILY STREQUAL "rp2040") + cmake_minimum_required(VERSION 3.12) + set(PICO_SDK_PATH ${TOP}/hw/mcu/raspberrypi/pico-sdk) + include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + project(${PROJECT}) + pico_sdk_init() + add_executable(${PROJECT}) + + include(${TOP}/hw/bsp/${FAMILY}/family.cmake) + + # Example source + target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c + ) + + # Example include + target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + + # Example defines + target_compile_definitions(${PROJECT} PUBLIC + CFG_TUSB_OS=OPT_OS_PICO + ) + + target_link_libraries(${PROJECT} pico_stdlib pico_fix_rp2040_usb_device_enumeration) + pico_add_extra_outputs(${PROJECT}) + +else() + message(FATAL_ERROR "Invalid FAMILY specified") +endif() diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index e4f5f47b4..d2e164be5 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -13,8 +13,15 @@ set(SRC_TINYUSB ${TOP}/src/class/net/net_device.c ${TOP}/src/class/usbtmc/usbtmc_device.c ${TOP}/src/class/vendor/vendor_device.c - ${TOP}/src/portable/raspberrypi/${FAMILY}/dcd_rp2040.c + ${TOP}/src/host/hub.c + ${TOP}/src/host/usbh.c + ${TOP}/src/host/usbh_control.c + ${TOP}/src/class/cdc/cdc_host.c + ${TOP}/src/class/hid/hid_host.c + ${TOP}/src/class/msc/msc_host.c ${TOP}/src/portable/raspberrypi/${FAMILY}/rp2040_usb.c + ${TOP}/src/portable/raspberrypi/${FAMILY}/dcd_rp2040.c + ${TOP}/src/portable/raspberrypi/${FAMILY}/hcd_rp2040.c ) target_sources(${PROJECT} PUBLIC diff --git a/src/host/usbh.c b/src/host/usbh.c index 0bc6378b2..a4ee4cb5c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -157,6 +157,7 @@ tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) return (tusb_speed_t) _usbh_devices[dev_addr].speed; } +#if CFG_TUSB_OS == OPT_OS_NONE void osal_task_delay(uint32_t msec) { (void) msec; @@ -164,6 +165,7 @@ void osal_task_delay(uint32_t msec) const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} } +#endif //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) diff --git a/src/osal/osal.h b/src/osal/osal.h index 02e3e0a06..28bdf479c 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -66,7 +66,6 @@ typedef void (*osal_task_func_t)( void * ); //--------------------------------------------------------------------+ // OSAL Porting API //--------------------------------------------------------------------+ -//static inline void osal_task_delay(uint32_t msec); //------------- Semaphore -------------// static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index ea6818621..a1f997cf2 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -34,14 +34,7 @@ //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -//static inline void osal_task_delay(uint32_t msec) -//{ -// (void) msec; -// // TODO only used by Host stack, will implement using SOF -// -//// uint32_t start = tusb_hal_millis(); -//// while ( ( tusb_hal_millis() - start ) < msec ) {} -//} + //--------------------------------------------------------------------+ // Binary Semaphore API diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index de964a7a0..c277af271 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -39,12 +39,10 @@ //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -#ifndef RP2040_USB_HOST_MODE static inline void osal_task_delay(uint32_t msec) { - sleep_ms(msec); + sleep_ms(msec); } -#endif //--------------------------------------------------------------------+ // Binary Semaphore API diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 4e0850af8..4866f0fea 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -43,7 +43,7 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) { ep->last_buf = ep->len + ep->transfer_size == ep->total_len; @@ -69,7 +69,7 @@ void hw_endpoint_reset_transfer(struct hw_endpoint *ep) { ep->stalled = false; ep->active = false; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED ep->sent_setup = false; #endif ep->total_len = 0; @@ -92,7 +92,7 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; // 12 cycle delay.. (should be good for 48*12Mhz = 576Mhz) // Don't need delay in host mode as host is in charge -#ifndef RP2040_USB_HOST_MODE +#if !TUSB_OPT_HOST_ENABLED __asm volatile ( "b 1f\n" "1: b 1f\n" @@ -125,7 +125,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; ep->next_pid ^= 1u; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about // trans complete for setup packets being sent @@ -161,7 +161,7 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); ep->active = true; ep->user_buf = buffer; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // Recalculate if this is the last buffer _hw_endpoint_update_last_buf(ep); ep->buf_sel = 0; @@ -181,7 +181,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // tag::host_buf_sel_fix[] if (ep->buf_sel == 1) { @@ -239,7 +239,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Now we have synced our state with the hardware. Is there more data to transfer? uint16_t remaining_bytes = ep->total_len - ep->len; ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED _hw_endpoint_update_last_buf(ep); #endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index e92b70416..986bd2f07 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -79,7 +79,7 @@ struct hw_endpoint // Interrupt, bulk, etc uint8_t transfer_type; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // Only needed for host mode bool last_buf; // HOST BUG. Host will incorrect write status to top half of buffer -- cgit v1.3.1 From eb44b6f7db33e89c0d1dc369d914f18388deff53 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Fri, 26 Feb 2021 11:07:34 -0600 Subject: rp2040: improve _hw_endpoint_init() --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 787add15d..d32870439 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -102,8 +102,8 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - uint8_t num = tu_edpt_number(ep_addr); - tusb_dir_t dir = tu_edpt_dir(ep_addr); + const uint8_t num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); ep->ep_addr = ep_addr; // For device, IN is a tx transfer and OUT is an rx transfer ep->rx = (dir == TUSB_DIR_OUT); @@ -130,7 +130,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t ep->transfer_type = transfer_type; // Every endpoint has a buffer control register in dpram - if (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) + if (dir == TUSB_DIR_IN) { ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; } @@ -142,7 +142,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t // Clear existing buffer control state *ep->buffer_control = 0; - if (tu_edpt_number(ep->ep_addr) == 0) + if (num == 0) { // EP0 has no endpoint control register because // the buffer offsets are fixed -- cgit v1.3.1 From 72c1066ed152916cb99dee5e5749b78916d4ba76 Mon Sep 17 00:00:00 2001 From: Duddie Date: Sun, 28 Feb 2021 22:18:35 +0800 Subject: Fix Endpoint descriptor for MIDI Device Endpoint descriptor should be 9 bytes in length (not 7) and have two extra bytes at the end: bRefresh and bSynchAddress According to MIDI USB specification 1.0 (6.2.1 Standard MS Bulk Data Endpoint Descriptor) --- src/device/usbd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index b5f7dceba..8aeb6aff8 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -289,10 +289,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* MS Out Jack (External), connected to In Jack Embedded */\ 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 -#define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) +#define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ /* MS Endpoint (connected to embedded jack) */\ (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables -- cgit v1.3.1 From 1676a836d137bc67e24b778abe72addfa835ff20 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Mar 2021 14:54:12 +0700 Subject: fix rp2040 host build --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 0f2779453..224f6ef21 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -291,14 +291,16 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t assert(ep->buffer_control); assert(ep->hw_data_buf); - uint8_t num = tu_edpt_number(ep_addr); + uint8_t const num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + bool in = ep_addr & TUSB_DIR_IN_MASK; ep->ep_addr = ep_addr; ep->dev_addr = dev_addr; - ep->in = in; + // For host, IN to host == RX, anything else rx == false - ep->rx = in == true; - ep->num = num; + ep->rx = (dir == TUSB_DIR_IN); + // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = num == 0 ? 1u : 0u; ep->wMaxPacketSize = wMaxPacketSize; @@ -327,9 +329,9 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t // device address // endpoint number / direction // preamble - uint32_t reg = dev_addr | (ep->num << USB_ADDR_ENDP1_ENDPOINT_LSB); + uint32_t reg = dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB); // Assert the interrupt endpoint is IN_TO_HOST - assert(ep->in); + assert(dir == TUSB_DIR_IN); if (need_pre(dev_addr)) { @@ -462,7 +464,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * if (ep == &epx) { // That has set up buffer control, endpoint control etc // for host we have to initiate the transfer - usb_hw->dev_addr_ctrl = dev_addr | ep->num << USB_ADDR_ENDP_ENDPOINT_LSB; + usb_hw->dev_addr_ctrl = dev_addr | (tu_edpt_number(ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB); uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base; flags |= ep->rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS; // Set pre if we are a low speed device on full speed hub -- cgit v1.3.1 From 9d5e3691706f3f17edd701310b967c729240a507 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Mar 2021 23:24:36 +0700 Subject: rp2040 add disconnection detection - also use dcd_event_bus_reset() - Add TODO for suspend, resume later on (need to test with/without vbus detection). --- src/device/usbd.c | 21 ++++++++------ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 43 ++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 4fc221888..911977eb0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -992,11 +992,15 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) switch (event->event_id) { case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); + // UNPLUGGED event can be bouncing, only processing if we are currently connected + if ( _usbd_dev.connected ) + { + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + osal_queue_send(_usbd_q, event, in_isr); + } break; case DCD_EVENT_SOF: @@ -1004,9 +1008,10 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) break; case DCD_EVENT_SUSPEND: - // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the - // SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well. - // We will skip handling SUSPEND/RESUME event if not currently connected + // NOTE: When plugging/unplugging device, the D+/D- state are unstable and + // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). + // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish + // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected if ( _usbd_dev.connected ) { _usbd_dev.suspended = 1; diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index d32870439..84dce0248 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -317,13 +317,45 @@ static void dcd_rp2040_irq(void) pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); usb_hw->dev_addr_ctrl = 0; handled |= USB_INTS_BUS_RESET_BITS; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX rp2040_usb_device_enumeration_fix(); #endif } + if (status & USB_INTS_DEV_CONN_DIS_BITS) + { + handled |= USB_INTS_DEV_CONN_DIS_BITS; + + if ( usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS ) + { + // Connected: nothing to do + }else + { + // Disconnected + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS; + } + +#if 0 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection + if (status & USB_INTS_DEV_SUSPEND_BITS) + { + handled |= USB_INTS_DEV_SUSPEND_BITS; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS; + } + + if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) + { + handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS; + } +#endif + if (status ^ handled) { panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); @@ -364,8 +396,10 @@ void dcd_init (uint8_t rhport) // Enable individual controller IRQS here. Processor interrupt enable will be used // for the global interrupt enable... + // TODO Enable SUSPEND & RESUME interrupt usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; - usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS; + usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS | + USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */ ; dcd_connect(rhport); } @@ -393,8 +427,9 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { - pico_info("dcd_remote_wakeup %d is not supported yet\n", rhport); + pico_info("dcd_remote_wakeup %d\n", rhport); assert(rhport == 0); + usb_hw_set->sie_ctrl = USB_SIE_CTRL_RESUME_BITS; } // disconnect by disabling internal pull-up resistor on D+/D- @@ -402,6 +437,7 @@ void dcd_disconnect(uint8_t rhport) { pico_info("dcd_disconnect %d\n", rhport); assert(rhport == 0); + //TU_LOG2("dcd_disconnect\n"); usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } @@ -410,6 +446,7 @@ void dcd_connect(uint8_t rhport) { pico_info("dcd_connect %d\n", rhport); assert(rhport == 0); + //TU_LOG2("dcd_connect\n"); usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } -- cgit v1.3.1 From a298045f6c57ed3bad23ce44a1944016a882e08c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Mar 2021 23:30:21 +0700 Subject: clean up --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 84dce0248..ba708081c 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -437,7 +437,6 @@ void dcd_disconnect(uint8_t rhport) { pico_info("dcd_disconnect %d\n", rhport); assert(rhport == 0); - //TU_LOG2("dcd_disconnect\n"); usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } @@ -446,7 +445,6 @@ void dcd_connect(uint8_t rhport) { pico_info("dcd_connect %d\n", rhport); assert(rhport == 0); - //TU_LOG2("dcd_connect\n"); usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } -- cgit v1.3.1 From a655a4169e4a7be4b547f012643a86d198d46b1f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 01:18:49 +0700 Subject: add note for MIDI (audio v1.0) endpoint decriptor use 9 bytes instead of 7 --- src/device/usbd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 8aeb6aff8..56615b081 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -254,6 +254,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// +// MIDI v1.0 is based on Audio v1.0 #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ @@ -291,7 +292,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ + /* Endpoint: Note Audio v1.0's endpoint has 9 bytes instead of 7 */\ 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ /* MS Endpoint (connected to embedded jack) */\ (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables -- cgit v1.3.1 From 8cabbb28df17bfcb7c549a98aec4eef4e70bba12 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 18:36:18 +0700 Subject: fix enum walkaround forever check for SE0 when pull up is disabled --- hw/bsp/rp2040/family.c | 4 +-- hw/bsp/rp2040/family.mk | 1 + src/portable/raspberrypi/rp2040/dcd_rp2040.c | 43 +++++++++++++++++++--------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 5 +++- 4 files changed, 37 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index ec4088ea1..9995c23d7 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -80,8 +80,8 @@ bool __no_inline_not_in_flash_func(get_bootsel_button)() { #if defined(LOGGER_RTT) // Logging with RTT -// If RTT Control Block is not found by 'Auto Detection` -// try to use 'Search Range` with '0x20000000 0x10000' +// - If RTT Control Block is not found by 'Auto Detection` try to use 'Search Range` with '0x20000000 0x10000' +// - SWD speed is rather slow around 1000Khz #include "pico/stdio/driver.h" #include "SEGGER_RTT.h" diff --git a/hw/bsp/rp2040/family.mk b/hw/bsp/rp2040/family.mk index 9aacae37d..b0fb58ff7 100644 --- a/hw/bsp/rp2040/family.mk +++ b/hw/bsp/rp2040/family.mk @@ -1,3 +1,4 @@ FAMILY_SUBMODULES = hw/mcu/raspberrypi/pico-sdk JLINK_DEVICE = rp2040_m0_0 +PYOCD_TARGET = rp2040 diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index ba708081c..f844a0c65 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -312,18 +312,7 @@ static void dcd_rp2040_irq(void) hw_handle_buff_status(); } - if (status & USB_INTS_BUS_RESET_BITS) - { - pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); - usb_hw->dev_addr_ctrl = 0; - handled |= USB_INTS_BUS_RESET_BITS; - dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); - usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; -#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX - rp2040_usb_device_enumeration_fix(); -#endif - } - + // SE0 for 2 us or more, usually together with Bus Reset if (status & USB_INTS_DEV_CONN_DIS_BITS) { handled |= USB_INTS_DEV_CONN_DIS_BITS; @@ -340,7 +329,35 @@ static void dcd_rp2040_irq(void) usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS; } -#if 0 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection + // SE0 for 2.5 us or more + if (status & USB_INTS_BUS_RESET_BITS) + { + pico_trace("BUS RESET\n"); + usb_hw->dev_addr_ctrl = 0; + handled |= USB_INTS_BUS_RESET_BITS; + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; + +#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX + // Only run enumeration walk-around if pull up is enabled + if ( usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS ) + { + rp2040_usb_device_enumeration_fix(); + } +#endif + } + +#if 0 + // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection + + /* Note from pico datasheet 4.1.2.6.4 (v1.2) + * If you enable the suspend interrupt, it is likely you will see a suspend interrupt when + * the device is first connected but the bus is idle. The bus can be idle for a few ms before + * the host begins sending start of frame packets. You will also see a suspend interrupt + * when the device is disconnected if you do not have a VBUS detect circuit connected. This is + * because without VBUS detection, it is impossible to tell the difference between + * being disconnected and suspended. + */ if (status & USB_INTS_DEV_SUSPEND_BITS) { handled |= USB_INTS_DEV_SUSPEND_BITS; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index c6f6d7231..98ffea9a3 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -60,8 +60,11 @@ void rp2040_usb_init(void) memset(usb_hw, 0, sizeof(*usb_hw)); memset(usb_dpram, 0, sizeof(*usb_dpram)); - // Mux to phy + // Mux the controller to the onboard usb phy usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + + // Force VBUS detect so the device thinks it is plugged into a host + // TODO support VBUs detect usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; } -- cgit v1.3.1 From 33a29c9e4ca9aebb3469c8f8114365acc3614321 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 19:30:08 +0700 Subject: add midi comment --- src/class/midi/midi_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 325fc4669..29019cc1d 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -387,6 +387,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint p_midi->ep_out = ep_addr; } + // Class Specific MIDI Stream endpoint descriptor drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); -- cgit v1.3.1 From eeea19c0ab1c6e66c56eabac49e2c0f190e9a080 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 11:33:03 +0700 Subject: usbd ack SET_INTERFACE if it is not implemented by class driver. --- src/device/usbd.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 911977eb0..ca5a482fc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -699,13 +699,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE if ( !invoke_class_control(rhport, driver, p_request) ) { - // For GET_INTERFACE, it is mandatory to respond even if the class - // driver doesn't use alternate settings. - TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && - TUSB_REQ_GET_INTERFACE == p_request->bRequest); + // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class + // driver doesn't use alternate settings or implement this + TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + }else if (TUSB_REQ_SET_INTERFACE == p_request->bRequest) + { + tud_control_status(rhport, p_request); + } else + { + return false; + } } } break; -- cgit v1.3.1 From e864bda6272485a33398ebf0f139607bf244f237 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 17:21:59 +0700 Subject: fix build with freertos --- src/common/tusb_fifo.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6e0ecdc82..0276c8044 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -53,6 +53,7 @@ extern "C" { #endif #if CFG_FIFO_MUTEX +#include "osal/osal.h" #define tu_fifo_mutex_t osal_mutex_t #endif -- cgit v1.3.1 From a397353916db36d925f5aec654fc66d5ca09f427 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 17:58:39 +0700 Subject: fix ci build with rp2040 --- src/common/tusb_fifo.h | 2 +- src/device/dcd.h | 5 +++-- src/osal/osal_pico.h | 4 ++-- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 0276c8044..62ee942d2 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -109,7 +109,7 @@ static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mute bool tu_fifo_write (tu_fifo_t* f, void const * p_data); uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); -uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); +uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); diff --git a/src/device/dcd.h b/src/device/dcd.h index 89f8760d0..1e5b3ff1e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -134,8 +134,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +// Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack +// This API is optional, may be useful for register-based for transferring data. +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index c277af271..bae1217eb 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -143,7 +143,7 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context - assert(!qhdl->ff.mutex); + //assert(!qhdl->ff.mutex); _osal_q_lock(qhdl); bool success = tu_fifo_read(&qhdl->ff, data); @@ -157,7 +157,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context - assert(!qhdl->ff.mutex); + //assert(!qhdl->ff.mutex); _osal_q_lock(qhdl); bool success = tu_fifo_write(&qhdl->ff, data); diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index f844a0c65..7731078b5 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -35,7 +35,8 @@ #include "pico/fix/rp2040_usb_device_enumeration.h" #endif - +#include "osal/osal.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ -- cgit v1.3.1