diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 5c21590c4..952245cb1 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -71,18 +71,17 @@ TU_ATTR_ALWAYS_INLINE static inline hw_endpoint_t *hw_endpoint_get_by_addr(uint8 // 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) { - const uint8_t epnum = tu_edpt_number(ep_addr); - ep->ep_addr = ep_addr; ep->next_pid = 0u; ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; // Clear existing buffer control state - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); *buf_ctrl_reg = 0; // allocated hw buffer + 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]; @@ -104,16 +103,9 @@ static void hw_endpoint_init(hw_endpoint_t *ep, uint8_t ep_addr, uint16_t wMaxPa } } -// Init, allocate buffer and enable endpoint -static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - const uint8_t epnum = tu_edpt_number(ep_addr); - const tusb_dir_t dir = tu_edpt_dir(ep_addr); - hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); - - hw_endpoint_init(ep, ep_addr, wMaxPacketSize, transfer_type); - - // Set endpoint control register to enable (EP0 has no endpoint control register) +static void hw_endpoint_enable(hw_endpoint_t *ep, uint8_t transfer_type) { io_rw_32 *ctrl_reg = hwep_ctrl_reg_device(ep); + // 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); @@ -121,14 +113,24 @@ static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t } } +// Init and enable endpoint +static void hw_endpoint_open(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { + const uint8_t epnum = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); + hw_endpoint_t *ep = hw_endpoint_get(epnum, dir); + + hw_endpoint_init(ep, ep_addr, wMaxPacketSize, transfer_type); + hw_endpoint_enable(ep, transfer_type); +} + static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { // Abort any pending transfer - // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1). - // Which means we are not guaranteed to safely abort pending transfer on B0 and B1. const uint8_t dir = (uint8_t)tu_edpt_dir(ep->ep_addr); - const uint8_t epnum = tu_edpt_number(ep->ep_addr); + const uint8_t epnum = tu_edpt_number(ep->ep_addr); const uint32_t abort_mask = TU_BIT((epnum << 1) | (dir ? 0 : 1)); + // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1). + // Which means we are not guaranteed to safely abort pending transfer on B0 and B1. if (rp2040_chip_version() >= 2) { usb_hw_set->abort = abort_mask; while ((usb_hw->abort_done & abort_mask) != abort_mask) {} @@ -139,8 +141,8 @@ static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { buf_ctrl |= USB_BUF_CTRL_DATA1_PID; } - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_set(buf_ctrl_reg, buf_ctrl); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); hw_endpoint_reset_transfer(ep); if (rp2040_chip_version() >= 2) { @@ -265,15 +267,12 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { #if FORCE_VBUS_DETECT == 0 // Since we force VBUS detect On, device will always think it is connected and // couldn't distinguish between disconnect and suspend - if (status & USB_INTS_DEV_CONN_DIS_BITS) - { + 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 ) - { + if (usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS) { // Connected: nothing to do - }else - { + } else { // Disconnected dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); } @@ -295,8 +294,10 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void) { #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX // Only run enumeration workaround if pull up is enabled - if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS) rp2040_usb_device_enumeration_fix(); -#endif + if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS) { + rp2040_usb_device_enumeration_fix(); + } + #endif } /* Note from pico datasheet 4.1.2.6.4 (v1.2) @@ -458,7 +459,6 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req 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; } @@ -485,13 +485,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) } ep->wMaxPacketSize = ep_desc->wMaxPacketSize; - // Set control register to enable endpoint - io_rw_32 *ctrl_reg = hwep_ctrl_reg_device(ep); - if (ctrl_reg != NULL) { - const uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | ((uint32_t)TUSB_XFER_ISOCHRONOUS << EP_CTRL_BUFFER_TYPE_LSB) | - hw_data_offset(ep->hw_data_buf); - *ctrl_reg = ctrl_value; - } + hw_endpoint_enable(ep, TUSB_XFER_ISOCHRONOUS); return true; } @@ -522,8 +516,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } // stall and clear current pending buffer, may need to use EP_ABORT - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_set(buf_ctrl_reg, USB_BUF_CTRL_STALL); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_set(buf_ctrl_reg, USB_BUF_CTRL_STALL); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -534,8 +528,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // clear stall also reset toggle to DATA0, ready for next transfer ep->next_pid = 0; - io_rw_32 *buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_clear_mask(buf_ctrl_reg, USB_BUF_CTRL_STALL); + io_rw_32 *buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_clear_mask(buf_ctrl_reg, USB_BUF_CTRL_STALL); } } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 2e5f0fe1f..c4eba0d5f 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -62,22 +62,23 @@ enum { USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS }; -static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) -{ +static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) { uint8_t num = tu_edpt_number(ep_addr); - if ( num == 0 ) return &epx; + if (num == 0) { + return &epx; + } - for ( uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++ ) - { + for (uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { struct hw_endpoint *ep = &ep_pool[i]; - if ( ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr) ) return ep; + if (ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr)) { + return ep; + } } return NULL; } -TU_ATTR_ALWAYS_INLINE static inline uint8_t dev_speed(void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t dev_speed(void) { return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB; } @@ -98,8 +99,7 @@ static void __tusb_irq_path_func(hw_xfer_complete)(struct hw_endpoint *ep, xfer_ hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } -static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_endpoint *ep) -{ +static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_endpoint *ep) { usb_hw_clear->buf_status = bit; // EP may have been stalled? assert(ep->active); @@ -357,8 +357,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t // Finally, enable interrupt that endpoint usb_hw_set->int_ep_ctrl = 1 << (ep->interrupt_num + 1); - // If it's an interrupt endpoint we need to set up the buffer control - // register + // If it's an interrupt endpoint we need to set up the buffer control register } } @@ -456,8 +455,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // reset epx if it is currently active with unplugged device if (epx.configured && epx.active && epx.dev_addr == dev_addr) { epx.configured = false; - *hwep_ctrl_reg_host(&epx) = 0; - *hwep_buf_ctrl_reg_host(&epx) = 0; + *hwep_ctrl_reg_host(&epx) = 0; + *hwbuf_ctrl_reg_host(&epx) = 0; hw_endpoint_reset_transfer(&epx); } @@ -472,8 +471,8 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // unconfigure the endpoint ep->configured = false; - *hwep_ctrl_reg_host(ep) = 0; - *hwep_buf_ctrl_reg_host(ep) = 0; + *hwep_ctrl_reg_host(ep) = 0; + *hwbuf_ctrl_reg_host(ep) = 0; hw_endpoint_reset_transfer(ep); } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 5258b9705..798129e0c 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -88,7 +88,7 @@ void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) { ep->user_buf = 0; } -void __tusb_irq_path_func(hwep_buf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask) { +void __tusb_irq_path_func(hwbuf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask) { const bool is_host = rp2usb_is_host_mode(); uint32_t value = 0; uint32_t buf_ctrl = *buf_ctrl_reg; @@ -101,7 +101,7 @@ void __tusb_irq_path_func(hwep_buf_ctrl_update)(io_rw_32 *buf_ctrl_reg, uint32_t value |= or_mask; if (or_mask & USB_BUF_CTRL_AVAIL) { if (buf_ctrl & USB_BUF_CTRL_AVAIL) { - panic("buf_ctrl @%lX already available", (uintptr_t)buf_ctrl_reg); + panic("buf_ctrl @ 0x%lX already available", (uintptr_t)buf_ctrl_reg); } *buf_ctrl_reg = value & ~USB_BUF_CTRL_AVAIL; @@ -162,15 +162,15 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) #if CFG_TUH_ENABLED const bool is_host = rp2usb_is_host_mode(); if (is_host) { - buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); - ep_ctrl_reg = hwep_ctrl_reg_host(ep); - is_rx = (dir == TUSB_DIR_IN); + buf_ctrl_reg = hwbuf_ctrl_reg_host(ep); + ep_ctrl_reg = hwep_ctrl_reg_host(ep); + is_rx = (dir == TUSB_DIR_IN); } else #endif { - buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); - ep_ctrl_reg = hwep_ctrl_reg_device(ep); - is_rx = (dir == TUSB_DIR_OUT); + buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); + ep_ctrl_reg = hwep_ctrl_reg_device(ep); + is_rx = (dir == TUSB_DIR_OUT); } // always compute and start with buffer 0 @@ -209,7 +209,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address - hwep_buf_ctrl_set(buf_ctrl_reg, buf_ctrl); + hwbuf_ctrl_set(buf_ctrl_reg, buf_ctrl); } void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t total_len) { @@ -287,13 +287,13 @@ static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { #if CFG_TUH_ENABLED const bool is_host = rp2usb_is_host_mode(); if (is_host) { - buf_ctrl_reg = hwep_buf_ctrl_reg_host(ep); + buf_ctrl_reg = hwbuf_ctrl_reg_host(ep); ep_ctrl_reg = hwep_ctrl_reg_host(ep); is_rx = (dir == TUSB_DIR_IN); } else #endif { - buf_ctrl_reg = hwep_buf_ctrl_reg_device(ep); + buf_ctrl_reg = hwbuf_ctrl_reg_device(ep); ep_ctrl_reg = hwep_ctrl_reg_device(ep); is_rx = (dir == TUSB_DIR_OUT); } @@ -327,8 +327,8 @@ static void __tusb_irq_path_func(hwep_xfer_sync)(hw_endpoint_t *ep) { ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; - io_rw_32 *buf_ctrl_reg = is_host ? hwep_buf_ctrl_reg_host(ep) : hwep_buf_ctrl_reg_device(ep); - hwep_buf_ctrl_set(buf_ctrl_reg, 0); + io_rw_32 *buf_ctrl_reg = is_host ? hwbuf_ctrl_reg_host(ep) : hwbuf_ctrl_reg_device(ep); + hwbuf_ctrl_set(buf_ctrl_reg, 0); usb_hw->abort &= ~TU_BIT(ep_id); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index e9fed73de..368bb6509 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -1,10 +1,6 @@ #ifndef RP2040_COMMON_H_ #define RP2040_COMMON_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 - #include "common/tusb_common.h" #include "pico.h" @@ -13,6 +9,10 @@ #include "hardware/resets.h" #include "hardware/timer.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 + #if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX) #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif @@ -36,6 +36,9 @@ #define __tusb_irq_path_func(x) x #endif +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ #define usb_hw_set ((usb_hw_t *) hw_set_alias_untyped(usb_hw)) #define usb_hw_clear ((usb_hw_t *) hw_clear_alias_untyped(usb_hw)) @@ -56,9 +59,9 @@ typedef struct hw_endpoint uint16_t wMaxPacketSize; uint8_t *hw_data_buf; // Buffer pointer in usb dpram - uint8_t *user_buf; // User buffer in main memory // Current transfer information + uint8_t *user_buf; // User buffer in main memory uint16_t remaining_len; uint16_t xferred_len; @@ -108,7 +111,7 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_device(struct hw_end 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 *hwep_buf_ctrl_reg_device(struct hw_endpoint *ep) { +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; @@ -123,30 +126,29 @@ TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_ctrl_reg_host(struct hw_endpo return &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; } -TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwep_buf_ctrl_reg_host(struct hw_endpoint *ep) { - if (ep->transfer_type == TUSB_XFER_CONTROL) { +TU_ATTR_ALWAYS_INLINE static inline io_rw_32 *hwbuf_ctrl_reg_host(struct hw_endpoint *ep) { + if (tu_edpt_number(ep->ep_addr) == 0) { return &usbh_dpram->epx_buf_ctrl; } return &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; } #endif - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -void hwep_buf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); +void hwbuf_ctrl_update(io_rw_32 *buf_ctrl_reg, uint32_t and_mask, uint32_t or_mask); -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwep_buf_ctrl_update(buf_ctrl_reg, 0, value); +TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwbuf_ctrl_update(buf_ctrl_reg, 0, value); } -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_set_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwep_buf_ctrl_update(buf_ctrl_reg, ~value, value); +TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_set_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwbuf_ctrl_update(buf_ctrl_reg, ~value, value); } -TU_ATTR_ALWAYS_INLINE static inline void hwep_buf_ctrl_clear_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { - hwep_buf_ctrl_update(buf_ctrl_reg, ~value, 0); +TU_ATTR_ALWAYS_INLINE static inline void hwbuf_ctrl_clear_mask(io_rw_32 *buf_ctrl_reg, uint32_t value) { + hwbuf_ctrl_update(buf_ctrl_reg, ~value, 0); } static inline uintptr_t hw_data_offset(uint8_t *buf) {