feat(usb/host): Add High Speed enumeration types

This commit is contained in:
Tomas Rezucha 2023-11-23 04:00:22 +01:00
parent 925e3e2ed5
commit d9223c6d91
7 changed files with 43 additions and 69 deletions

View File

@ -465,12 +465,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)
{

View File

@ -556,13 +556,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;
}

View File

@ -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;

View File

@ -30,6 +30,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;

View File

@ -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

View File

@ -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;
/**

View File

@ -141,11 +141,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;