Merge branch 'refactor/make_usb_hal_independent_backport_v6.0' into 'release/v6.0'

refactor(usb): Make usb hal layer independent (backport v6.0)

See merge request espressif/esp-idf!43249
This commit is contained in:
morris
2025-11-13 10:20:10 +08:00
29 changed files with 167 additions and 115 deletions
+23
View File
@@ -0,0 +1,23 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(includes "include")
set(srcs)
# USB-DWC related source files and USB FSLS PHY wrapper
if(CONFIG_SOC_USB_OTG_SUPPORTED)
list(APPEND srcs "usb_dwc_hal.c" "usb_wrap_hal.c" "${target}/usb_dwc_periph.c")
list(APPEND includes "${target}/include")
endif()
# USB UTMI PHY
if(CONFIG_SOC_USB_UTMI_PHY_NUM GREATER 0)
list(APPEND srcs "usb_utmi_hal.c")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes}
REQUIRES soc hal)
+55
View File
@@ -0,0 +1,55 @@
# ESP Hardware Abstraction Layer for USB Peripheral(s)
> [!NOTE]
> This component is currently in beta. Its API, behavior, and compatibility may change at any time and without notice; backward compatibility is not guaranteed. Use caution when integrating into production systems.
## Overview
The `esp_hal_usb` component provides a **Hardware Abstraction Layer** for USB controllers and PHYs across all ESP-IDF supported targets. USB (Universal Serial Bus) enables communication between the ESP device and USB hosts or devices, supporting various USB speeds and transfer types for data exchange.
## Architecture
The USB HAL is structured in two main sub-layers:
1. **HAL Layer (Upper)**: Defines the operational steps and data structures required to control USB peripherals (e.g., initialization, endpoint configuration, transfer management, PHY control).
2. **Low-Level Layer (Bottom)**: Serves as a translation layer between the HAL and the register files defined in the `soc` component, handling target-specific register configurations.
## Supported USB Controllers and PHYs
This HAL supports various USB controller and PHY types depending on the ESP chip:
- **USB-DWC (DesignWare USB Controller)**: The main USB OTG controller available on:
- ESP32-S2
- ESP32-S3
- ESP32-H4
- ESP32-P4
- **USB WRAP**: A wrapper/peripheral controller that provides additional USB functionality and GPIO matrix integration
- **USB PHY Types**:
- **FSLS (Full Speed/Low Speed) Internal PHY**: Built-in PHY supporting USB Full Speed and Low Speed operation
- **FSLS External PHY**: Support for external FSLS PHY via GPIO matrix
- **UTMI PHY**: UTMI+ compliant PHY interface (available on ESP32-P4)
## Features
- USB controller initialization and configuration
- Endpoint management (IN/OUT endpoints)
- Transfer type support (Control, Bulk, Interrupt, Isochronous)
- USB speed detection and configuration (High Speed, Full Speed, Low Speed)
- FIFO configuration and management
- PHY initialization and control (FSLS and UTMI)
- GPIO matrix signal routing for USB PHY interfaces
- OTG (On-The-Go) signal handling
- Interrupt management and event handling
- Multi-controller support (on chips with multiple USB controllers)
## Usage
The HAL functions primarily serve ESP-IDF USB drivers, primarily the [USB Host stack](https://components.espressif.com/components/espressif/usb).
## Dependencies
- `soc`: Provides chip-specific register definitions
- `hal`: Core hardware abstraction utilities and macros
@@ -164,7 +164,6 @@ typedef struct {
uint8_t *buffer;
} usb_dwc_ll_dma_qtd_t;
/* -----------------------------------------------------------------------------
------------------------------- Global Registers -------------------------------
----------------------------------------------------------------------------- */
@@ -400,18 +399,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw,
{
uint32_t frlisten;
switch (num_entries) {
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
}
hw->hcfg_reg.frlisten = frlisten;
}
@@ -17,7 +17,6 @@
#define USB_WRAP_LL_EXT_PHY_SUPPORTED 0 // Cannot route to an external FSLS PHY
#ifdef __cplusplus
extern "C" {
#endif
@@ -70,11 +69,11 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_srp_sessend_override(usb_wrap_dev
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pin_exchg(usb_wrap_dev_t *hw, bool enable)
{
if (enable) {
hw->wrap_otg_conf.wrap_exchg_pins = 1;
hw->wrap_otg_conf.wrap_exchg_pins = 1;
hw->wrap_otg_conf.wrap_exchg_pins_override = 1;
} else {
hw->wrap_otg_conf.wrap_exchg_pins_override = 0;
hw->wrap_otg_conf.wrap_exchg_pins = 0;
hw->wrap_otg_conf.wrap_exchg_pins_override = 0;
hw->wrap_otg_conf.wrap_exchg_pins = 0;
}
}
@@ -166,7 +166,6 @@ typedef struct {
uint8_t *buffer;
} usb_dwc_ll_dma_qtd_t;
/* -----------------------------------------------------------------------------
------------------------------- Global Registers -------------------------------
----------------------------------------------------------------------------- */
@@ -423,18 +422,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw,
{
uint32_t frlisten;
switch (num_entries) {
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
}
hw->hcfg_reg.frlisten = frlisten;
}
@@ -862,25 +861,25 @@ static inline void usb_dwc_ll_hctsiz_set_sched_info(volatile usb_dwc_host_chan_r
hctsiz.val = chan->hctsiz_reg.val;
uint8_t sched_info_val;
switch (tokens_per_frame) {
case 1:
offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8
sched_info_val = 0b00000001;
break;
case 2:
offset %= 4;
sched_info_val = 0b00010001;
break;
case 4:
offset %= 2;
sched_info_val = 0b01010101;
break;
case 8:
offset = 0;
sched_info_val = 0b11111111;
break;
default:
abort();
break;
case 1:
offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8
sched_info_val = 0b00000001;
break;
case 2:
offset %= 4;
sched_info_val = 0b00010001;
break;
case 4:
offset %= 2;
sched_info_val = 0b01010101;
break;
case 8:
offset = 0;
sched_info_val = 0b11111111;
break;
default:
abort();
break;
}
sched_info_val <<= offset;
hctsiz.xfersize &= ~(0xFF);
@@ -19,7 +19,6 @@
#define USB_WRAP_LL_SELECT_PHY_SUPPORTED 1 // Can swap to another internal FSLS PHY
#ifdef __cplusplus
extern "C" {
#endif
@@ -164,7 +164,6 @@ typedef struct {
uint8_t *buffer;
} usb_dwc_ll_dma_qtd_t;
/* -----------------------------------------------------------------------------
------------------------------- Global Registers -------------------------------
----------------------------------------------------------------------------- */
@@ -398,18 +397,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw,
{
uint32_t frlisten;
switch (num_entries) {
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
}
hw->hcfg_reg.frlisten = frlisten;
}
@@ -17,7 +17,6 @@
#define USB_WRAP_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY
#ifdef __cplusplus
extern "C" {
#endif
@@ -164,7 +164,6 @@ typedef struct {
uint8_t *buffer;
} usb_dwc_ll_dma_qtd_t;
/* -----------------------------------------------------------------------------
------------------------------- Global Registers -------------------------------
----------------------------------------------------------------------------- */
@@ -398,18 +397,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw,
{
uint32_t frlisten;
switch (num_entries) {
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
case USB_HAL_FRAME_LIST_LEN_8:
frlisten = 0;
break;
case USB_HAL_FRAME_LIST_LEN_16:
frlisten = 1;
break;
case USB_HAL_FRAME_LIST_LEN_32:
frlisten = 2;
break;
default: //USB_HAL_FRAME_LIST_LEN_64
frlisten = 3;
break;
}
hw->hcfg_reg.frlisten = frlisten;
}
@@ -18,7 +18,6 @@
#define USB_WRAP_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY
#ifdef __cplusplus
extern "C" {
#endif
@@ -263,7 +263,6 @@ void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal);
*/
bool usb_dwc_hal_fifo_config_is_valid(const usb_dwc_hal_context_t *hal, const usb_dwc_hal_fifo_config_t *config);
/**
* @brief Set the FIFO sizes of the USB-DWC core
*
@@ -759,14 +758,14 @@ static inline void usb_dwc_hal_xfer_desc_fill(void *desc_list, uint32_t desc_idx
usb_dwc_ll_dma_qtd_t *qtd_list = (usb_dwc_ll_dma_qtd_t *)desc_list;
if (flags & USB_DWC_HAL_XFER_DESC_FLAG_IN) {
usb_dwc_ll_qtd_set_in(&qtd_list[desc_idx],
xfer_data_buff, xfer_len,
flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC);
xfer_data_buff, xfer_len,
flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC);
} else {
usb_dwc_ll_qtd_set_out(&qtd_list[desc_idx],
xfer_data_buff,
xfer_len,
flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC,
flags & USB_DWC_HAL_XFER_DESC_FLAG_SETUP);
xfer_data_buff,
xfer_len,
flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC,
flags & USB_DWC_HAL_XFER_DESC_FLAG_SETUP);
}
}
@@ -193,7 +193,6 @@ bool usb_dwc_hal_fifo_config_is_valid(const usb_dwc_hal_context_t *hal, const us
return (used_lines <= hal->constant_config.fifo_size);
}
void usb_dwc_hal_set_fifo_config(usb_dwc_hal_context_t *hal, const usb_dwc_hal_fifo_config_t *config)
{
// Check internal HAL state
@@ -330,12 +329,12 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t
HAL_ASSERT(!chan_obj->flags.active);
//Set the endpoint characteristics of the pipe
usb_dwc_ll_hcchar_init(chan_obj->regs,
ep_char->dev_addr,
ep_char->bEndpointAddress & BENDPOINTADDRESS_NUM_MSK,
ep_char->mps,
ep_char->type,
ep_char->bEndpointAddress & BENDPOINTADDRESS_DIR_MSK,
ep_char->ls_via_fs_hub);
ep_char->dev_addr,
ep_char->bEndpointAddress & BENDPOINTADDRESS_NUM_MSK,
ep_char->mps,
ep_char->type,
ep_char->bEndpointAddress & BENDPOINTADDRESS_DIR_MSK,
ep_char->ls_via_fs_hub);
//Save channel type
chan_obj->type = ep_char->type;
//If this is a periodic endpoint/channel, set its schedule in the frame list
@@ -365,7 +364,7 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t
interval_frame_list = 1;
}
// Schedule the channel in the frame list
for (int i = 0; i < hal->frame_list_len; i+= interval_frame_list) {
for (int i = 0; i < hal->frame_list_len; i += interval_frame_list) {
int index = (offset_frame_list + i) % hal->frame_list_len;
hal->periodic_frame_list[index] |= 1 << chan_obj->flags.chan_idx;
}
+1 -1
View File
@@ -9,7 +9,7 @@ if(${target} STREQUAL "linux")
return()
endif()
set(requires esp_hal_dma)
set(requires esp_hal_dma esp_hal_usb)
# only esp_hw_support/adc_share_hw_ctrl.c requires efuse component
set(priv_requires efuse spi_flash bootloader_support esp_hal_wdt)
-10
View File
@@ -235,16 +235,6 @@ elseif(NOT BOOTLOADER_BUILD)
list(APPEND srcs "usb_serial_jtag_hal.c")
endif()
if(CONFIG_SOC_USB_UTMI_PHY_NUM GREATER 0)
list(APPEND srcs "usb_utmi_hal.c")
endif()
if(CONFIG_SOC_USB_OTG_SUPPORTED)
list(APPEND srcs
"usb_dwc_hal.c"
"usb_wrap_hal.c")
endif()
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED)
# Source files for the legacy touch hal driver
if(CONFIG_SOC_TOUCH_SENSOR_VERSION LESS 3)
-4
View File
@@ -154,10 +154,6 @@ if(CONFIG_SOC_IEEE802154_SUPPORTED)
endif()
endif()
if(CONFIG_SOC_USB_OTG_SUPPORTED)
list(APPEND srcs "${target_folder}/usb_dwc_periph.c")
endif()
if(CONFIG_SOC_DAC_SUPPORTED)
list(APPEND srcs "${target_folder}/dac_periph.c")
endif()
+5 -7
View File
@@ -560,6 +560,9 @@ examples/peripherals/usb/device:
depends_components:
- fatfs
depends_filepatterns:
- components/soc/esp32*/include/soc/usb_dwc_struct.h
- components/esp_hw_support/usb_phy/usb_phy.c
- components/esp_hw_support/include/esp_private/usb_phy.h
- examples/peripherals/usb/device/**/*
examples/peripherals/usb/device/cherryusb_serial_device:
@@ -589,14 +592,9 @@ examples/peripherals/usb/host:
reason: lack of runners with usb_host_flash_disk tag
depends_components:
- fatfs
- esp_hal_usb
depends_filepatterns:
- components/hal/usb*.c
- components/hal/include/hal/usb*.h
- components/hal/esp32*/include/hal/usb*.h
- components/soc/esp32*/usb*.c
- components/soc/include/soc/usb*.h
- components/soc/esp32*/include/soc/usb_dwc_*.h
- components/soc/esp32*/include/soc/usb_wrap_*.h
- components/soc/esp32*/include/soc/usb_dwc_struct.h
- components/esp_hw_support/usb_phy/usb_phy.c
- components/esp_hw_support/include/esp_private/usb_phy.h
- examples/peripherals/usb/host/**/*