Merge branch 'feature/usb_hs_support_v5.1' into 'release/v5.1'

feat(usb/host): Add High Speed enumeration types (backport v5.1)

See merge request espressif/esp-idf!28059
This commit is contained in:
morris 2024-02-28 11:46:17 +08:00
commit bbb7c4c756
10 changed files with 273 additions and 273 deletions

View File

@ -19,7 +19,7 @@ NOTE: Thread safety is the responsibility fo the HAL user. All USB Host HAL
#include <stddef.h> #include <stddef.h>
#include "soc/usb_dwc_struct.h" #include "soc/usb_dwc_struct.h"
#include "hal/usb_dwc_ll.h" #include "hal/usb_dwc_ll.h"
#include "hal/usb_types_private.h" #include "hal/usb_dwc_types.h"
#include "hal/assert.h" #include "hal/assert.h"
#if SOC_USB_OTG_SUPPORTED #if SOC_USB_OTG_SUPPORTED
@ -28,6 +28,30 @@ NOTE: Thread safety is the responsibility fo the HAL user. All USB Host HAL
// ----------------------- Configs ------------------------- // ----------------------- Configs -------------------------
/**
* @brief Possible FIFO biases
*/
typedef enum {
USB_HAL_FIFO_BIAS_DEFAULT, /**< Default (balanced) FIFO sizes */
USB_HAL_FIFO_BIAS_RX, /**< Bigger RX FIFO for IN transfers */
USB_HAL_FIFO_BIAS_PTX, /**< Bigger periodic TX FIFO for ISOC OUT transfers */
} usb_hal_fifo_bias_t;
/**
* @brief MPS limits based on FIFO configuration
*
* In bytes
*
* The resulting values depend on
* 1. FIFO total size (chip specific)
* 2. Set FIFO bias
*/
typedef struct {
unsigned int in_mps; /**< Maximum packet size of IN packet */
unsigned int non_periodic_out_mps; /**< Maximum packet size of BULK and CTRL OUT packets */
unsigned int periodic_out_mps; /**< Maximum packet size of INTR and ISOC OUT packets */
} usb_hal_fifo_mps_limits_t;
/** /**
* @brief FIFO size configuration structure * @brief FIFO size configuration structure
*/ */
@ -104,7 +128,7 @@ typedef enum {
typedef struct { typedef struct {
union { union {
struct { struct {
usb_priv_xfer_type_t type: 2; /**< The type of endpoint */ usb_dwc_xfer_type_t type: 2; /**< The type of endpoint */
uint32_t bEndpointAddress: 8; /**< Endpoint address (containing endpoint number and direction) */ uint32_t bEndpointAddress: 8; /**< Endpoint address (containing endpoint number and direction) */
uint32_t mps: 11; /**< Maximum Packet Size */ uint32_t mps: 11; /**< Maximum Packet Size */
uint32_t dev_addr: 8; /**< Device Address */ uint32_t dev_addr: 8; /**< Device Address */
@ -135,9 +159,9 @@ typedef struct {
}; };
uint32_t val; uint32_t val;
} flags; /**< Flags regarding channel's status and information */ } flags; /**< Flags regarding channel's status and information */
usb_dwc_host_chan_regs_t *regs; /**< Pointer to the channel's register set */ usb_dwc_host_chan_regs_t *regs; /**< Pointer to the channel's register set */
usb_dwc_hal_chan_error_t error; /**< The last error that occurred on the channel */ usb_dwc_hal_chan_error_t error; /**< The last error that occurred on the channel */
usb_priv_xfer_type_t type; /**< The transfer type of the channel */ usb_dwc_xfer_type_t type; /**< The transfer type of the channel */
void *chan_ctx; /**< Context variable for the owner of the channel */ void *chan_ctx; /**< Context variable for the owner of the channel */
} usb_dwc_hal_chan_t; } usb_dwc_hal_chan_t;
@ -148,8 +172,10 @@ typedef struct {
//Context //Context
usb_dwc_dev_t *dev; /**< Pointer to base address of DWC_OTG registers */ usb_dwc_dev_t *dev; /**< Pointer to base address of DWC_OTG registers */
//Host Port related //Host Port related
uint32_t *periodic_frame_list; /**< Pointer to scheduling frame list */ uint32_t *periodic_frame_list; /**< Pointer to scheduling frame list */
usb_hal_frame_list_len_t frame_list_len; /**< Length of the periodic scheduling frame list */ usb_hal_frame_list_len_t frame_list_len; /**< Length of the periodic scheduling frame list */
//FIFO related
const usb_dwc_hal_fifo_config_t *fifo_config; /**< FIFO sizes configuration */
union { union {
struct { struct {
uint32_t dbnc_lock_enabled: 1; /**< Debounce lock enabled */ uint32_t dbnc_lock_enabled: 1; /**< Debounce lock enabled */
@ -218,21 +244,28 @@ void usb_dwc_hal_deinit(usb_dwc_hal_context_t *hal);
void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal); void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal);
/** /**
* @brief Set FIFO sizes * @brief Set FIFO bias
* *
* This function will set the sizes of each of the FIFOs (RX FIFO, Non-periodic TX FIFO, Periodic TX FIFO) and must be * This function will set the sizes of each of the FIFOs (RX FIFO, Non-periodic TX FIFO, Periodic TX FIFO) and must be
* called at least once before allocating the channel. Based on the type of endpoints (and the endpionts' MPS), there * called at least once before allocating the channel. Based on the type of endpoints (and the endpoints' MPS), there
* may be situations where this function may need to be called again to resize the FIFOs. If resizing FIFOs dynamically, * may be situations where this function may need to be called again to resize the FIFOs. If resizing FIFOs dynamically,
* it is the user's responsibility to ensure there are no active channels when this function is called. * it is the user's responsibility to ensure there are no active channels when this function is called.
* *
* @note The totol size of all the FIFOs must be less than or equal to USB_DWC_FIFO_TOTAL_USABLE_LINES
* @note After a port reset, the FIFO size registers will reset to their default values, so this function must be called * @note After a port reset, the FIFO size registers will reset to their default values, so this function must be called
* again post reset. * again post reset.
* *
* @param hal Context of the HAL layer * @param[in] hal Context of the HAL layer
* @param fifo_config FIFO configuration * @param[in] fifo_bias FIFO bias configuration
*/ */
void usb_dwc_hal_set_fifo_size(usb_dwc_hal_context_t *hal, const usb_dwc_hal_fifo_config_t *fifo_config); void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bias_t fifo_bias);
/**
* @brief Get MPS limits
*
* @param[in] hal Context of the HAL layer
* @param[out] mps_limits MPS limits
*/
void usb_dwc_hal_get_mps_limits(usb_dwc_hal_context_t *hal, usb_hal_fifo_mps_limits_t *mps_limits);
// ---------------------------------------------------- Host Port ------------------------------------------------------ // ---------------------------------------------------- Host Port ------------------------------------------------------
@ -465,14 +498,14 @@ 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 * @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 * @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_dwc_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) static inline usb_dwc_speed_t usb_dwc_hal_port_get_conn_speed(usb_dwc_hal_context_t *hal)
{ {
return usb_dwc_ll_hprt_get_speed(hal->dev); return usb_dwc_ll_hprt_get_speed(hal->dev);
} }

View File

@ -13,7 +13,7 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "soc/usb_dwc_struct.h" #include "soc/usb_dwc_struct.h"
#include "hal/usb_types_private.h" #include "hal/usb_dwc_types.h"
#include "hal/misc.h" #include "hal/misc.h"
@ -33,6 +33,67 @@ Todo: Check sizes again and express this macro in terms of DWC config options (I
------------------------------ DWC Configuration ------------------------------- ------------------------------ DWC Configuration -------------------------------
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */
/**
* @brief Default FIFO sizes (see 2.1.2.4 for programming guide)
*
* RXFIFO
* - Recommended: ((LPS/4) * 2) + 2
* - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 48 - 48 = 104
* - Worst case can accommodate two packets of 204 bytes, or one packet of 408
* NPTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 3 packets: (64/4) * 3 = 48
* - Worst case can accommodate three packets of 64 bytes or one packet of 192
* PTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 3 packets: (64/4) * 3 = 48
* - Worst case can accommodate three packets of 64 bytes or one packet of 192
*/
#define USB_DWC_FIFO_RX_LINES_DEFAULT 104
#define USB_DWC_FIFO_NPTX_LINES_DEFAULT 48
#define USB_DWC_FIFO_PTX_LINES_DEFAULT 48
/**
* @brief FIFO sizes that bias to giving RX FIFO more capacity
*
* RXFIFO
* - Recommended: ((LPS/4) * 2) + 2
* - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 32 - 16 = 152
* - Worst case can accommodate two packets of 300 bytes or one packet of 600 bytes
* NPTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 1 packets: (64/4) * 1 = 16
* - Worst case can accommodate one packet of 64 bytes
* PTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 3 packets: (64/4) * 2 = 32
* - Worst case can accommodate two packets of 64 bytes or one packet of 128
*/
#define USB_DWC_FIFO_RX_LINES_BIASRX 152
#define USB_DWC_FIFO_NPTX_LINES_BIASRX 16
#define USB_DWC_FIFO_PTX_LINES_BIASRX 32
/**
* @brief FIFO sizes that bias to giving Periodic TX FIFO more capacity (i.e., ISOC OUT)
*
* RXFIFO
* - Recommended: ((LPS/4) * 2) + 2
* - Actual: Assume LPS is 64, and 2 packets: ((64/4) * 2) + 2 = 34
* - Worst case can accommodate two packets of 64 bytes or one packet of 128
* NPTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 1 packets: (64/4) * 1 = 16
* - Worst case can accommodate one packet of 64 bytes
* PTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 34 - 16 = 150
* - Worst case can accommodate two packets of 300 bytes or one packet of 600 bytes
*/
#define USB_DWC_FIFO_RX_LINES_BIASTX 34
#define USB_DWC_FIFO_NPTX_LINES_BIASTX 16
#define USB_DWC_FIFO_PTX_LINES_BIASTX 150
/* /*
* List of relevant DWC configurations. See DWC OTG databook Chapter 3 for more * List of relevant DWC configurations. See DWC OTG databook Chapter 3 for more
* details. * details.
@ -446,7 +507,7 @@ static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw)
* @param hw Start address of the DWC_OTG registers * @param hw Start address of the DWC_OTG registers
* @param speed Speed to initialize the host port at * @param speed Speed to initialize the host port at
*/ */
static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_priv_speed_t speed) static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
{ {
hw->hcfg_reg.descdma = 1; //Enable scatt/gatt hw->hcfg_reg.descdma = 1; //Enable scatt/gatt
hw->hcfg_reg.fslssupp = 1; //FS/LS support only hw->hcfg_reg.fslssupp = 1; //FS/LS support only
@ -455,13 +516,13 @@ static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_priv_spee
Note: It seems like our PHY has an implicit 8 divider applied when in LS mode, Note: It seems like our PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/ */
hw->hcfg_reg.fslspclksel = (speed == USB_PRIV_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only
hw->hcfg_reg.perschedena = 0; //Disable perio sched hw->hcfg_reg.perschedena = 0; //Disable perio sched
} }
// ----------------------------- HFIR Register --------------------------------- // ----------------------------- HFIR Register ---------------------------------
static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_priv_speed_t speed) static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
{ {
usb_dwc_hfir_reg_t hfir; usb_dwc_hfir_reg_t hfir;
hfir.val = hw->hfir_reg.val; hfir.val = hw->hfir_reg.val;
@ -471,7 +532,7 @@ static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_priv_spee
Note: It seems like our PHY has an implicit 8 divider applied when in LS mode, Note: It seems like our PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/ */
hfir.frint = (speed == USB_PRIV_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS
hw->hfir_reg.val = hfir.val; hw->hfir_reg.val = hfir.val;
} }
@ -554,19 +615,9 @@ static inline uint32_t usb_dwc_ll_hflbaddr_get_base_addr(usb_dwc_dev_t *hw)
// ----------------------------- HPRT Register --------------------------------- // ----------------------------- HPRT Register ---------------------------------
static inline usb_priv_speed_t usb_dwc_ll_hprt_get_speed(usb_dwc_dev_t *hw) static inline usb_dwc_speed_t usb_dwc_ll_hprt_get_speed(usb_dwc_dev_t *hw)
{ {
usb_priv_speed_t speed; return (usb_dwc_speed_t)hw->hprt_reg.prtspd;
//esp32-s2 and esp32-s3 only support FS or LS
switch (hw->hprt_reg.prtspd) {
case 1:
speed = USB_PRIV_SPEED_FULL;
break;
default:
speed = USB_PRIV_SPEED_LOW;
break;
}
return speed;
} }
static inline uint32_t usb_dwc_ll_hprt_get_test_ctl(usb_dwc_dev_t *hw) static inline uint32_t usb_dwc_ll_hprt_get_test_ctl(usb_dwc_dev_t *hw)
@ -725,24 +776,9 @@ static inline void usb_dwc_ll_hcchar_set_dev_addr(volatile usb_dwc_host_chan_reg
chan->hcchar_reg.devaddr = addr; chan->hcchar_reg.devaddr = addr;
} }
static inline void usb_dwc_ll_hcchar_set_ep_type(volatile usb_dwc_host_chan_regs_t *chan, usb_priv_xfer_type_t type) static inline void usb_dwc_ll_hcchar_set_ep_type(volatile usb_dwc_host_chan_regs_t *chan, usb_dwc_xfer_type_t type)
{ {
uint32_t ep_type; chan->hcchar_reg.eptype = (uint32_t)type;
switch (type) {
case USB_PRIV_XFER_TYPE_CTRL:
ep_type = 0;
break;
case USB_PRIV_XFER_TYPE_ISOCHRONOUS:
ep_type = 1;
break;
case USB_PRIV_XFER_TYPE_BULK:
ep_type = 2;
break;
default: //USB_PRIV_XFER_TYPE_INTR
ep_type = 3;
break;
}
chan->hcchar_reg.eptype = ep_type;
} }
//Indicates whether channel is commuunicating with a LS device connected via a FS hub. Setting this bit to 1 will cause //Indicates whether channel is commuunicating with a LS device connected via a FS hub. Setting this bit to 1 will cause
@ -767,7 +803,7 @@ static inline void usb_dwc_ll_hcchar_set_mps(volatile usb_dwc_host_chan_regs_t *
chan->hcchar_reg.mps = mps; chan->hcchar_reg.mps = mps;
} }
static inline void usb_dwc_ll_hcchar_init(volatile usb_dwc_host_chan_regs_t *chan, int dev_addr, int ep_num, int mps, usb_priv_xfer_type_t type, bool is_in, bool is_ls) static inline void usb_dwc_ll_hcchar_init(volatile usb_dwc_host_chan_regs_t *chan, int dev_addr, int ep_num, int mps, usb_dwc_xfer_type_t type, bool is_in, bool is_ls)
{ {
//Sets all persistent fields of the channel over its lifetimez //Sets all persistent fields of the channel over its lifetimez
usb_dwc_ll_hcchar_set_dev_addr(chan, dev_addr); usb_dwc_ll_hcchar_set_dev_addr(chan, dev_addr);

View File

@ -1,16 +1,8 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// You may obtain a copy of the License at */
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/* /*
Note: This header file contains USB2.0 related types and macros that can be used by code specific to the DWC_OTG Note: This header file contains USB2.0 related types and macros that can be used by code specific to the DWC_OTG
@ -28,21 +20,26 @@ extern "C"
/** /**
* @brief USB speeds supported by the DWC OTG controller * @brief USB speeds supported by the DWC OTG controller
*
* @note usb_dwc_speed_t enum values must match the values of the DWC_OTG prtspd register field
*/ */
typedef enum { typedef enum {
USB_PRIV_SPEED_FULL, USB_DWC_SPEED_HIGH = 0,
USB_PRIV_SPEED_LOW, USB_DWC_SPEED_FULL = 1,
} usb_priv_speed_t; USB_DWC_SPEED_LOW = 2,
} usb_dwc_speed_t;
/** /**
* @brief USB transfer types supported by the DWC OTG controller * @brief USB transfer types supported by the DWC OTG controller
*
* @note usb_dwc_xfer_type_t enum values must match the values of the DWC_OTG hcchar register field
*/ */
typedef enum { typedef enum {
USB_PRIV_XFER_TYPE_CTRL, USB_DWC_XFER_TYPE_CTRL = 0,
USB_PRIV_XFER_TYPE_ISOCHRONOUS, USB_DWC_XFER_TYPE_ISOCHRONOUS = 1,
USB_PRIV_XFER_TYPE_BULK, USB_DWC_XFER_TYPE_BULK = 2,
USB_PRIV_XFER_TYPE_INTR, USB_DWC_XFER_TYPE_INTR = 3,
} usb_priv_xfer_type_t; } usb_dwc_xfer_type_t;
/** /**
* @brief Enumeration of different possible lengths of the periodic frame list * @brief Enumeration of different possible lengths of the periodic frame list

View File

@ -6,7 +6,8 @@
#pragma once #pragma once
#include "usb_types_private.h" #include <stdbool.h>
#include "usb_dwc_types.h"
#include "usb_phy_types.h" #include "usb_phy_types.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "soc/usb_wrap_struct.h" #include "soc/usb_wrap_struct.h"
@ -66,7 +67,7 @@ void usb_phy_hal_int_load_conf_host(usb_phy_hal_context_t *hal);
* @param hal Context of the HAL layer * @param hal Context of the HAL layer
* @param speed USB speed * @param speed USB speed
*/ */
void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_priv_speed_t speed); void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_phy_speed_t speed);
/** /**
* @brief Enable/Disable test mode for internal PHY to mimick host-device disconnection * @brief Enable/Disable test mode for internal PHY to mimick host-device disconnection

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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -55,6 +55,7 @@ typedef enum {
USB_PHY_SPEED_UNDEFINED, USB_PHY_SPEED_UNDEFINED,
USB_PHY_SPEED_LOW, /**< USB Low Speed (1.5 Mbit/s) */ USB_PHY_SPEED_LOW, /**< USB Low Speed (1.5 Mbit/s) */
USB_PHY_SPEED_FULL, /**< USB Full Speed (12 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_MAX,
} usb_phy_speed_t; } usb_phy_speed_t;

View File

@ -27,6 +27,35 @@
#define CORE_REG_GHWCFG3 0x00C804B5 #define CORE_REG_GHWCFG3 0x00C804B5
#define CORE_REG_GHWCFG4 0xD3F0A030 #define CORE_REG_GHWCFG4 0xD3F0A030
// ----------------------- Configs -------------------------
/**
* @brief Default FIFO sizes (see 2.1.2.4 for programming guide)
*/
const usb_dwc_hal_fifo_config_t fifo_config_default = {
.rx_fifo_lines = USB_DWC_FIFO_RX_LINES_DEFAULT,
.nptx_fifo_lines = USB_DWC_FIFO_NPTX_LINES_DEFAULT,
.ptx_fifo_lines = USB_DWC_FIFO_PTX_LINES_DEFAULT,
};
/**
* @brief FIFO sizes that bias to giving RX FIFO more capacity
*/
const usb_dwc_hal_fifo_config_t fifo_config_bias_rx = {
.rx_fifo_lines = USB_DWC_FIFO_RX_LINES_BIASRX,
.nptx_fifo_lines = USB_DWC_FIFO_NPTX_LINES_BIASRX,
.ptx_fifo_lines = USB_DWC_FIFO_PTX_LINES_BIASRX,
};
/**
* @brief FIFO sizes that bias to giving Periodic TX FIFO more capacity (i.e., ISOC OUT)
*/
const usb_dwc_hal_fifo_config_t fifo_config_bias_ptx = {
.rx_fifo_lines = USB_DWC_FIFO_RX_LINES_BIASTX,
.nptx_fifo_lines = USB_DWC_FIFO_NPTX_LINES_BIASTX,
.ptx_fifo_lines = USB_DWC_FIFO_PTX_LINES_BIASTX,
};
// -------------------- Configurable ----------------------- // -------------------- Configurable -----------------------
/** /**
@ -162,8 +191,23 @@ void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal)
memset(hal->channels.hdls, 0, sizeof(usb_dwc_hal_chan_t *) * USB_DWC_NUM_HOST_CHAN); memset(hal->channels.hdls, 0, sizeof(usb_dwc_hal_chan_t *) * USB_DWC_NUM_HOST_CHAN);
} }
void usb_dwc_hal_set_fifo_size(usb_dwc_hal_context_t *hal, const usb_dwc_hal_fifo_config_t *fifo_config) void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bias_t fifo_bias)
{ {
const usb_dwc_hal_fifo_config_t *fifo_config;
switch (fifo_bias) {
case USB_HAL_FIFO_BIAS_DEFAULT:
fifo_config = &fifo_config_default;
break;
case USB_HAL_FIFO_BIAS_RX:
fifo_config = &fifo_config_bias_rx;
break;
case USB_HAL_FIFO_BIAS_PTX:
fifo_config = &fifo_config_bias_ptx;
break;
default:
abort();
}
HAL_ASSERT((fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines + fifo_config->ptx_fifo_lines) <= USB_DWC_FIFO_TOTAL_USABLE_LINES); HAL_ASSERT((fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines + fifo_config->ptx_fifo_lines) <= USB_DWC_FIFO_TOTAL_USABLE_LINES);
//Check that none of the channels are active //Check that none of the channels are active
for (int i = 0; i < USB_DWC_NUM_HOST_CHAN; i++) { for (int i = 0; i < USB_DWC_NUM_HOST_CHAN; i++) {
@ -179,9 +223,21 @@ void usb_dwc_hal_set_fifo_size(usb_dwc_hal_context_t *hal, const usb_dwc_hal_fif
usb_dwc_ll_grstctl_flush_nptx_fifo(hal->dev); usb_dwc_ll_grstctl_flush_nptx_fifo(hal->dev);
usb_dwc_ll_grstctl_flush_ptx_fifo(hal->dev); usb_dwc_ll_grstctl_flush_ptx_fifo(hal->dev);
usb_dwc_ll_grstctl_flush_rx_fifo(hal->dev); usb_dwc_ll_grstctl_flush_rx_fifo(hal->dev);
hal->fifo_config = fifo_config;
hal->flags.fifo_sizes_set = 1; hal->flags.fifo_sizes_set = 1;
} }
void usb_dwc_hal_get_mps_limits(usb_dwc_hal_context_t *hal, usb_hal_fifo_mps_limits_t *mps_limits)
{
HAL_ASSERT(hal && mps_limits);
HAL_ASSERT(hal->flags.fifo_sizes_set);
const usb_dwc_hal_fifo_config_t *fifo_config = hal->fifo_config;
mps_limits->in_mps = (fifo_config->rx_fifo_lines - 2) * 4; // Two lines are reserved for status quadlets internally by USB_DWC
mps_limits->non_periodic_out_mps = fifo_config->nptx_fifo_lines * 4;
mps_limits->periodic_out_mps = fifo_config->ptx_fifo_lines * 4;
}
// ---------------------------------------------------- Host Port ------------------------------------------------------ // ---------------------------------------------------- Host Port ------------------------------------------------------
static inline void debounce_lock_enable(usb_dwc_hal_context_t *hal) static inline void debounce_lock_enable(usb_dwc_hal_context_t *hal)
@ -193,7 +249,7 @@ static inline void debounce_lock_enable(usb_dwc_hal_context_t *hal)
void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal) void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal)
{ {
usb_priv_speed_t speed = usb_dwc_ll_hprt_get_speed(hal->dev); usb_dwc_speed_t speed = usb_dwc_ll_hprt_get_speed(hal->dev);
//Host Configuration //Host Configuration
usb_dwc_ll_hcfg_set_defaults(hal->dev, speed); usb_dwc_ll_hcfg_set_defaults(hal->dev, speed);
//Configure HFIR //Configure HFIR
@ -238,7 +294,7 @@ bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan
void usb_dwc_hal_chan_free(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj) void usb_dwc_hal_chan_free(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj)
{ {
if (chan_obj->type == USB_PRIV_XFER_TYPE_INTR || chan_obj->type == USB_PRIV_XFER_TYPE_ISOCHRONOUS) { if (chan_obj->type == USB_DWC_XFER_TYPE_INTR || chan_obj->type == USB_DWC_XFER_TYPE_ISOCHRONOUS) {
//Unschedule this channel //Unschedule this channel
for (int i = 0; i < hal->frame_list_len; i++) { for (int i = 0; i < hal->frame_list_len; i++) {
hal->periodic_frame_list[i] &= ~(1 << chan_obj->flags.chan_idx); hal->periodic_frame_list[i] &= ~(1 << chan_obj->flags.chan_idx);
@ -271,7 +327,7 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t
//Save channel type //Save channel type
chan_obj->type = ep_char->type; chan_obj->type = ep_char->type;
//If this is a periodic endpoint/channel, set its schedule in the frame list //If this is a periodic endpoint/channel, set its schedule in the frame list
if (ep_char->type == USB_PRIV_XFER_TYPE_ISOCHRONOUS || ep_char->type == USB_PRIV_XFER_TYPE_INTR) { if (ep_char->type == USB_DWC_XFER_TYPE_ISOCHRONOUS || ep_char->type == USB_DWC_XFER_TYPE_INTR) {
HAL_ASSERT((int)ep_char->periodic.interval <= (int)hal->frame_list_len); //Interval cannot exceed the length of the frame list HAL_ASSERT((int)ep_char->periodic.interval <= (int)hal->frame_list_len); //Interval cannot exceed the length of the frame list
//Find the effective offset in the frame list (in case the phase_offset_frames > interval) //Find the effective offset in the frame list (in case the phase_offset_frames > interval)
int offset = ep_char->periodic.phase_offset_frames % ep_char->periodic.interval; int offset = ep_char->periodic.phase_offset_frames % ep_char->periodic.interval;

View File

@ -42,10 +42,10 @@ void usb_phy_hal_int_load_conf_host(usb_phy_hal_context_t *hal)
usb_phy_ll_int_load_conf(hal->wrap_dev, false, true, false, true); usb_phy_ll_int_load_conf(hal->wrap_dev, false, true, false, true);
} }
void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_priv_speed_t speed) void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_phy_speed_t speed)
{ {
// DEVICE - downstream // DEVICE - downstream
if (speed == USB_PRIV_SPEED_LOW) { if (speed == USB_PHY_SPEED_LOW) {
// LS: dm_pu = 1 // LS: dm_pu = 1
usb_phy_ll_int_load_conf(hal->wrap_dev, false, false, true, false); usb_phy_ll_int_load_conf(hal->wrap_dev, false, false, true, false);
} else { } else {

View File

@ -12,14 +12,11 @@
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "soc/interrupts.h" // For interrupt index
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_rom_gpio.h"
#include "hal/usb_dwc_hal.h" #include "hal/usb_dwc_hal.h"
#include "hal/usb_types_private.h" #include "hal/usb_dwc_types.h"
#include "soc/gpio_pins.h"
#include "soc/gpio_sig_map.h"
#include "esp_private/periph_ctrl.h"
#include "hcd.h" #include "hcd.h"
#include "usb_private.h" #include "usb_private.h"
#include "usb/usb_types_ch9.h" #include "usb/usb_types_ch9.h"
@ -36,102 +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 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_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. #define NUM_PORTS 1 // The controller only has one port.
// ----------------------- Configs ------------------------- // ----------------------- 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)
*
* RXFIFO
* - Recommended: ((LPS/4) * 2) + 2
* - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 48 - 48 = 104
* - Worst case can accommodate two packets of 204 bytes, or one packet of 408
* NPTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 3 packets: (64/4) * 3 = 48
* - Worst case can accommodate three packets of 64 bytes or one packet of 192
* PTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 3 packets: (64/4) * 3 = 48
* - Worst case can accommodate three packets of 64 bytes or one packet of 192
*/
const usb_dwc_hal_fifo_config_t fifo_config_default = {
.rx_fifo_lines = 104,
.nptx_fifo_lines = 48,
.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
*
* RXFIFO
* - Recommended: ((LPS/4) * 2) + 2
* - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 32 - 16 = 152
* - Worst case can accommodate two packets of 300 bytes or one packet of 600 bytes
* NPTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 1 packets: (64/4) * 1 = 16
* - Worst case can accommodate one packet of 64 bytes
* PTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 3 packets: (64/4) * 2 = 32
* - Worst case can accommodate two packets of 64 bytes or one packet of 128
*/
const usb_dwc_hal_fifo_config_t fifo_config_bias_rx = {
.rx_fifo_lines = 152,
.nptx_fifo_lines = 16,
.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)
*
* RXFIFO
* - Recommended: ((LPS/4) * 2) + 2
* - Actual: Assume LPS is 64, and 2 packets: ((64/4) * 2) + 2 = 34
* - Worst case can accommodate two packets of 64 bytes or one packet of 128
* NPTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Assume LPS is 64, and 1 packets: (64/4) * 1 = 16
* - Worst case can accommodate one packet of 64 bytes
* PTXFIFO
* - Recommended: (LPS/4) * 2
* - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 34 - 16 = 150
* - Worst case can accommodate two packets of 300 bytes or one packet of 600 bytes
*/
const usb_dwc_hal_fifo_config_t fifo_config_bias_ptx = {
.rx_fifo_lines = 34,
.nptx_fifo_lines = 16,
.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 FRAME_LIST_LEN USB_HAL_FRAME_LIST_LEN_32
#define NUM_BUFFERS 2 #define NUM_BUFFERS 2
@ -307,8 +214,7 @@ struct port_obj {
} flags; } flags;
bool initialized; bool initialized;
// FIFO biasing related // FIFO biasing related
const usb_dwc_hal_fifo_config_t *fifo_config; usb_hal_fifo_bias_t fifo_bias; // Bias is saved so it can be reconfigured upon reset
const fifo_mps_limits_t *fifo_mps_limits;
// Port callback and context // Port callback and context
hcd_port_callback_t callback; hcd_port_callback_t callback;
void *callback_arg; void *callback_arg;
@ -401,7 +307,7 @@ static void _buffer_exec(pipe_t *pipe);
*/ */
static inline bool _buffer_check_done(pipe_t *pipe) static inline bool _buffer_check_done(pipe_t *pipe)
{ {
if (pipe->ep_char.type != USB_PRIV_XFER_TYPE_CTRL) { if (pipe->ep_char.type != USB_DWC_XFER_TYPE_CTRL) {
return true; return true;
} }
// Only control transfers need to be continued // Only control transfers need to be continued
@ -757,6 +663,28 @@ static bool _internal_pipe_event_notify(pipe_t *pipe, bool from_isr)
return ret; return ret;
} }
// ----------------- HAL <-> USB helpers --------------------
static usb_speed_t get_usb_port_speed(usb_dwc_speed_t priv)
{
switch (priv) {
case USB_DWC_SPEED_LOW: return USB_SPEED_LOW;
case USB_DWC_SPEED_FULL: return USB_SPEED_FULL;
case USB_DWC_SPEED_HIGH: return USB_SPEED_HIGH;
default: abort();
}
}
static usb_hal_fifo_bias_t get_hal_fifo_bias(hcd_port_fifo_bias_t public)
{
switch (public) {
case HCD_PORT_FIFO_BIAS_BALANCED: return USB_HAL_FIFO_BIAS_DEFAULT;
case HCD_PORT_FIFO_BIAS_RX: return USB_HAL_FIFO_BIAS_RX;
case HCD_PORT_FIFO_BIAS_PTX: return USB_HAL_FIFO_BIAS_PTX;
default: abort();
}
}
// ----------------- Interrupt Handlers -------------------- // ----------------- Interrupt Handlers --------------------
/** /**
@ -784,7 +712,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: { case USB_DWC_HAL_PORT_EVENT_ENABLED: {
usb_dwc_hal_port_enable(port->hal); // Initialize remaining host port registers 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 = get_usb_port_speed(usb_dwc_hal_port_get_conn_speed(port->hal));
port->state = HCD_PORT_STATE_ENABLED; port->state = HCD_PORT_STATE_ENABLED;
port->flags.conn_dev_ena = 1; port->flags.conn_dev_ena = 1;
// This was triggered by a command, so no event needs to be propagated. // This was triggered by a command, so no event needs to be propagated.
@ -1210,7 +1138,7 @@ static esp_err_t _port_cmd_reset(port_t *port)
goto bailout; goto bailout;
} }
// Set FIFO sizes based on the selected biasing // Set FIFO sizes based on the selected biasing
usb_dwc_hal_set_fifo_size(port->hal, port->fifo_config); usb_dwc_hal_set_fifo_bias(port->hal, port->fifo_bias);
// We start periodic scheduling only after a RESET command since SOFs only start after a reset // We start periodic scheduling only after a RESET command since SOFs only start after a reset
usb_dwc_hal_port_set_frame_list(port->hal, port->frame_list, FRAME_LIST_LEN); usb_dwc_hal_port_set_frame_list(port->hal, port->frame_list, FRAME_LIST_LEN);
usb_dwc_hal_port_periodic_enable(port->hal); usb_dwc_hal_port_periodic_enable(port->hal);
@ -1307,29 +1235,6 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h
HCD_CHECK(port_number > 0 && port_config != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG); HCD_CHECK(port_number > 0 && port_config != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG);
HCD_CHECK(port_number <= NUM_PORTS, ESP_ERR_NOT_FOUND); HCD_CHECK(port_number <= NUM_PORTS, ESP_ERR_NOT_FOUND);
// 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;
}
HCD_ENTER_CRITICAL(); HCD_ENTER_CRITICAL();
HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && !s_hcd_obj->port_obj->initialized, ESP_ERR_INVALID_STATE); HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && !s_hcd_obj->port_obj->initialized, ESP_ERR_INVALID_STATE);
// Port object memory and resources (such as the mutex) already be allocated. Just need to initialize necessary fields only // Port object memory and resources (such as the mutex) already be allocated. Just need to initialize necessary fields only
@ -1338,8 +1243,7 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h
TAILQ_INIT(&port_obj->pipes_active_tailq); TAILQ_INIT(&port_obj->pipes_active_tailq);
port_obj->state = HCD_PORT_STATE_NOT_POWERED; port_obj->state = HCD_PORT_STATE_NOT_POWERED;
port_obj->last_event = HCD_PORT_EVENT_NONE; port_obj->last_event = HCD_PORT_EVENT_NONE;
port_obj->fifo_config = fifo_config; port_obj->fifo_bias = get_hal_fifo_bias(port_config->fifo_bias);
port_obj->fifo_mps_limits = mps_limits;
port_obj->callback = port_config->callback; port_obj->callback = port_config->callback;
port_obj->callback_arg = port_config->callback_arg; port_obj->callback_arg = port_config->callback_arg;
port_obj->context = port_config->context; port_obj->context = port_config->context;
@ -1431,12 +1335,7 @@ esp_err_t hcd_port_get_speed(hcd_port_handle_t port_hdl, usb_speed_t *speed)
HCD_ENTER_CRITICAL(); HCD_ENTER_CRITICAL();
// Device speed is only valid if there is device connected to the port that has been reset // 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); 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); *speed = get_usb_port_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;
}
HCD_EXIT_CRITICAL(); HCD_EXIT_CRITICAL();
return ESP_OK; return ESP_OK;
} }
@ -1512,37 +1411,16 @@ void *hcd_port_get_context(hcd_port_handle_t port_hdl)
esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_t bias) esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_t bias)
{ {
esp_err_t ret; esp_err_t ret;
// Get a pointer to the correct FIFO bias constant values usb_hal_fifo_bias_t hal_bias = get_hal_fifo_bias(bias);
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;
}
// Configure the new FIFO sizes and store the pointers // Configure the new FIFO sizes and store the pointers
port_t *port = (port_t *)port_hdl; port_t *port = (port_t *)port_hdl;
xSemaphoreTake(port->port_mux, portMAX_DELAY); xSemaphoreTake(port->port_mux, portMAX_DELAY);
HCD_ENTER_CRITICAL(); HCD_ENTER_CRITICAL();
// Check that port is in the correct state to update FIFO sizes // Check that port is in the correct state to update FIFO sizes
if (port->initialized && !port->flags.event_pending && port->num_pipes_idle == 0 && port->num_pipes_queued == 0) { 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); usb_dwc_hal_set_fifo_bias(port->hal, hal_bias);
port->fifo_config = fifo_config; port->fifo_bias = hal_bias;
port->fifo_mps_limits = mps_limits;
ret = ESP_OK; ret = ESP_OK;
} else { } else {
ret = ESP_ERR_INVALID_STATE; ret = ESP_ERR_INVALID_STATE;
@ -1629,10 +1507,14 @@ static bool pipe_args_usb_compliance_verification(const hcd_pipe_config_t *pipe_
return true; 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(usb_dwc_hal_context_t *hal, const usb_ep_desc_t * ep_desc)
{ {
assert(hal != NULL);
assert(ep_desc != NULL); assert(ep_desc != NULL);
usb_transfer_type_t type = USB_EP_DESC_GET_XFERTYPE(ep_desc);
usb_hal_fifo_mps_limits_t mps_limits = {0};
usb_dwc_hal_get_mps_limits(hal, &mps_limits);
const usb_transfer_type_t type = USB_EP_DESC_GET_XFERTYPE(ep_desc);
// Check the pipe's interval is not zero // Check the pipe's interval is not zero
if ((type == USB_TRANSFER_TYPE_INTR || type == USB_TRANSFER_TYPE_ISOCHRONOUS) && if ((type == USB_TRANSFER_TYPE_INTR || type == USB_TRANSFER_TYPE_ISOCHRONOUS) &&
@ -1645,12 +1527,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) // Check if pipe MPS exceeds HCD MPS limits (due to DWC FIFO sizing)
int limit; int limit;
if (USB_EP_DESC_GET_EP_DIR(ep_desc)) { // IN if (USB_EP_DESC_GET_EP_DIR(ep_desc)) { // IN
limit = mps_limits->in_mps; limit = mps_limits.in_mps;
} else { // OUT } else { // OUT
if (type == USB_TRANSFER_TYPE_CTRL || type == USB_TRANSFER_TYPE_BULK) { if (type == USB_TRANSFER_TYPE_CTRL || type == USB_TRANSFER_TYPE_BULK) {
limit = mps_limits->non_periodic_out_mps; limit = mps_limits.non_periodic_out_mps;
} else { } else {
limit = mps_limits->periodic_out_mps; limit = mps_limits.periodic_out_mps;
} }
} }
@ -1667,26 +1549,26 @@ static bool pipe_alloc_hcd_support_verification(const usb_ep_desc_t *ep_desc, co
static void pipe_set_ep_char(const hcd_pipe_config_t *pipe_config, usb_transfer_type_t type, bool is_default_pipe, int pipe_idx, usb_speed_t port_speed, usb_dwc_hal_ep_char_t *ep_char) static void pipe_set_ep_char(const hcd_pipe_config_t *pipe_config, usb_transfer_type_t type, bool is_default_pipe, int pipe_idx, usb_speed_t port_speed, usb_dwc_hal_ep_char_t *ep_char)
{ {
// Initialize EP characteristics // Initialize EP characteristics
usb_priv_xfer_type_t hal_xfer_type; usb_dwc_xfer_type_t hal_xfer_type;
switch (type) { switch (type) {
case USB_TRANSFER_TYPE_CTRL: case USB_TRANSFER_TYPE_CTRL:
hal_xfer_type = USB_PRIV_XFER_TYPE_CTRL; hal_xfer_type = USB_DWC_XFER_TYPE_CTRL;
break; break;
case USB_TRANSFER_TYPE_ISOCHRONOUS: case USB_TRANSFER_TYPE_ISOCHRONOUS:
hal_xfer_type = USB_PRIV_XFER_TYPE_ISOCHRONOUS; hal_xfer_type = USB_DWC_XFER_TYPE_ISOCHRONOUS;
break; break;
case USB_TRANSFER_TYPE_BULK: case USB_TRANSFER_TYPE_BULK:
hal_xfer_type = USB_PRIV_XFER_TYPE_BULK; hal_xfer_type = USB_DWC_XFER_TYPE_BULK;
break; break;
default: // USB_TRANSFER_TYPE_INTR default: // USB_TRANSFER_TYPE_INTR
hal_xfer_type = USB_PRIV_XFER_TYPE_INTR; hal_xfer_type = USB_DWC_XFER_TYPE_INTR;
break; break;
} }
ep_char->type = hal_xfer_type; ep_char->type = hal_xfer_type;
if (is_default_pipe) { if (is_default_pipe) {
ep_char->bEndpointAddress = 0; ep_char->bEndpointAddress = 0;
// Set the default pipe's MPS to the worst case MPS for the device's speed // 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 { } else {
ep_char->bEndpointAddress = pipe_config->ep_desc->bEndpointAddress; ep_char->bEndpointAddress = pipe_config->ep_desc->bEndpointAddress;
ep_char->mps = pipe_config->ep_desc->wMaxPacketSize; ep_char->mps = pipe_config->ep_desc->wMaxPacketSize;
@ -1780,7 +1662,7 @@ static esp_err_t _pipe_cmd_flush(pipe_t *pipe)
// URBs were never executed, Update the actual_num_bytes and status // URBs were never executed, Update the actual_num_bytes and status
urb->transfer.actual_num_bytes = 0; urb->transfer.actual_num_bytes = 0;
urb->transfer.status = (canceled) ? USB_TRANSFER_STATUS_CANCELED : USB_TRANSFER_STATUS_NO_DEVICE; urb->transfer.status = (canceled) ? USB_TRANSFER_STATUS_CANCELED : USB_TRANSFER_STATUS_NO_DEVICE;
if (pipe->ep_char.type == USB_PRIV_XFER_TYPE_ISOCHRONOUS) { if (pipe->ep_char.type == USB_DWC_XFER_TYPE_ISOCHRONOUS) {
// Update the URB's isoc packet descriptors as well // Update the URB's isoc packet descriptors as well
for (int pkt_idx = 0; pkt_idx < urb->transfer.num_isoc_packets; pkt_idx++) { for (int pkt_idx = 0; pkt_idx < urb->transfer.num_isoc_packets; pkt_idx++) {
urb->transfer.isoc_packet_desc[pkt_idx].actual_num_bytes = 0; urb->transfer.isoc_packet_desc[pkt_idx].actual_num_bytes = 0;
@ -1840,7 +1722,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 // 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); HCD_CHECK_FROM_CRIT(port->initialized && port->flags.conn_dev_ena, ESP_ERR_INVALID_STATE);
usb_speed_t port_speed = port->speed; 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; int pipe_idx = port->num_pipes_idle + port->num_pipes_queued;
HCD_EXIT_CRITICAL(); HCD_EXIT_CRITICAL();
@ -1861,7 +1742,7 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi
return ESP_ERR_NOT_SUPPORTED; return ESP_ERR_NOT_SUPPORTED;
} }
// Default pipes have a NULL ep_desc thus should skip the HCD support verification // 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(port->hal, pipe_config->ep_desc)) {
return ESP_ERR_NOT_SUPPORTED; return ESP_ERR_NOT_SUPPORTED;
} }
// Allocate the pipe resources // Allocate the pipe resources
@ -2230,11 +2111,11 @@ static void _buffer_fill(pipe_t *pipe)
int mps = pipe->ep_char.mps; int mps = pipe->ep_char.mps;
usb_transfer_t *transfer = &urb->transfer; usb_transfer_t *transfer = &urb->transfer;
switch (pipe->ep_char.type) { switch (pipe->ep_char.type) {
case USB_PRIV_XFER_TYPE_CTRL: { case USB_DWC_XFER_TYPE_CTRL: {
_buffer_fill_ctrl(buffer_to_fill, transfer); _buffer_fill_ctrl(buffer_to_fill, transfer);
break; break;
} }
case USB_PRIV_XFER_TYPE_ISOCHRONOUS: { case USB_DWC_XFER_TYPE_ISOCHRONOUS: {
uint32_t start_idx; uint32_t start_idx;
if (pipe->multi_buffer_control.buffer_num_to_exec == 0) { if (pipe->multi_buffer_control.buffer_num_to_exec == 0) {
// There are no more previously filled buffers to execute. We need to calculate a new start index based on HFNUM and the pipe's schedule // There are no more previously filled buffers to execute. We need to calculate a new start index based on HFNUM and the pipe's schedule
@ -2260,11 +2141,11 @@ static void _buffer_fill(pipe_t *pipe)
_buffer_fill_isoc(buffer_to_fill, transfer, is_in, mps, (int)pipe->ep_char.periodic.interval, start_idx); _buffer_fill_isoc(buffer_to_fill, transfer, is_in, mps, (int)pipe->ep_char.periodic.interval, start_idx);
break; break;
} }
case USB_PRIV_XFER_TYPE_BULK: { case USB_DWC_XFER_TYPE_BULK: {
_buffer_fill_bulk(buffer_to_fill, transfer, is_in, mps); _buffer_fill_bulk(buffer_to_fill, transfer, is_in, mps);
break; break;
} }
case USB_PRIV_XFER_TYPE_INTR: { case USB_DWC_XFER_TYPE_INTR: {
_buffer_fill_intr(buffer_to_fill, transfer, is_in, mps); _buffer_fill_intr(buffer_to_fill, transfer, is_in, mps);
break; break;
} }
@ -2290,7 +2171,7 @@ static void _buffer_exec(pipe_t *pipe)
uint32_t start_idx; uint32_t start_idx;
int desc_list_len; int desc_list_len;
switch (pipe->ep_char.type) { switch (pipe->ep_char.type) {
case USB_PRIV_XFER_TYPE_CTRL: { case USB_DWC_XFER_TYPE_CTRL: {
start_idx = 0; start_idx = 0;
desc_list_len = XFER_LIST_LEN_CTRL; desc_list_len = XFER_LIST_LEN_CTRL;
// Set the channel's direction to OUT and PID to 0 respectively for the the setup stage // Set the channel's direction to OUT and PID to 0 respectively for the the setup stage
@ -2298,17 +2179,17 @@ static void _buffer_exec(pipe_t *pipe)
usb_dwc_hal_chan_set_pid(pipe->chan_obj, 0); // Setup stage always has a PID of DATA0 usb_dwc_hal_chan_set_pid(pipe->chan_obj, 0); // Setup stage always has a PID of DATA0
break; break;
} }
case USB_PRIV_XFER_TYPE_ISOCHRONOUS: { case USB_DWC_XFER_TYPE_ISOCHRONOUS: {
start_idx = buffer_to_exec->flags.isoc.start_idx; start_idx = buffer_to_exec->flags.isoc.start_idx;
desc_list_len = XFER_LIST_LEN_ISOC; desc_list_len = XFER_LIST_LEN_ISOC;
break; break;
} }
case USB_PRIV_XFER_TYPE_BULK: { case USB_DWC_XFER_TYPE_BULK: {
start_idx = 0; start_idx = 0;
desc_list_len = (buffer_to_exec->flags.bulk.zero_len_packet) ? XFER_LIST_LEN_BULK : 1; desc_list_len = (buffer_to_exec->flags.bulk.zero_len_packet) ? XFER_LIST_LEN_BULK : 1;
break; break;
} }
case USB_PRIV_XFER_TYPE_INTR: { case USB_DWC_XFER_TYPE_INTR: {
start_idx = 0; start_idx = 0;
desc_list_len = (buffer_to_exec->flags.intr.zero_len_packet) ? buffer_to_exec->flags.intr.num_qtds + 1 : buffer_to_exec->flags.intr.num_qtds; desc_list_len = (buffer_to_exec->flags.intr.zero_len_packet) ? buffer_to_exec->flags.intr.num_qtds + 1 : buffer_to_exec->flags.intr.num_qtds;
break; break;
@ -2329,7 +2210,7 @@ static void _buffer_exec(pipe_t *pipe)
static void _buffer_exec_cont(pipe_t *pipe) static void _buffer_exec_cont(pipe_t *pipe)
{ {
// This should only ever be called on control transfers // This should only ever be called on control transfers
assert(pipe->ep_char.type == USB_PRIV_XFER_TYPE_CTRL); assert(pipe->ep_char.type == USB_DWC_XFER_TYPE_CTRL);
dma_buffer_block_t *buffer_inflight = pipe->buffers[pipe->multi_buffer_control.rd_idx]; dma_buffer_block_t *buffer_inflight = pipe->buffers[pipe->multi_buffer_control.rd_idx];
bool next_dir_is_in; bool next_dir_is_in;
int next_pid; int next_pid;
@ -2513,19 +2394,19 @@ static void _buffer_parse(pipe_t *pipe)
if (buffer_to_parse->status_flags.pipe_event == HCD_PIPE_EVENT_URB_DONE) { if (buffer_to_parse->status_flags.pipe_event == HCD_PIPE_EVENT_URB_DONE) {
// URB was successful // URB was successful
switch (pipe->ep_char.type) { switch (pipe->ep_char.type) {
case USB_PRIV_XFER_TYPE_CTRL: { case USB_DWC_XFER_TYPE_CTRL: {
_buffer_parse_ctrl(buffer_to_parse); _buffer_parse_ctrl(buffer_to_parse);
break; break;
} }
case USB_PRIV_XFER_TYPE_ISOCHRONOUS: { case USB_DWC_XFER_TYPE_ISOCHRONOUS: {
_buffer_parse_isoc(buffer_to_parse, is_in); _buffer_parse_isoc(buffer_to_parse, is_in);
break; break;
} }
case USB_PRIV_XFER_TYPE_BULK: { case USB_DWC_XFER_TYPE_BULK: {
_buffer_parse_bulk(buffer_to_parse); _buffer_parse_bulk(buffer_to_parse);
break; break;
} }
case USB_PRIV_XFER_TYPE_INTR: { case USB_DWC_XFER_TYPE_INTR: {
_buffer_parse_intr(buffer_to_parse, is_in, mps); _buffer_parse_intr(buffer_to_parse, is_in, mps);
break; break;
} }

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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -24,6 +24,7 @@ extern "C" {
typedef enum { typedef enum {
USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */ USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */
USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */
USB_SPEED_HIGH, /**< USB High Speed (480 Mbit/s) */
} usb_speed_t; } usb_speed_t;
/** /**

View File

@ -141,13 +141,7 @@ 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"); USBPHY_TAG, "set speed not supported");
handle->otg_speed = speed; handle->otg_speed = speed;
usb_priv_speed_t hal_speed = 0; usb_phy_hal_int_load_conf_dev(&(handle->hal_context), speed);
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_phy_hal_int_load_conf_dev(&(handle->hal_context), hal_speed);
return ESP_OK; return ESP_OK;
} }