From d65b467108be638d0d4fe812d9695fcda33d970f Mon Sep 17 00:00:00 2001 From: Jiang Guang Ming Date: Mon, 8 Jun 2026 15:26:45 +0800 Subject: [PATCH] fix(usb): address usb wakeup review comments --- .../esp32p4/include/hal/usb_utmi_ll.h | 4 +--- .../esp_hw_support/include/esp_private/usb_phy.h | 15 ++++++++++++++- components/esp_hw_support/include/esp_sleep.h | 7 +++---- components/esp_hw_support/usb_phy/usb_phy.c | 16 ++++++++++++++++ .../usb/device/tud_cdc_acm_wakeup/README.md | 5 ++++- .../main/tud_cdc_acm_wakeup_main.c | 15 ++++++--------- 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/components/esp_hal_usb/esp32p4/include/hal/usb_utmi_ll.h b/components/esp_hal_usb/esp32p4/include/hal/usb_utmi_ll.h index 65e91cb9748..fd34ade1cdb 100644 --- a/components/esp_hal_usb/esp32p4/include/hal/usb_utmi_ll.h +++ b/components/esp_hal_usb/esp32p4/include/hal/usb_utmi_ll.h @@ -11,11 +11,9 @@ #include "soc/lp_clkrst_struct.h" #include "soc/hp_sys_clkrst_struct.h" #include "soc/hp_system_struct.h" +#include "soc/lp_system_struct.h" #include "soc/usb_utmi_struct.h" #include "hal/config.h" -#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 -#include "soc/lp_system_struct.h" -#endif #ifdef __cplusplus extern "C" { diff --git a/components/esp_hw_support/include/esp_private/usb_phy.h b/components/esp_hw_support/include/esp_private/usb_phy.h index 7553b879bad..05dcddd7a84 100644 --- a/components/esp_hw_support/include/esp_private/usb_phy.h +++ b/components/esp_hw_support/include/esp_private/usb_phy.h @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include #include #include "esp_err.h" #include "soc/soc_caps.h" @@ -164,6 +165,18 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r */ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode); +/** + * @brief Set the USB OTG suspend state for USB wakeup logic + * + * @param in_suspend True if the USB OTG bus is suspended + */ +void usb_phy_set_otg_suspend_state(bool in_suspend); + +/** + * @brief Clear USB OTG wakeup status from the USB wakeup logic + */ +void usb_phy_clear_otg_wakeup_status(void); + /** * @brief Delete a USB PHY * diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 7145e5b1906..723774eeb88 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -137,7 +137,7 @@ typedef enum { ESP_SLEEP_WAKEUP_BT, //!< Wakeup caused by BT (light sleep only) ESP_SLEEP_WAKEUP_VAD, //!< Wakeup caused by VAD ESP_SLEEP_WAKEUP_VBAT_UNDER_VOLT, //!< Wakeup caused by VDD_BAT under voltage. - ESP_SLEEP_WAKEUP_USB, //!< Wakeup caused by USB (light sleep only) + ESP_SLEEP_WAKEUP_USB, //!< Wakeup caused by USB HS (light sleep only) } esp_sleep_source_t; /** @@ -150,7 +150,6 @@ typedef enum { /* Leave this type define for compatibility */ typedef esp_sleep_source_t esp_sleep_wakeup_cause_t; - enum { ESP_ERR_SLEEP_REJECT = ESP_ERR_INVALID_STATE, ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION = ESP_ERR_INVALID_ARG, @@ -567,7 +566,7 @@ esp_err_t esp_sleep_enable_bt_wakeup(void); esp_err_t esp_sleep_disable_bt_wakeup(void); /** - * @brief Enable wakeup by USB + * @brief Enable wakeup by High-Speed USB-OTG * @return * - ESP_OK on success * - ESP_ERR_NOT_SUPPORTED if wakeup from USB is not supported @@ -575,7 +574,7 @@ esp_err_t esp_sleep_disable_bt_wakeup(void); esp_err_t esp_sleep_enable_usb_wakeup(void); /** - * @brief Disable wakeup by USB + * @brief Disable wakeup by High-Speed USB-OTG * @return * - ESP_OK on success * - ESP_ERR_NOT_SUPPORTED if wakeup from USB is not supported diff --git a/components/esp_hw_support/usb_phy/usb_phy.c b/components/esp_hw_support/usb_phy/usb_phy.c index c7e40a6805e..57fc7fca215 100644 --- a/components/esp_hw_support/usb_phy/usb_phy.c +++ b/components/esp_hw_support/usb_phy/usb_phy.c @@ -180,6 +180,22 @@ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode) return ESP_OK; } +void usb_phy_set_otg_suspend_state(bool in_suspend) +{ +#if SOC_USB_UTMI_PHY_NUM + usb_utmi_hal_set_suspend_state(in_suspend); +#else + (void)in_suspend; +#endif +} + +void usb_phy_clear_otg_wakeup_status(void) +{ +#if SOC_USB_UTMI_PHY_NUM + usb_utmi_hal_clear_wakeup_status(); +#endif +} + static esp_err_t usb_phy_install(void) { PHY_ENTER_CRITICAL(); diff --git a/examples/peripherals/usb/device/tud_cdc_acm_wakeup/README.md b/examples/peripherals/usb/device/tud_cdc_acm_wakeup/README.md index 8e021256d46..b12c127747f 100644 --- a/examples/peripherals/usb/device/tud_cdc_acm_wakeup/README.md +++ b/examples/peripherals/usb/device/tud_cdc_acm_wakeup/README.md @@ -6,6 +6,7 @@ (See the README.md file in the upper level 'examples' directory for more information about examples.) This example shows how to set up an ESP chip as a USB CDC ACM device that enters light sleep when the USB bus is suspended and wakes up from USB activity. +The wakeup source is available only on USB-OTG capable targets with High-Speed USB support. It is not supported by USB Serial/JTAG-only peripherals. As a USB stack, a TinyUSB component is used. @@ -15,7 +16,7 @@ The example implements a USB CDC ACM echo device. When the host suspends the USB ### Hardware Required -Any ESP board that supports USB wakeup from light sleep. +Any ESP board that supports High-Speed USB-OTG wakeup from light sleep. #### Pin Assignment @@ -50,6 +51,8 @@ I (465) tud_cdc_acm_wakeup: USB initialization DONE Connect to the serial port (e.g. on Linux, it should be `/dev/ttyACM0`) by any terminal application (e.g. `picocom /dev/ttyACM0`). Now you can send data strings to the device, the device will echo back the same data string. +To trigger USB suspend from the host, disable or suspend the CDC ACM device on the host side. On Windows, open Device Manager, find the COM port for the device, and disable it. On Linux, you can unbind the CDC ACM driver for the device or put the USB device into autosuspend. On macOS, disconnecting the terminal application and letting the host suspend the interface can also trigger suspend depending on the host power policy. + When the USB host suspends and resumes the bus, the monitor output should include: ``` diff --git a/examples/peripherals/usb/device/tud_cdc_acm_wakeup/main/tud_cdc_acm_wakeup_main.c b/examples/peripherals/usb/device/tud_cdc_acm_wakeup/main/tud_cdc_acm_wakeup_main.c index 59c8496d07a..639a7fb124c 100644 --- a/examples/peripherals/usb/device/tud_cdc_acm_wakeup/main/tud_cdc_acm_wakeup_main.c +++ b/examples/peripherals/usb/device/tud_cdc_acm_wakeup/main/tud_cdc_acm_wakeup_main.c @@ -10,10 +10,10 @@ #include "esp_log.h" #include "esp_rom_serial_output.h" #include "esp_sleep.h" +#include "esp_private/usb_phy.h" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" #include "freertos/task.h" -#include "hal/usb_utmi_hal.h" #include "sdkconfig.h" #include "soc/soc_caps.h" #include "tinyusb.h" @@ -85,7 +85,7 @@ void tud_suspend_cb(bool remote_wakeup_en) (void) remote_wakeup_en; ESP_LOGI(TAG, "USB suspended, entering light sleep"); - usb_utmi_hal_set_suspend_state(true); + usb_phy_set_otg_suspend_state(true); esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); @@ -95,16 +95,13 @@ void tud_suspend_cb(bool remote_wakeup_en) } else { uint32_t causes = esp_sleep_get_wakeup_causes(); if (causes & BIT(ESP_SLEEP_WAKEUP_UNDEFINED)) { - ESP_LOGI(TAG, "Woke up from: unknown"); - printf("%lx\n", causes); - return; - } - if (causes & BIT(ESP_SLEEP_WAKEUP_USB)) { + ESP_LOGW(TAG, "Woke up from an unknown source: 0x%lx", causes); + } else if (causes & BIT(ESP_SLEEP_WAKEUP_USB)) { ESP_LOGI(TAG, "Woke up from: USB"); } } - usb_utmi_hal_set_suspend_state(false); - usb_utmi_hal_clear_wakeup_status(); + usb_phy_set_otg_suspend_state(false); + usb_phy_clear_otg_wakeup_status(); } void tud_resume_cb(void)