From 455cb7e7beae2fd29771348670f5ccd90dead846 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 25 Feb 2026 12:24:43 +0800 Subject: [PATCH] feat(esp_hal_uart): support esp32p4 hp uart 3,4 wakeup during light sleep --- .../esp32p4/include/hal/uart_ll.h | 8 ++ .../include/esp_private/esp_pmu.h | 23 +++-- .../include/esp_private/esp_sleep_internal.h | 6 ++ components/esp_hw_support/include/esp_sleep.h | 11 ++- .../port/esp32p4/pmu_sleep_clock_icg.c | 10 +++ components/esp_hw_support/sleep_modes.c | 86 +++++++++++++------ .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32/include/soc/soc_caps.h | 3 + .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s3/include/soc/soc_caps.h | 2 + 10 files changed, 121 insertions(+), 36 deletions(-) diff --git a/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h b/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h index 0098c6da702..e4343a2e36c 100644 --- a/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h @@ -33,6 +33,14 @@ (num) == 2 ? (&UART2) : \ (num) == 3 ? (&UART3) : \ (num) == 4 ? (&UART4) : (&LP_UART)) +// Get UART sleep clock with giving uart num +#define UART_LL_SLEEP_CLOCK(num) \ + ( ((num) == UART_NUM_0) ? (ESP_SLEEP_CLOCK_UART0) \ + : ((num) == UART_NUM_1) ? (ESP_SLEEP_CLOCK_UART1) \ + : ((num) == UART_NUM_2) ? (ESP_SLEEP_CLOCK_UART2) \ + : ((num) == UART_NUM_3) ? (ESP_SLEEP_CLOCK_UART3) \ + : ((num) == UART_NUM_4) ? (ESP_SLEEP_CLOCK_UART4) \ + : (ESP_SLEEP_CLOCK_MAX)) #define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0) diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index c7af0b1212c..543b9c34c5a 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -87,18 +87,25 @@ typedef enum { #define RTC_WIFI_TRIG_EN 0 #endif -#if SOC_UART_SUPPORT_WAKEUP_INT #define RTC_UART0_TRIG_EN PMU_UART0_WAKEUP_EN //!< UART0 wakeup (light sleep only) #define RTC_UART1_TRIG_EN PMU_UART1_WAKEUP_EN //!< UART1 wakeup (light sleep only) +#define RTC_UART2_TRIG_EN 0 +#define RTC_UART3_TRIG_EN 0 +#define RTC_UART4_TRIG_EN 0 + #if SOC_UART_HP_NUM > 2 +#undef RTC_UART2_TRIG_EN #define RTC_UART2_TRIG_EN PMU_UART2_WAKEUP_EN //!< UART2 wakeup (light sleep only) -#else -#define RTC_UART2_TRIG_EN 0 #endif -#else -#define RTC_UART0_TRIG_EN 0 -#define RTC_UART1_TRIG_EN 0 -#define RTC_UART2_TRIG_EN 0 + +#if SOC_UART_HP_NUM > 3 +#undef RTC_UART3_TRIG_EN +#define RTC_UART3_TRIG_EN PMU_UART3_WAKEUP_EN //!< UART3 wakeup (light sleep only) +#endif + +#if SOC_UART_HP_NUM > 4 +#undef RTC_UART4_TRIG_EN +#define RTC_UART4_TRIG_EN PMU_UART4_WAKEUP_EN //!< UART4 wakeup (light sleep only) #endif #if SOC_BT_SUPPORTED @@ -149,6 +156,8 @@ typedef enum { RTC_UART0_TRIG_EN | \ RTC_UART1_TRIG_EN | \ RTC_UART2_TRIG_EN | \ + RTC_UART3_TRIG_EN | \ + RTC_UART4_TRIG_EN | \ RTC_BT_TRIG_EN | \ RTC_LP_CORE_TRIG_EN | \ RTC_TOUCH_TRIG_EN | \ diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index 83b15760e4e..c2257f4c566 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -118,6 +118,12 @@ typedef enum { #if SOC_UART_HP_NUM > 2 ESP_SLEEP_CLOCK_UART2, //!< The clock ICG cell mapping of UART2 #endif +#if SOC_UART_HP_NUM > 3 + ESP_SLEEP_CLOCK_UART3, //!< The clock ICG cell mapping of UART3 +#endif +#if SOC_UART_HP_NUM > 4 + ESP_SLEEP_CLOCK_UART4, //!< The clock ICG cell mapping of UART4 +#endif #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK, //!< The clock ICG cell remapping of RETENTION #endif diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 129b0aea694..304659bf7f7 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -112,9 +112,18 @@ typedef enum { ESP_SLEEP_WAKEUP_TOUCHPAD, //!< Wakeup caused by touchpad ESP_SLEEP_WAKEUP_ULP, //!< Wakeup caused by ULP program ESP_SLEEP_WAKEUP_GPIO, //!< Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3) - ESP_SLEEP_WAKEUP_UART, //!< Wakeup caused by UART0 (light sleep only) + ESP_SLEEP_WAKEUP_UART0, //!< Wakeup caused by UART0 (light sleep only) + ESP_SLEEP_WAKEUP_UART = ESP_SLEEP_WAKEUP_UART0, ESP_SLEEP_WAKEUP_UART1, //!< Wakeup caused by UART1 (light sleep only) +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP ESP_SLEEP_WAKEUP_UART2, //!< Wakeup caused by UART2 (light sleep only) +#endif +#if (SOC_UART_HP_NUM > 3) + ESP_SLEEP_WAKEUP_UART3, //!< Wakeup caused by UART3 (light sleep only) +#endif +#if (SOC_UART_HP_NUM > 4) + ESP_SLEEP_WAKEUP_UART4, //!< Wakeup caused by UART4 (light sleep only) +#endif ESP_SLEEP_WAKEUP_WIFI, //!< Wakeup caused by WIFI (light sleep only) ESP_SLEEP_WAKEUP_COCPU, //!< Wakeup caused by COCPU int ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG, //!< Wakeup caused by COCPU crash diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c b/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c index 93fa5c5085c..4beca572007 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c @@ -196,4 +196,14 @@ void pmu_sleep_clock_icg_config(void *icg_context, const uint32_t icg_func) regdma_link_set_write_wait_content(clock_icg->regdma_desc[14], PERI_CLK_EN(UART2), PERI_CLK_MASK(UART2)); } #endif +#if SOC_UART_HP_NUM > 3 + if (icg_func & BIT(PMU_ICG_FUNC_ENA_UART3)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[15], PERI_CLK_EN(UART3), PERI_CLK_MASK(UART3)); + } +#endif +#if SOC_UART_HP_NUM > 4 + if (icg_func & BIT(PMU_ICG_FUNC_ENA_UART4)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[16], PERI_CLK_EN(UART4), PERI_CLK_MASK(UART4)); + } +#endif } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ef8473c4dfb..ad9e148d2bf 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1744,31 +1744,35 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) s_config.gpio_trigger_mode = 0; #endif s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN; -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) - } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN | RTC_UART2_TRIG_EN))) { - s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN | RTC_UART2_TRIG_EN); - } -#else - } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) { - s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN); - } + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART0, RTC_UART0_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART0_TRIG_EN; + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART1, RTC_UART1_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART1_TRIG_EN; +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART2, RTC_UART2_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART2_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 3) + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART3, RTC_UART3_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART3_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 4) + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART4, RTC_UART4_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART4_TRIG_EN; #endif #if CONFIG_ULP_COPROC_TYPE_FSM - else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) { + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN; - } #endif #if SOC_LP_VAD_SUPPORTED - else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VAD, RTC_LP_VAD_TRIG_EN)) { + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VAD, RTC_LP_VAD_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_LP_VAD_TRIG_EN; - } #endif #if SOC_VBAT_SUPPORTED - else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VBAT_UNDER_VOLT, RTC_VBAT_UNDER_VOLT_TRIG_EN)) { + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VBAT_UNDER_VOLT, RTC_VBAT_UNDER_VOLT_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_VBAT_UNDER_VOLT_TRIG_EN; - } #endif - else { + } else { ESP_LOGE(TAG, "Incorrect wakeup source (%d) to disable.", (int) source); return ESP_ERR_INVALID_STATE; } @@ -2292,18 +2296,27 @@ esp_err_t esp_sleep_enable_uart_wakeup(int uart_num) s_config.wakeup_triggers |= RTC_UART0_TRIG_EN; } else if (uart_num == UART_NUM_1) { s_config.wakeup_triggers |= RTC_UART1_TRIG_EN; -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP } else if (uart_num == UART_NUM_2) { s_config.wakeup_triggers |= RTC_UART2_TRIG_EN; #endif -#if SOC_PM_SUPPORT_LP_UART_WAKEUP - } else if (uart_num == LP_UART_NUM_0) { - s_config.wakeup_triggers |= PMU_LP_UART_WAKEUP_EN; +#if (SOC_UART_HP_NUM > 3) + } else if (uart_num == UART_NUM_3) { + s_config.wakeup_triggers |= RTC_UART3_TRIG_EN; #endif - } else { +#if (SOC_UART_HP_NUM > 4) + } else if (uart_num == UART_NUM_4) { + s_config.wakeup_triggers |= RTC_UART4_TRIG_EN; +#endif + } else +#if SOC_PM_SUPPORT_LP_UART_WAKEUP + if (uart_num == LP_UART_NUM_0) { + s_config.wakeup_triggers |= PMU_LP_UART_WAKEUP_EN; + } else +#endif + { return ESP_ERR_INVALID_ARG; } - return ESP_OK; } @@ -2379,15 +2392,22 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause(); #endif + uint32_t uart_wakeup_mask = RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN; +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + uart_wakeup_mask |= RTC_UART2_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 3) + uart_wakeup_mask |= RTC_UART3_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 4) + uart_wakeup_mask |= RTC_UART4_TRIG_EN; +#endif + if (wakeup_cause & RTC_TIMER_TRIG_EN) { return ESP_SLEEP_WAKEUP_TIMER; } else if (wakeup_cause & RTC_GPIO_TRIG_EN) { return ESP_SLEEP_WAKEUP_GPIO; -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) - } else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN | RTC_UART2_TRIG_EN)) { -#else - } else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) { -#endif + } else if (wakeup_cause & uart_wakeup_mask) { return ESP_SLEEP_WAKEUP_UART; #if SOC_PM_SUPPORT_EXT0_WAKEUP } else if (wakeup_cause & RTC_EXT0_TRIG_EN) { @@ -2460,16 +2480,26 @@ uint32_t esp_sleep_get_wakeup_causes(void) wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_GPIO); } if (wakeup_cause_raw & RTC_UART0_TRIG_EN) { - wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART); + wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART0); } if (wakeup_cause_raw & RTC_UART1_TRIG_EN) { wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART1); } -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP if (wakeup_cause_raw & RTC_UART2_TRIG_EN) { wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART2); } #endif +#if (SOC_UART_HP_NUM > 3) + if (wakeup_cause_raw & RTC_UART3_TRIG_EN) { + wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART3); + } +#endif +#if (SOC_UART_HP_NUM > 4) + if (wakeup_cause_raw & RTC_UART4_TRIG_EN) { + wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART4); + } +#endif #if SOC_PM_SUPPORT_EXT0_WAKEUP if (wakeup_cause_raw & RTC_EXT0_TRIG_EN) { wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_EXT0); diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 42f8d282f1e..719639c3c91 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -707,6 +707,10 @@ config SOC_PM_MODEM_PD_BY_SW bool default y +config SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + bool + default y + config SOC_CLK_APLL_SUPPORTED bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 053c82ec591..1f128eb298b 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -353,6 +353,9 @@ #define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1) #define SOC_PM_MODEM_PD_BY_SW (1) + +#define SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP (1) + /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_APLL_SUPPORTED (1) diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index d121cc2de40..7063dbe2d40 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -939,6 +939,10 @@ config SOC_PM_MODEM_PD_BY_SW bool default y +config SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + bool + default y + config SOC_CLK_RC_FAST_D256_SUPPORTED bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 707cb06d594..c3ac93303e1 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -397,6 +397,8 @@ #define SOC_PM_MODEM_RETENTION_BY_BACKUPDMA (1) #define SOC_PM_MODEM_PD_BY_SW (1) +#define SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP (1) + /*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */ #define SOC_CLK_RC_FAST_D256_SUPPORTED (1) #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 (1)