Merge branch 'docs/usb-external-phy' into 'master'

docs(usb): add section on external USB PHY configuration

Closes DOC-3308

See merge request espressif/esp-idf!40670
This commit is contained in:
Igor Masar
2025-08-25 19:37:09 +08:00
7 changed files with 305 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -57,6 +57,88 @@ Hardware Connection
Self-powered devices must also connect VBUS through a voltage divider or comparator. For more details, please refer to :ref:`self-powered-device`. Self-powered devices must also connect VBUS through a voltage divider or comparator. For more details, please refer to :ref:`self-powered-device`.
.. only:: esp32s3
External PHY Configuration
--------------------------
The {IDF_TARGET_NAME} contains two USB controllers: USB-OTG and USB-Serial-JTAG. However, both controllers share a **single PHY**, which means only one can operate at a time. To use USB Device functionality while the USB-Serial-JTAG is active (e.g., for debugging or flashing), an **external PHY** is required, since the PHY is used by USB-Serial-JTAG.
.. note::
An external PHY is not the only way to enable debugging alongside USB Host or Device functionality. It is also possible to switch the debugging interface from USB-Serial-JTAG to plain JTAG by burning the appropriate eFuses. For details, refer to document :doc:`JTAG Debugging <../../api-guides/jtag-debugging/index>` in ESP-IDF Programming Guide for your target.
{IDF_TARGET_NAME} supports connecting external PHY ICs. This becomes especially relevant when full-speed USB device functionality is needed while the USB-Serial-JTAG controller is also in use. Various external PHY ICs may require different hardware modifications. Please refer to each IC's datasheet for specifics. A general connection diagram below is provided for reference. For more information, please refer to `Use an external PHY <https://docs.espressif.com/projects/esp-iot-solution/en/latest/usb/usb_overview/usb_phy.html#use-an-external-phy>`__.
.. figure:: ../../../_static/usb_device/usb_fs_phy_sp5301.png
:align: center
:alt: usb_fs_phy_sp5301
A typical circuit diagram for an external PHY
**List of Tested External PHY ICs:**
- **SP5301** — Directly supported by {IDF_TARGET_NAME}. See the guide above for schematic and routing information.
- **STUSB03E** — Requires signal routing using an analog switch. See example below.
.. figure:: ../../../_static/usb_device/ext_phy_schematic_stusb03e.png
:align: center
:alt: External PHY with Analog Switch Schematic (Device mode)
Example connection using STUSB03E and analog switch (Device mode)
.. note::
This schematic is a minimal example intended only to demonstrate the external PHY connection. It omits other essential components and signals (e.g., VCC, GND, RESET) required for a complete, functional {IDF_TARGET_NAME} design.
The schematic includes both a +5 V rail (usually from USB VBUS) and a VCC rail. VCC should match the chip supply voltage (usually 3.3 V). Ensure that the external PHY and the chip are powered from the same voltage domain. If designing a self-powered USB device, connect VBUSDET signal from the external PHY to {IDF_TARGET_NAME} for mandatory VBUS monitoring.
Hardware configuration is handled via GPIO mapping to the PHY's pins. Any unused pins (e.g., :cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num`, :cpp:member:`usb_phy_ext_io_conf_t::fs_edge_sel_io_num`) **must be set to -1**.
.. note::
The :cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num` pin is **currently not supported** and does not need to be connected.
The :cpp:member:`usb_phy_ext_io_conf_t::fs_edge_sel_io_num` pin is optional and only required if switching between low-speed and full-speed modes is needed.
Starting from version 2.0, the ESP TinyUSB Device Stack supports external PHY usage. To use an external PHY in device mode:
1. Configure the GPIO mapping and PHY using :cpp:type:`usb_phy_config_t`.
2. Create the PHY using :cpp:func:`usb_new_phy()`.
3. Use :cpp:func:`TINYUSB_DEFAULT_CONFIG()` to initialize :cpp:type:`tinyusb_config_t`.
4. Set the `phy.skip_setup` field of :cpp:type:`tinyusb_config_t` to ``true`` to bypass PHY reinitialization and use the externally configured PHY.
**Example Code:**
.. code-block:: c
// GPIO configuration for external PHY
const usb_phy_ext_io_conf_t ext_io_conf = {
.vp_io_num = 8,
.vm_io_num = 5,
.rcv_io_num = 11,
.oen_io_num = 17,
.vpo_io_num = 4,
.vmo_io_num = 46,
.suspend_n_io_num = -1,
.fs_edge_sel_io_num = -1,
};
// Configuration and initialization of external PHY for OTG controller (Device mode)
const usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.target = USB_PHY_TARGET_EXT,
.otg_mode = USB_OTG_MODE_DEVICE,
.otg_speed = USB_PHY_SPEED_FULL,
.ext_io_conf = &ext_io_conf
};
usb_phy_handle_t phy_hdl;
ESP_ERROR_CHECK(usb_new_phy(&phy_config, &phy_hdl));
// Initialize TinyUSB with default configuration (event handler can be set if needed)
tinyusb_config_t config = TINYUSB_DEFAULT_CONFIG();
config.phy.skip_setup = true;
tinyusb_driver_install(&config);
This setup ensures that the USB Device stack uses the **external PHY** instead of attempting to configure the internal one.
Device Stack Structure Device Stack Structure
---------------------- ----------------------
@@ -145,7 +227,7 @@ To install the Device Stack, please call :cpp:func:`tinyusb_driver_install`. The
const tinyusb_config_t partial_init = { const tinyusb_config_t partial_init = {
.device_descriptor = NULL, // Use the default device descriptor specified in Menuconfig .device_descriptor = NULL, // Use the default device descriptor specified in Menuconfig
.string_descriptor = NULL, // Use the default string descriptors specified in Menuconfig .string_descriptor = NULL, // Use the default string descriptors specified in Menuconfig
.external_phy = false, // Use internal USB PHY .external_phy = false, // Use internal PHY
#if (TUD_OPT_HIGH_SPEED) #if (TUD_OPT_HIGH_SPEED)
.fs_configuration_descriptor = NULL, // Use the default full-speed configuration descriptor according to settings in Menuconfig .fs_configuration_descriptor = NULL, // Use the default full-speed configuration descriptor according to settings in Menuconfig
.hs_configuration_descriptor = NULL, // Use the default high-speed configuration descriptor according to settings in Menuconfig .hs_configuration_descriptor = NULL, // Use the default high-speed configuration descriptor according to settings in Menuconfig

View File

@@ -407,6 +407,75 @@ UVC
.. ---------------------------------------------- USB Host Menuconfig -------------------------------------------------- .. ---------------------------------------------- USB Host Menuconfig --------------------------------------------------
.. only:: esp32s3
External PHY Configuration
--------------------------
The {IDF_TARGET_NAME} contains two USB controllers—the USB-OTG and USB-Serial-JTAG. However, both controllers share a **single PHY**, which means only one can operate at a time. To use USB Host functionality while the USB-Serial-JTAG is active (e.g., for debugging or flashing), an **external PHY** is required, since the PHY is used by USB-Serial-JTAG.
.. note::
An external PHY is not the only way to enable debugging alongside USB Host or Device functionality. It is also possible to switch the debugging interface from USB-Serial-JTAG to plain JTAG by burning the appropriate eFuses. For details, refer to the `JTAG Debugging <https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/jtag-debugging/index.html>`_ in the ESP-IDF Programming Guide for your target.
{IDF_TARGET_NAME} supports connecting external PHY ICs. This allows independent operation of both USB-OTG and USB-Serial-JTAG controllers. Various external PHY ICs may require different hardware configurations. Please refer to the respective IC datasheets for details. A general connection diagram is available in the official ESP documentation: `Use an external PHY <https://docs.espressif.com/projects/esp-iot-solution/en/latest/usb/usb_overview/usb_phy.html#use-an-external-phy>`__.
**List of Tested External PHY ICs:**
- **SP5301** — Directly supported by {IDF_TARGET_NAME}. See the guide above for schematic and routing details.
- **STUSB03E** — Requires signal routing using an analog switch. See example below.
.. figure:: ../../../_static/usb_host/ext_phy_schematic_stusb03e.png
:align: center
:alt: External PHY with Analog Switch Schematic (Host mode)
Example connection using STUSB03E and analog switch (Host mode)
.. note::
This schematic is a minimal example intended only to demonstrate the external PHY connection. It omits other essential components and signals (e.g., VCC, GND, RESET) required for a complete, functional {IDF_TARGET_NAME} design.
The schematic includes both a +5 V rail (used to power USB devices) and a VCC rail (typically 3.3 V). VCC should match the chip supply voltage. Ensure that +5 V for the USB bus is appropriately sourced and protected (e.g., with a power switch and current limiting). Always comply with USB host power requirements, particularly when supporting USB bus-powered devices.
Hardware configuration is handled via GPIO mapping to the PHY's pins. Any unused pins (e.g., :cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num`) **must be set to -1**.
.. note::
The :cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num` pin is **currently not supported** and does not need to be connected.
**Example Code:**
.. code-block:: c
// GPIO configuration for external PHY
const usb_phy_ext_io_conf_t ext_io_conf = {
.vp_io_num = 8,
.vm_io_num = 5,
.rcv_io_num = 11,
.oen_io_num = 17,
.vpo_io_num = 4,
.vmo_io_num = 46,
.fs_edge_sel_io_num = 38,
.suspend_n_io_num = -1,
};
// Configuration and initialization of external PHY for OTG controller (Host mode)
const usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.target = USB_PHY_TARGET_EXT,
.otg_mode = USB_OTG_MODE_HOST,
.otg_speed = USB_PHY_SPEED_FULL,
.ext_io_conf = &ext_io_conf
};
usb_phy_handle_t phy_hdl;
ESP_ERROR_CHECK(usb_new_phy(&phy_config, &phy_hdl));
// Configure USB Host to use the externally initialized PHY
usb_host_config_t host_config = {
.skip_phy_setup = true,
// Add other host configuration fields as needed
};
ESP_ERROR_CHECK(usb_host_install(&host_config));
This setup ensures that the USB Host stack uses the **external PHY** and bypasses PHY setup.
Host Stack Configuration Host Stack Configuration
------------------------ ------------------------

View File

@@ -40,7 +40,7 @@ USB 设备栈(以下简称设备栈)支持在 {IDF_TARGET_NAME} 上启用 US
.. only:: esp32p4 .. only:: esp32p4
{IDF_TARGET_NAME} 将 USB D+ 和 D- 信号路由到其专用脚。为了实现 USB 设备功能,这些脚应通过某种方式连接到总线(例如,通过 Micro-B 端口、USB-C 端口或直接连接到标准-A 插头)。 {IDF_TARGET_NAME} 将 USB D+ 和 D- 信号路由到其专用脚。为了实现 USB 设备功能,这些脚应通过某种方式连接到总线(例如,通过 Micro-B 端口、USB-C 端口或直接连接到标准-A 插头)。
.. figure:: ../../../_static/usb-board-connection.png .. figure:: ../../../_static/usb-board-connection.png
:align: center :align: center
@@ -57,6 +57,88 @@ USB 设备栈(以下简称设备栈)支持在 {IDF_TARGET_NAME} 上启用 US
自供电设备还必须通过电压分压器或比较器连接 VBUS详情请参阅 :ref:`self-powered-device` 自供电设备还必须通过电压分压器或比较器连接 VBUS详情请参阅 :ref:`self-powered-device`
.. only:: esp32s3
外部 PHY 配置
-------------
{IDF_TARGET_NAME} 内部集成了两个 USB 控制器USB-OTG 与 USB-Serial-JTAG。这两个控制器 **共用同一个 PHY**,因此同一时间只能有一个控制器工作。如果在 USB-Serial-JTAG 工作时(例如调试或烧录)时仍需要使用 USB 设备功能,必须使用 **外部 PHY**,因为此时内部 PHY 已被 USB-Serial-JTAG 占用。
.. note::
使用外部 PHY 并不是在 USB 主机或设备功能开启时同时实现调试的唯一办法。也可以通过烧录对应的 eFuse将调试接口从 USB-Serial-JTAG 切换为传统的 JTAG 接口。具体步骤请参考 ESP-IDF 编程指南中针对你的芯片的 :doc:`JTAG 调试 <../../api-guides/jtag-debugging/index>` 章节。
{IDF_TARGET_NAME} 支持连接外部 PHY 芯片。当需要在使用 USB-Serial-JTAG 控制器的同时提供全速 USB 设备功能时,这一点尤其重要。不同的外部 PHY 芯片可能需要不同的硬件配置,请参考各自芯片的规格书。乐鑫官方文档提供了如下的通用连接示意图供参考。如需了解更多内容,请参阅 `使用外部 PHY <https://docs.espressif.com/projects/esp-iot-solution/zh_CN/latest/usb/usb_overview/usb_phy.html#external-phy>`__
.. figure:: ../../../_static/usb_device/usb_fs_phy_sp5301.png
:align: center
:alt: usb_fs_phy_sp5301
连接外部 PHY 芯片的典型电路图
**已测试的外部 PHY 芯片如下:**
- **SP5301** — {IDF_TARGET_NAME} 原生支持此芯片。原理图与布线方法请参考上文链接。
- **STUSB03E** — 需要通过模拟开关进行信号切换,详情参考下方示例。
.. figure:: ../../../_static/usb_device/ext_phy_schematic_stusb03e.png
:align: center
:alt: 使用模拟开关的外部 PHY 原理图(设备模式)
使用 STUSB03E 与模拟开关的连接示例(设备模式)
.. note::
此原理图仅为简化示例,用于展示外部 PHY 的连接方式,未包含完整 {IDF_TARGET_NAME} 设计所需的所有元件和信号(如 VCC、GND、RESET 等)。
图中包含 +5 V 电源轨(通常来自 USB VBUS和 VCC 电源轨。VCC 电压应与芯片供电电压一致(通常为 3.3 V并确保外部 PHY 与芯片使用同一电压域供电。如果设计自供电 USB 设备,请将外部 PHY 的 VBUSDET 信号接入 {IDF_TARGET_NAME},以便实现对 VBUS 电压状态的监控。
硬件配置通过将 GPIO 映射到 PHY 管脚实现。任何未使用的管脚(如 :cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num`:cpp:member:`usb_phy_ext_io_conf_t::fs_edge_sel_io_num` **必须设置为 -1**
.. note::
:cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num` 管脚 **当前不受支持**,无需连接。
:cpp:member:`usb_phy_ext_io_conf_t::fs_edge_sel_io_num` 管脚为可选管脚,仅需在低速和全速模式间切换时使用。
ESP TinyUSB 设备栈从 2.0 版本开始支持外部 PHY。要在设备模式下使用外部 PHY需执行以下步骤
1. 使用 :cpp:type:`usb_phy_config_t` 配置 GPIO 映射与 PHY。
2. 调用 :cpp:func:`usb_new_phy()` 创建 PHY。
3. 使用 :cpp:func:`TINYUSB_DEFAULT_CONFIG()` 初始化 :cpp:type:`tinyusb_config_t`
4.:cpp:type:`tinyusb_config_t``phy.skip_setup` 字段设为 ``true``,从而跳过 PHY 的重新初始化,直接使用已配置的外部 PHY。
**示例代码:**
.. code-block:: c
// 外部 PHY 的 GPIO 配置
const usb_phy_ext_io_conf_t ext_io_conf = {
.vp_io_num = 8,
.vm_io_num = 5,
.rcv_io_num = 11,
.oen_io_num = 17,
.vpo_io_num = 4,
.vmo_io_num = 46,
.suspend_n_io_num = -1,
.fs_edge_sel_io_num = -1,
};
// 针对 OTG 控制器(设备模式)的外部 PHY 配置与初始化
const usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.target = USB_PHY_TARGET_EXT,
.otg_mode = USB_OTG_MODE_DEVICE,
.otg_speed = USB_PHY_SPEED_FULL,
.ext_io_conf = &ext_io_conf
};
usb_phy_handle_t phy_hdl;
ESP_ERROR_CHECK(usb_new_phy(&phy_config, &phy_hdl));
// 使用默认配置初始化 TinyUSB可根据需要设置事件处理函数
tinyusb_config_t config = TINYUSB_DEFAULT_CONFIG();
config.phy.skip_setup = true;
tinyusb_driver_install(&config);
通过上述配置USB 设备栈会直接使用 **外部 PHY**,而不会尝试配置内部 PHY。
设备栈结构 设备栈结构
---------- ----------
@@ -170,7 +252,7 @@ USB 规范要求自供电设备监测 USB 的 VBUS 信号的电压水平。与
.. note:: .. note::
在这两种情况下,设备从 USB 主机拔出后 3 毫秒内,传感脚上的电压必须为逻辑低电平。 在这两种情况下,设备从 USB 主机拔出后 3 毫秒内,传感脚上的电压必须为逻辑低电平。
.. figure:: ../../../_static/diagrams/usb/usb_vbus_voltage_monitor.png .. figure:: ../../../_static/diagrams/usb/usb_vbus_voltage_monitor.png
:align: center :align: center

View File

@@ -407,6 +407,75 @@ UVC
.. ---------------------------------------------- USB Host Menuconfig -------------------------------------------------- .. ---------------------------------------------- USB Host Menuconfig --------------------------------------------------
.. only:: esp32s3
外部 PHY 配置
-------------
{IDF_TARGET_NAME} 内部集成了两个 USB 控制器 —— USB-OTG 和 USB-Serial-JTAG。这两个控制器 **共用同一个 PHY**,因此同一时间只能有一个控制器工作。如果在 USB-Serial-JTAG 工作时(如调试或烧录)时仍需使用 USB 主机功能,必须使用 **外部 PHY**,因为此时内部 PHY 已被 USB-Serial-JTAG 占用。
.. note::
使用外部 PHY 并不是在 USB 主机或设备功能开启时同时实现调试的唯一办法。也可以通过烧录对应的 eFuse将调试接口从 USB-Serial-JTAG 切换为传统的 JTAG 接口。具体步骤请参考 ESP-IDF 编程指南中针对你的芯片的 `JTAG 调试 <https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/api-guides/jtag-debugging/index.html>`_ 章节。
{IDF_TARGET_NAME} 支持连接外部 PHY 芯片,从而实现 USB-OTG 和 USB-Serial-JTAG 控制器的独立工作。不同的外部 PHY 芯片可能需要不同的硬件配置,具体请参阅各芯片的规格书。乐鑫官方文档提供了通用的连接示意图用于参考:`使用外部 PHY <https://docs.espressif.com/projects/esp-iot-solution/en/latest/usb/usb_overview/usb_phy.html#use-an-external-phy>`__。
**已测试的外部 PHY 芯片如下:**
- **SP5301** — {IDF_TARGET_NAME} 原生支持此芯片。原理图与布线方法请参考上文链接。
- **STUSB03E** — 需要通过模拟开关进行信号路由。请参考下方示例。
.. figure:: ../../../_static/usb_host/ext_phy_schematic_stusb03e.png
:align: center
:alt: 使用模拟开关的外部 PHY 原理图(主机模式)
使用 STUSB03E 与模拟开关的连接示例(主机模式)
.. note::
此原理图为简化示例,用于演示外部 PHY 连接方式,未包含完整 {IDF_TARGET_NAME} 设计所需的所有元器件和信号(如 VCC、GND、RESET 等)。
图中包含 +5 V 电源轨(用于为 USB 设备供电)和 VCC 电源轨(通常为 3.3 V。VCC 电压应与芯片供电电压保持一致。确保为 USB 总线提供的 +5 V 电源可靠,并具备必要的保护措施(如电源开关和限流设计)在支持 USB 总线供电设备时,务必遵守 USB 主机的供电规范。
硬件配置通过将 GPIO 映射到 PHY 引脚实现。任何未使用的引脚(如 :cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num` **必须设置为 -1**。
.. note::
:cpp:member:`usb_phy_ext_io_conf_t::suspend_n_io_num` 引脚 **当前不支持**,无需连接。
**示例代码:**
.. code-block:: c
// 外部 PHY 的 GPIO 配置
const usb_phy_ext_io_conf_t ext_io_conf = {
.vp_io_num = 8,
.vm_io_num = 5,
.rcv_io_num = 11,
.oen_io_num = 17,
.vpo_io_num = 4,
.vmo_io_num = 46,
.fs_edge_sel_io_num = 38,
.suspend_n_io_num = -1,
};
// 针对 OTG 控制器Host 模式)的外部 PHY 配置与初始化
const usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.target = USB_PHY_TARGET_EXT,
.otg_mode = USB_OTG_MODE_HOST,
.otg_speed = USB_PHY_SPEED_FULL,
.ext_io_conf = &ext_io_conf
};
usb_phy_handle_t phy_hdl;
ESP_ERROR_CHECK(usb_new_phy(&phy_config, &phy_hdl));
// 配置 USB 主机使用外部初始化的 PHY
usb_host_config_t host_config = {
.skip_phy_setup = true,
// 根据需求添加其他 host 配置字段
};
ESP_ERROR_CHECK(usb_host_install(&host_config));
该配置确保 USB 主机协议栈使用 **外部 PHY**,并跳过 PHY 初始化步骤。
主机栈配置 主机栈配置
---------- ----------