From 69d9e7625b398b682de22732f257ae7f19049acb Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Thu, 23 Nov 2023 04:00:22 +0100 Subject: [PATCH] feat(usb/host): Add High Speed enumeration types --- components/hal/include/hal/usb_dwc_hal.h | 4 +- components/hal/include/hal/usb_dwc_ll.h | 8 +- components/hal/include/hal/usb_phy_types.h | 3 +- .../hal/include/hal/usb_types_private.h | 1 + components/usb/hcd_dwc.c | 82 ++++++------------- components/usb/include/usb/usb_types_stack.h | 3 +- components/usb/usb_phy.c | 11 +-- 7 files changed, 43 insertions(+), 69 deletions(-) diff --git a/components/hal/include/hal/usb_dwc_hal.h b/components/hal/include/hal/usb_dwc_hal.h index 438361fc23..d753c16e02 100644 --- a/components/hal/include/hal/usb_dwc_hal.h +++ b/components/hal/include/hal/usb_dwc_hal.h @@ -468,12 +468,12 @@ static inline bool usb_dwc_hal_port_check_if_connected(usb_dwc_hal_context_t *ha } /** - * @brief Check the speed (LS/FS) of the device connected to the host port + * @brief Check the speed of the device connected to the host port * * @note This function should only be called after confirming that a device is connected to the host port * * @param hal Context of the HAL layer - * @return usb_priv_speed_t Speed of the connected device (FS or LS only on the esp32-s2 and esp32-s3) + * @return usb_priv_speed_t Speed of the connected device */ static inline usb_priv_speed_t usb_dwc_hal_port_get_conn_speed(usb_dwc_hal_context_t *hal) { diff --git a/components/hal/include/hal/usb_dwc_ll.h b/components/hal/include/hal/usb_dwc_ll.h index 1bd2d5306e..22b4f2f6b7 100644 --- a/components/hal/include/hal/usb_dwc_ll.h +++ b/components/hal/include/hal/usb_dwc_ll.h @@ -560,13 +560,15 @@ static inline uint32_t usb_dwc_ll_hflbaddr_get_base_addr(usb_dwc_dev_t *hw) static inline usb_priv_speed_t usb_dwc_ll_hprt_get_speed(usb_dwc_dev_t *hw) { - usb_priv_speed_t speed; - //esp32-s2 and esp32-s3 only support FS or LS + usb_priv_speed_t speed = USB_PRIV_SPEED_HIGH; switch (hw->hprt_reg.prtspd) { + case 0: + speed = USB_PRIV_SPEED_HIGH; + break; case 1: speed = USB_PRIV_SPEED_FULL; break; - default: + case 2: speed = USB_PRIV_SPEED_LOW; break; } diff --git a/components/hal/include/hal/usb_phy_types.h b/components/hal/include/hal/usb_phy_types.h index 1f5ac431ef..50636a64dd 100644 --- a/components/hal/include/hal/usb_phy_types.h +++ b/components/hal/include/hal/usb_phy_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -55,6 +55,7 @@ typedef enum { USB_PHY_SPEED_UNDEFINED, USB_PHY_SPEED_LOW, /**< USB Low Speed (1.5 Mbit/s) */ USB_PHY_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ + USB_PHY_SPEED_HIGH, /**< USB High Speed (480 Mbit/s) */ USB_PHY_SPEED_MAX, } usb_phy_speed_t; diff --git a/components/hal/include/hal/usb_types_private.h b/components/hal/include/hal/usb_types_private.h index d3d358688d..1d81b61cc5 100644 --- a/components/hal/include/hal/usb_types_private.h +++ b/components/hal/include/hal/usb_types_private.h @@ -22,6 +22,7 @@ extern "C" * @brief USB speeds supported by the DWC OTG controller */ typedef enum { + USB_PRIV_SPEED_HIGH, USB_PRIV_SPEED_FULL, USB_PRIV_SPEED_LOW, } usb_priv_speed_t; diff --git a/components/usb/hcd_dwc.c b/components/usb/hcd_dwc.c index 19e3165197..3e0aecf040 100644 --- a/components/usb/hcd_dwc.c +++ b/components/usb/hcd_dwc.c @@ -12,14 +12,11 @@ #include "freertos/semphr.h" #include "esp_heap_caps.h" #include "esp_intr_alloc.h" +#include "soc/interrupts.h" // For interrupt index #include "esp_err.h" #include "esp_log.h" -#include "esp_rom_gpio.h" #include "hal/usb_dwc_hal.h" #include "hal/usb_types_private.h" -#include "soc/gpio_pins.h" -#include "soc/gpio_sig_map.h" -#include "esp_private/periph_ctrl.h" #include "hcd.h" #include "usb_private.h" #include "usb/usb_types_ch9.h" @@ -36,18 +33,12 @@ #define RESUME_RECOVERY_MS 20 // Resume recovery of at least 10ms. Make it 20 ms to be safe. This will include the 3 LS bit times of the EOP #define CTRL_EP_MAX_MPS_LS 8 // Largest Maximum Packet Size for Low Speed control endpoints -#define CTRL_EP_MAX_MPS_FS 64 // Largest Maximum Packet Size for Full Speed control endpoints +#define CTRL_EP_MAX_MPS_HSFS 64 // Largest Maximum Packet Size for High & Full Speed control endpoints #define NUM_PORTS 1 // The controller only has one port. // ----------------------- Configs ------------------------- -typedef struct { - int in_mps; - int non_periodic_out_mps; - int periodic_out_mps; -} fifo_mps_limits_t; - /** * @brief Default FIFO sizes (see 2.1.2.4 for programming guide) * @@ -70,12 +61,6 @@ const usb_dwc_hal_fifo_config_t fifo_config_default = { .ptx_fifo_lines = 48, }; -const fifo_mps_limits_t mps_limits_default = { - .in_mps = 408, - .non_periodic_out_mps = 192, - .periodic_out_mps = 192, -}; - /** * @brief FIFO sizes that bias to giving RX FIFO more capacity * @@ -98,12 +83,6 @@ const usb_dwc_hal_fifo_config_t fifo_config_bias_rx = { .ptx_fifo_lines = 32, }; -const fifo_mps_limits_t mps_limits_bias_rx = { - .in_mps = 600, - .non_periodic_out_mps = 64, - .periodic_out_mps = 128, -}; - /** * @brief FIFO sizes that bias to giving Periodic TX FIFO more capacity (i.e., ISOC OUT) * @@ -126,12 +105,6 @@ const usb_dwc_hal_fifo_config_t fifo_config_bias_ptx = { .ptx_fifo_lines = 150, }; -const fifo_mps_limits_t mps_limits_bias_ptx = { - .in_mps = 128, - .non_periodic_out_mps = 64, - .periodic_out_mps = 600, -}; - #define FRAME_LIST_LEN USB_HAL_FRAME_LIST_LEN_32 #define NUM_BUFFERS 2 @@ -308,7 +281,6 @@ struct port_obj { bool initialized; // FIFO biasing related const usb_dwc_hal_fifo_config_t *fifo_config; - const fifo_mps_limits_t *fifo_mps_limits; // Port callback and context hcd_port_callback_t callback; void *callback_arg; @@ -759,6 +731,16 @@ static bool _internal_pipe_event_notify(pipe_t *pipe, bool from_isr) // ----------------- Interrupt Handlers -------------------- +static usb_speed_t speed_priv_to_public(usb_priv_speed_t priv) +{ + switch (priv) { + case USB_PRIV_SPEED_LOW: return USB_SPEED_LOW; + case USB_PRIV_SPEED_FULL: return USB_SPEED_FULL; + case USB_PRIV_SPEED_HIGH: return USB_SPEED_HIGH; + default: abort(); + } +} + /** * @brief Handle a HAL port interrupt and obtain the corresponding port event * @@ -784,7 +766,7 @@ static hcd_port_event_t _intr_hdlr_hprt(port_t *port, usb_dwc_hal_port_event_t h } case USB_DWC_HAL_PORT_EVENT_ENABLED: { usb_dwc_hal_port_enable(port->hal); // Initialize remaining host port registers - port->speed = (usb_dwc_hal_port_get_conn_speed(port->hal) == USB_PRIV_SPEED_FULL) ? USB_SPEED_FULL : USB_SPEED_LOW; + port->speed = speed_priv_to_public(usb_dwc_hal_port_get_conn_speed(port->hal)); port->state = HCD_PORT_STATE_ENABLED; port->flags.conn_dev_ena = 1; // This was triggered by a command, so no event needs to be propagated. @@ -1309,23 +1291,18 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h // Get a pointer to the correct FIFO bias constant values const usb_dwc_hal_fifo_config_t *fifo_config; - const fifo_mps_limits_t *mps_limits; switch (port_config->fifo_bias) { case HCD_PORT_FIFO_BIAS_BALANCED: fifo_config = &fifo_config_default; - mps_limits = &mps_limits_default; break; case HCD_PORT_FIFO_BIAS_RX: fifo_config = &fifo_config_bias_rx; - mps_limits = &mps_limits_bias_rx; break; case HCD_PORT_FIFO_BIAS_PTX: fifo_config = &fifo_config_bias_ptx; - mps_limits = &mps_limits_bias_ptx; break; default: fifo_config = NULL; - mps_limits = NULL; abort(); break; } @@ -1339,7 +1316,6 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h port_obj->state = HCD_PORT_STATE_NOT_POWERED; port_obj->last_event = HCD_PORT_EVENT_NONE; port_obj->fifo_config = fifo_config; - port_obj->fifo_mps_limits = mps_limits; port_obj->callback = port_config->callback; port_obj->callback_arg = port_config->callback_arg; port_obj->context = port_config->context; @@ -1431,12 +1407,7 @@ esp_err_t hcd_port_get_speed(hcd_port_handle_t port_hdl, usb_speed_t *speed) HCD_ENTER_CRITICAL(); // Device speed is only valid if there is device connected to the port that has been reset HCD_CHECK_FROM_CRIT(port->flags.conn_dev_ena, ESP_ERR_INVALID_STATE); - usb_priv_speed_t hal_speed = usb_dwc_hal_port_get_conn_speed(port->hal); - if (hal_speed == USB_PRIV_SPEED_FULL) { - *speed = USB_SPEED_FULL; - } else { - *speed = USB_SPEED_LOW; - } + *speed = speed_priv_to_public(usb_dwc_hal_port_get_conn_speed(port->hal)); HCD_EXIT_CRITICAL(); return ESP_OK; } @@ -1514,23 +1485,18 @@ esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_ esp_err_t ret; // Get a pointer to the correct FIFO bias constant values const usb_dwc_hal_fifo_config_t *fifo_config; - const fifo_mps_limits_t *mps_limits; switch (bias) { case HCD_PORT_FIFO_BIAS_BALANCED: fifo_config = &fifo_config_default; - mps_limits = &mps_limits_default; break; case HCD_PORT_FIFO_BIAS_RX: fifo_config = &fifo_config_bias_rx; - mps_limits = &mps_limits_bias_rx; break; case HCD_PORT_FIFO_BIAS_PTX: fifo_config = &fifo_config_bias_ptx; - mps_limits = &mps_limits_bias_ptx; break; default: fifo_config = NULL; - mps_limits = NULL; abort(); break; } @@ -1542,7 +1508,6 @@ esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_ if (port->initialized && !port->flags.event_pending && port->num_pipes_idle == 0 && port->num_pipes_queued == 0) { usb_dwc_hal_set_fifo_size(port->hal, fifo_config); port->fifo_config = fifo_config; - port->fifo_mps_limits = mps_limits; ret = ESP_OK; } else { ret = ESP_ERR_INVALID_STATE; @@ -1629,10 +1594,14 @@ static bool pipe_args_usb_compliance_verification(const hcd_pipe_config_t *pipe_ return true; } -static bool pipe_alloc_hcd_support_verification(const usb_ep_desc_t *ep_desc, const fifo_mps_limits_t *mps_limits) +static bool pipe_alloc_hcd_support_verification(const usb_ep_desc_t * ep_desc, const usb_dwc_hal_fifo_config_t *fifo_config) { assert(ep_desc != NULL); - usb_transfer_type_t type = USB_EP_DESC_GET_XFERTYPE(ep_desc); + + const uint32_t limit_in_mps = (fifo_config->rx_fifo_lines - 2) * 4; // Two lines are reserved for status quadlets internally by USB_DWC + const uint32_t limit_non_periodic_out_mps = fifo_config->nptx_fifo_lines * 4; + const uint32_t limit_periodic_out_mps = fifo_config->ptx_fifo_lines * 4; + const usb_transfer_type_t type = USB_EP_DESC_GET_XFERTYPE(ep_desc); // Check the pipe's interval is not zero if ((type == USB_TRANSFER_TYPE_INTR || type == USB_TRANSFER_TYPE_ISOCHRONOUS) && @@ -1645,12 +1614,12 @@ static bool pipe_alloc_hcd_support_verification(const usb_ep_desc_t *ep_desc, co // Check if pipe MPS exceeds HCD MPS limits (due to DWC FIFO sizing) int limit; if (USB_EP_DESC_GET_EP_DIR(ep_desc)) { // IN - limit = mps_limits->in_mps; + limit = limit_in_mps; } else { // OUT if (type == USB_TRANSFER_TYPE_CTRL || type == USB_TRANSFER_TYPE_BULK) { - limit = mps_limits->non_periodic_out_mps; + limit = limit_non_periodic_out_mps; } else { - limit = mps_limits->periodic_out_mps; + limit = limit_periodic_out_mps; } } @@ -1686,7 +1655,7 @@ static void pipe_set_ep_char(const hcd_pipe_config_t *pipe_config, usb_transfer_ if (is_default_pipe) { ep_char->bEndpointAddress = 0; // Set the default pipe's MPS to the worst case MPS for the device's speed - ep_char->mps = (pipe_config->dev_speed == USB_SPEED_FULL) ? CTRL_EP_MAX_MPS_FS : CTRL_EP_MAX_MPS_LS; + ep_char->mps = (pipe_config->dev_speed == USB_SPEED_LOW) ? CTRL_EP_MAX_MPS_LS : CTRL_EP_MAX_MPS_HSFS; } else { ep_char->bEndpointAddress = pipe_config->ep_desc->bEndpointAddress; ep_char->mps = pipe_config->ep_desc->wMaxPacketSize; @@ -1840,7 +1809,6 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi // Can only allocate a pipe if the target port is initialized and connected to an enabled device HCD_CHECK_FROM_CRIT(port->initialized && port->flags.conn_dev_ena, ESP_ERR_INVALID_STATE); usb_speed_t port_speed = port->speed; - const fifo_mps_limits_t *mps_limits = port->fifo_mps_limits; int pipe_idx = port->num_pipes_idle + port->num_pipes_queued; HCD_EXIT_CRITICAL(); @@ -1861,7 +1829,7 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi return ESP_ERR_NOT_SUPPORTED; } // Default pipes have a NULL ep_desc thus should skip the HCD support verification - if (!is_default && !pipe_alloc_hcd_support_verification(pipe_config->ep_desc, mps_limits)) { + if (!is_default && !pipe_alloc_hcd_support_verification(pipe_config->ep_desc, port->fifo_config)) { return ESP_ERR_NOT_SUPPORTED; } // Allocate the pipe resources diff --git a/components/usb/include/usb/usb_types_stack.h b/components/usb/include/usb/usb_types_stack.h index 94ab481ee9..00af897182 100644 --- a/components/usb/include/usb/usb_types_stack.h +++ b/components/usb/include/usb/usb_types_stack.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,6 +24,7 @@ extern "C" { typedef enum { USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */ USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ + USB_SPEED_HIGH, /**< USB High Speed (480 Mbit/s) */ } usb_speed_t; /** diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index ec8dc35856..583ed435cc 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -147,11 +147,12 @@ esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t spe USBPHY_TAG, "set speed not supported"); handle->otg_speed = speed; - usb_priv_speed_t hal_speed = 0; - if (speed == USB_PHY_SPEED_LOW) { - hal_speed = USB_PRIV_SPEED_LOW; - } else if (speed == USB_PHY_SPEED_FULL) { - hal_speed = USB_PRIV_SPEED_FULL; + usb_priv_speed_t hal_speed; + switch (speed) { + case USB_PHY_SPEED_LOW: hal_speed = USB_PRIV_SPEED_LOW; break; + case USB_PHY_SPEED_FULL: hal_speed = USB_PRIV_SPEED_FULL; break; + case USB_PHY_SPEED_HIGH: hal_speed = USB_PRIV_SPEED_HIGH; break; + default: abort(); } usb_phy_hal_int_load_conf_dev(&(handle->hal_context), hal_speed); return ESP_OK;