From a764b5f222a964e6cc194c2ac12547470fcc6667 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Tue, 10 Mar 2026 20:43:40 +0800 Subject: [PATCH 1/3] fix(ulp): record wakeup causes before lp core request sleep --- components/esp_hw_support/sleep_modes.c | 12 ++++++++++ .../esp_rom/esp32c5/include/esp32c5/rom/rtc.h | 2 ++ .../esp_rom/esp32c6/include/esp32c6/rom/rtc.h | 2 ++ .../esp_rom/esp32p4/include/esp32p4/rom/rtc.h | 20 +++++++++-------- .../hal/esp32c5/include/hal/lp_aon_hal.h | 3 +++ .../hal/esp32c5/include/hal/lp_aon_ll.h | 20 ++++++++++++++++- .../hal/esp32c6/include/hal/lp_aon_hal.h | 2 ++ .../hal/esp32c6/include/hal/lp_aon_ll.h | 20 ++++++++++++++++- .../hal/esp32p4/include/hal/lp_aon_hal.h | 2 ++ .../hal/esp32p4/include/hal/lp_sys_ll.h | 21 +++++++++++++++++- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32c5/include/soc/soc_caps.h | 1 + .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32c6/include/soc/soc_caps.h | 1 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32p4/include/soc/soc_caps.h | 1 + components/ulp/lp_core/lp_core.c | 22 +++++++++++++++++-- .../ulp/lp_core/lp_core/lp_core_utils.c | 21 ++++++++++++++++-- 18 files changed, 146 insertions(+), 16 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b5d89775f0d..132bb3ac806 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -74,6 +74,9 @@ #include "hal/touch_sens_hal.h" #endif #include "hal/mspi_ll.h" +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE +#include "hal/lp_aon_hal.h" +#endif #include "sdkconfig.h" #include "esp_rom_serial_output.h" @@ -2394,6 +2397,15 @@ uint32_t esp_sleep_get_wakeup_causes(void) uint32_t wakeup_cause_raw = rtc_cntl_ll_get_wakeup_cause(); #endif +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE + /* LP store register to read wakeup cause saved by LP core. + * Must match the register used in lp_core_utils.c */ + uint32_t lp_core_wakeup_cause_status0 = lp_aon_hal_load_wakeup_cause(); + if ((wakeup_cause_raw == 0) && (lp_core_wakeup_cause_status0 != 0)) { + wakeup_cause_raw = lp_core_wakeup_cause_status0; + } +#endif + if (wakeup_cause_raw & RTC_TIMER_TRIG_EN) { wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_TIMER); } diff --git a/components/esp_rom/esp32c5/include/esp32c5/rom/rtc.h b/components/esp_rom/esp32c5/include/esp32c5/rom/rtc.h index 726d250986c..4d57760f0f8 100644 --- a/components/esp_rom/esp32c5/include/esp32c5/rom/rtc.h +++ b/components/esp_rom/esp32c5/include/esp32c5/rom/rtc.h @@ -52,6 +52,7 @@ extern "C" { * LP_AON_STORE7_REG FAST_RTC_MEMORY_CRC * LP_AON_STORE8_REG Store light sleep wake stub addr (mask bit[1:0]) * LP_AON_STORE8_REG Store the sleep mode at bit[0] (0:light sleep 1:deep sleep) + * LP_AON_STORE9_REG LP core store wakeup cause ************************************************************************************* */ @@ -64,6 +65,7 @@ extern "C" { #define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG #define RTC_SLEEP_WAKE_STUB_ADDR_REG LP_AON_STORE8_REG #define RTC_SLEEP_MODE_REG LP_AON_STORE8_REG +#define RTC_LP_CORE_STORE_WAKEUP_REG LP_AON_STORE9_REG #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. diff --git a/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h b/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h index 70a868df415..38c3ac3c351 100644 --- a/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h +++ b/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h @@ -53,6 +53,7 @@ extern "C" { * LP_AON_STORE7_REG FAST_RTC_MEMORY_CRC * LP_AON_STORE8_REG Store light sleep wake stub addr * LP_AON_STORE9_REG Store the sleep mode at bit[0] (0:light sleep 1:deep sleep) + * LP_AON_STORE10_REG LP core store wakeup cause at bit[31:2] ************************************************************************************* */ @@ -66,6 +67,7 @@ extern "C" { #define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG #define RTC_SLEEP_WAKE_STUB_ADDR_REG LP_AON_STORE8_REG #define RTC_SLEEP_MODE_REG LP_AON_STORE9_REG +#define RTC_LP_CORE_STORE_WAKEUP_REG LP_AON_STORE9_REG #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. diff --git a/components/esp_rom/esp32p4/include/esp32p4/rom/rtc.h b/components/esp_rom/esp32p4/include/esp32p4/rom/rtc.h index 6eccaa9ba5c..d3c39b0e1ee 100644 --- a/components/esp_rom/esp32p4/include/esp32p4/rom/rtc.h +++ b/components/esp_rom/esp32p4/include/esp32p4/rom/rtc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,17 +53,19 @@ extern "C" { * LP_SYS_LP_STORE8_REG sleep mode and wake stub address * LP_SYS_LP_STORE9_REG LP_UART_INIT_CTRL * LP_SYS_LP_STORE10_REG LP_ROM_LOG_CTRL + * LP_SYS_LP_STORE11_REG LP core store wakeup cause ************************************************************************************* */ -#define RTC_SLOW_CLK_CAL_REG LP_SYSTEM_REG_LP_STORE1_REG -#define RTC_BOOT_TIME_LOW_REG LP_SYSTEM_REG_LP_STORE2_REG -#define RTC_BOOT_TIME_HIGH_REG LP_SYSTEM_REG_LP_STORE3_REG -#define RTC_XTAL_FREQ_REG LP_SYSTEM_REG_LP_STORE4_REG -#define RTC_APB_FREQ_REG LP_SYSTEM_REG_LP_STORE5_REG -#define RTC_ENTRY_ADDR_REG LP_SYSTEM_REG_LP_STORE6_REG -#define RTC_RESET_CAUSE_REG LP_SYSTEM_REG_LP_STORE6_REG -#define RTC_MEMORY_CRC_REG LP_SYSTEM_REG_LP_STORE7_REG +#define RTC_SLOW_CLK_CAL_REG LP_SYSTEM_REG_LP_STORE1_REG +#define RTC_BOOT_TIME_LOW_REG LP_SYSTEM_REG_LP_STORE2_REG +#define RTC_BOOT_TIME_HIGH_REG LP_SYSTEM_REG_LP_STORE3_REG +#define RTC_XTAL_FREQ_REG LP_SYSTEM_REG_LP_STORE4_REG +#define RTC_APB_FREQ_REG LP_SYSTEM_REG_LP_STORE5_REG +#define RTC_ENTRY_ADDR_REG LP_SYSTEM_REG_LP_STORE6_REG +#define RTC_RESET_CAUSE_REG LP_SYSTEM_REG_LP_STORE6_REG +#define RTC_MEMORY_CRC_REG LP_SYSTEM_REG_LP_STORE7_REG +#define RTC_LP_CORE_STORE_WAKEUP_REG LP_SYSTEM_REG_LP_STORE11_REG #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. diff --git a/components/hal/esp32c5/include/hal/lp_aon_hal.h b/components/hal/esp32c5/include/hal/lp_aon_hal.h index 2090a649287..9854ef3b0eb 100644 --- a/components/hal/esp32c5/include/hal/lp_aon_hal.h +++ b/components/hal/esp32c5/include/hal/lp_aon_hal.h @@ -15,3 +15,6 @@ #define rtc_hal_ext1_get_wakeup_pins() lp_aon_ll_ext1_get_wakeup_pins() #define lp_aon_hal_inform_wakeup_type(dslp) lp_aon_ll_inform_wakeup_type(dslp) + +#define lp_aon_hal_store_wakeup_cause(wakeup_cause) lp_aon_ll_store_wakeup_cause(wakeup_cause) +#define lp_aon_hal_load_wakeup_cause() lp_aon_ll_load_wakeup_cause() diff --git a/components/hal/esp32c5/include/hal/lp_aon_ll.h b/components/hal/esp32c5/include/hal/lp_aon_ll.h index e36779941a6..f077dc59c82 100644 --- a/components/hal/esp32c5/include/hal/lp_aon_ll.h +++ b/components/hal/esp32c5/include/hal/lp_aon_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,6 +85,24 @@ static inline void lp_aon_ll_inform_wakeup_type(bool dslp) } } +/** + * @brief Set the wakeup cause stored by LP core + * @param wakeup_cause The wakeup cause in PMU register + */ +static inline void lp_aon_ll_store_wakeup_cause(uint32_t wakeup_cause) +{ + REG_WRITE(RTC_LP_CORE_STORE_WAKEUP_REG, wakeup_cause); +} + +/** + * @brief Get the wakeup cause stored by LP core + * @return The wakeup cause cleared before LP core sleep + */ +static inline uint32_t lp_aon_ll_load_wakeup_cause(void) +{ + return REG_READ(RTC_LP_CORE_STORE_WAKEUP_REG); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/lp_aon_hal.h b/components/hal/esp32c6/include/hal/lp_aon_hal.h index 86a88492397..d409cdbb22e 100644 --- a/components/hal/esp32c6/include/hal/lp_aon_hal.h +++ b/components/hal/esp32c6/include/hal/lp_aon_hal.h @@ -13,6 +13,8 @@ extern "C" { #endif #define lp_aon_hal_inform_wakeup_type(dslp) lp_aon_ll_inform_wakeup_type(dslp) +#define lp_aon_hal_store_wakeup_cause(wakeup_cause) lp_aon_ll_store_wakeup_cause(wakeup_cause) +#define lp_aon_hal_load_wakeup_cause() lp_aon_ll_load_wakeup_cause() #ifdef __cplusplus } diff --git a/components/hal/esp32c6/include/hal/lp_aon_ll.h b/components/hal/esp32c6/include/hal/lp_aon_ll.h index 2283a0dff6e..d2ce8514029 100644 --- a/components/hal/esp32c6/include/hal/lp_aon_ll.h +++ b/components/hal/esp32c6/include/hal/lp_aon_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,6 +85,24 @@ static inline void lp_aon_ll_inform_wakeup_type(bool dslp) } } +/** + * @brief Set the wakeup cause stored by LP core + * @param wakeup_cause The wakeup cause in PMU register + */ +static inline void lp_aon_ll_store_wakeup_cause(uint32_t wakeup_cause) +{ + REG_WRITE(RTC_LP_CORE_STORE_WAKEUP_REG, (REG_READ(RTC_LP_CORE_STORE_WAKEUP_REG) & 0x1) | ((wakeup_cause << 1) & 0xFFFFFFFE)); +} + +/** + * @brief Get the wakeup cause stored by LP core + * @return The wakeup cause cleared before LP core sleep + */ +static inline uint32_t lp_aon_ll_load_wakeup_cause(void) +{ + return (REG_READ(RTC_LP_CORE_STORE_WAKEUP_REG) & 0xFFFFFFFE) >> 1; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/lp_aon_hal.h b/components/hal/esp32p4/include/hal/lp_aon_hal.h index 31d7c574858..6152d3b9527 100644 --- a/components/hal/esp32p4/include/hal/lp_aon_hal.h +++ b/components/hal/esp32p4/include/hal/lp_aon_hal.h @@ -13,6 +13,8 @@ extern "C" { #endif #define lp_aon_hal_inform_wakeup_type(dslp) lp_sys_ll_inform_wakeup_type(dslp) +#define lp_aon_hal_store_wakeup_cause(wakeup_cause) lp_sys_ll_store_wakeup_cause(wakeup_cause) +#define lp_aon_hal_load_wakeup_cause() lp_sys_ll_load_wakeup_cause() #ifdef __cplusplus } diff --git a/components/hal/esp32p4/include/hal/lp_sys_ll.h b/components/hal/esp32p4/include/hal/lp_sys_ll.h index 366edbd4d52..71d5371e9ac 100644 --- a/components/hal/esp32p4/include/hal/lp_sys_ll.h +++ b/components/hal/esp32p4/include/hal/lp_sys_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -81,6 +81,25 @@ FORCE_INLINE_ATTR void lp_sys_ll_set_lp_mem_lowpower_mode(uint32_t mode) LP_SYS.lp_mem_aux_ctrl.lp_mem_lowpower_mode = mode; } #endif + +/** + * @brief Set the wakeup cause stored by LP core + * @param wakeup_cause The wakeup cause in PMU register + */ +static inline void lp_sys_ll_store_wakeup_cause(uint32_t wakeup_cause) +{ + REG_WRITE(RTC_LP_CORE_STORE_WAKEUP_REG, wakeup_cause); +} + +/** + * @brief Get the wakeup cause stored by LP core + * @return The wakeup cause cleared before LP core sleep + */ +static inline uint32_t lp_sys_ll_load_wakeup_cause(void) +{ + return REG_READ(RTC_LP_CORE_STORE_WAKEUP_REG); +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index caf04771c42..c4f2b17aaaf 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1686,3 +1686,7 @@ config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED bool default y + +config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE + bool + default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index c29faf2c3fa..4d544ae9e49 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -674,3 +674,4 @@ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ #define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */ #define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */ +#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index d45fc08eda1..dd9257054c8 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1435,6 +1435,10 @@ config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED bool default y +config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE + bool + default y + config SOC_DEBUG_HAVE_OCD_STUB_BINS bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 9f7c074d50d..08257dbc5dc 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -589,6 +589,7 @@ #define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ #define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */ +#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */ /*------------------------------------- DEBUG CAPS -------------------------------------*/ #define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index edbf2cbceec..9229f10dd75 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1994,3 +1994,7 @@ config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED bool default y + +config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE + bool + default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 20c3405c716..8c236201355 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -771,3 +771,4 @@ #define SOC_LP_CORE_SUPPORT_LP_ADC (1) /*!< LP ADC can be accessed from the LP-Core */ #define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */ #define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */ +#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */ diff --git a/components/ulp/lp_core/lp_core.c b/components/ulp/lp_core/lp_core.c index 18a6f38de09..293a286271c 100644 --- a/components/ulp/lp_core/lp_core.c +++ b/components/ulp/lp_core/lp_core.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,6 +35,11 @@ extern uint32_t _rtc_ulp_memory_start; #endif //ESP_ROM_HAS_LP_ROM +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE +#include "hal/lp_aon_hal.h" +#include "rom/rtc.h" +#endif + const static char* TAG = "ulp-lp-core"; #define WAKEUP_SOURCE_MAX_NUMBER 6 @@ -175,6 +180,19 @@ esp_err_t ulp_lp_core_load_binary(const uint8_t* program_binary, size_t program_ return ESP_OK; } +void ulp_lp_core_sleep_start(void) +{ +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE + /* LP store register to save wakeup cause for HP core to query. + * Using a hardware register avoids symbol linking issues between + * the independently compiled HP and LP core binaries. + * Save PMU wakeup cause to LP store register for HP core to query */ + lp_aon_hal_store_wakeup_cause(pmu_ll_hp_get_wakeup_cause(&PMU)); +#endif + + lp_core_ll_request_sleep(); +} + void ulp_lp_core_stop(void) { if (esp_cpu_dbgr_is_attached()) { @@ -188,7 +206,7 @@ void ulp_lp_core_stop(void) } /* Disable wake-up source and put lp core to sleep */ lp_core_ll_set_wakeup_source(0); - lp_core_ll_request_sleep(); + ulp_lp_core_sleep_start(); } void ulp_lp_core_sw_intr_to_lp_trigger(void) diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c index f332ebe9cc4..e976037af8f 100644 --- a/components/ulp/lp_core/lp_core/lp_core_utils.c +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -27,6 +27,10 @@ #include "ulp_lp_core_cpu_freq_shared.h" #include "ulp_lp_core_lp_uart_shared.h" #include "ulp_lp_core_uart.h" +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE +#include "hal/lp_aon_hal.h" +#include "rom/rtc.h" +#endif static uint32_t lp_wakeup_cause = 0; @@ -150,9 +154,22 @@ void ulp_lp_core_delay_cycles(uint32_t cycles) } } +void ulp_lp_core_sleep_start_lp_core(void) +{ +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE + /* LP store register to save wakeup cause for HP core to query. + * Using a hardware register avoids symbol linking issues between + * the independently compiled HP and LP core binaries. + * Save PMU wakeup cause to LP store register for HP core to query */ + lp_aon_hal_store_wakeup_cause(pmu_ll_hp_get_wakeup_cause(&PMU)); +#endif + + lp_core_ll_request_sleep(); +} + void ulp_lp_core_halt(void) { - lp_core_ll_request_sleep(); + ulp_lp_core_sleep_start_lp_core(); while (1); } @@ -161,7 +178,7 @@ void ulp_lp_core_stop_lp_core(void) { /* Disable wake-up source and put lp core to sleep */ lp_core_ll_set_wakeup_source(0); - lp_core_ll_request_sleep(); + ulp_lp_core_sleep_start_lp_core(); } void __attribute__((noreturn)) abort(void) From bb49e40841fefd191b27af7f1fb249c3ddd16367 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Mon, 16 Mar 2026 16:09:43 +0800 Subject: [PATCH 2/3] change(ulp): add HP Core wakeup causes save test cases --- .../esp_rom/esp32c6/include/esp32c6/rom/rtc.h | 2 +- .../lp_core_basic_tests/main/CMakeLists.txt | 8 +++ .../main/lp_core/test_main_exception.c | 8 ++- .../main/lp_core/test_main_halt.c | 20 ++++++++ .../main/lp_core/test_shared.h | 1 + .../lp_core_basic_tests/main/test_lp_core.c | 50 +++++++++++++++++++ 6 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_halt.c diff --git a/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h b/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h index 38c3ac3c351..a8d34a0ecef 100644 --- a/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h +++ b/components/esp_rom/esp32c6/include/esp32c6/rom/rtc.h @@ -53,7 +53,7 @@ extern "C" { * LP_AON_STORE7_REG FAST_RTC_MEMORY_CRC * LP_AON_STORE8_REG Store light sleep wake stub addr * LP_AON_STORE9_REG Store the sleep mode at bit[0] (0:light sleep 1:deep sleep) - * LP_AON_STORE10_REG LP core store wakeup cause at bit[31:2] + * LP_AON_STORE9_REG LP core store wakeup cause at bit[31:2] ************************************************************************************* */ diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt index 7a22fcef159..4c82d5eb16e 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt @@ -59,6 +59,10 @@ if(CONFIG_SOC_LP_VAD_SUPPORTED) set(lp_core_sources_vad "lp_core/test_main_vad.c") endif() +if(CONFIG_SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE) + set(lp_core_sources_halt "lp_core/test_main_halt.c") +endif() + idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "lp_core" REQUIRES ulp unity esp_timer test_utils @@ -136,4 +140,8 @@ list(APPEND lp_core_test_apps lp_core_test_app_prefix2) ulp_embed_binary(lp_core_test_app_exception "lp_core/test_main_exception.c" "${lp_core_exp_dep_srcs}") list(APPEND lp_core_test_apps lp_core_test_app_exception) +if(CONFIG_SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE) + ulp_embed_binary(lp_core_test_app_halt "lp_core/test_main_halt.c" "${lp_core_exp_dep_srcs}") +endif() + lp_core_test_app_checks(${lp_core_test_apps}) diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_exception.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_exception.c index fc6b14ad0a2..df9177898b9 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_exception.c +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_exception.c @@ -1,10 +1,16 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include "ulp_lp_core_utils.h" + int main(void) { + // Wait for 1 second to ensure the HP Core enters deep sleep + ulp_lp_core_delay_us(1000000); + + // Trigger an exception to wake up the HP Core asm volatile("unimp"); } diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_halt.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_halt.c new file mode 100644 index 00000000000..12b8ebfa268 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_halt.c @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "ulp_lp_core_utils.h" +#include "hal/lp_core_ll.h" + +int main(void) +{ + // Wait for 1 second to ensure the HP Core enters deep sleep + ulp_lp_core_delay_us(1000000); + + ulp_lp_core_wakeup_main_processor(); + /* Disable wake-up source and put lp core to sleep */ + lp_core_ll_set_wakeup_source(0); + ulp_lp_core_halt(); +} diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_shared.h b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_shared.h index 68f0eb8676d..83b5d5747fb 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_shared.h +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_shared.h @@ -56,6 +56,7 @@ typedef enum { LP_CORE_DELAY_US_CALIBRATION_TEST, LP_CORE_DEEP_SLEEP_WAKEUP_SHORT_DELAY_TEST, LP_CORE_DEEP_SLEEP_WAKEUP_LONG_DELAY_TEST, + LP_CORE_HALT_TEST, LP_CORE_LP_UART_WRITE_TEST, LP_CORE_LP_UART_READ_TEST, LP_CORE_LP_UART_MULTI_BYTE_READ_TEST, diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c index 1f29a061664..53a4bb9a92e 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c @@ -40,6 +40,12 @@ #include "hal/lp_core_ll.h" #include "hal/rtc_io_ll.h" #include "driver/rtc_io.h" +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE +#include "rom/rtc.h" +#include "esp_private/esp_pmu.h" +#include "lp_core_test_app_halt.h" +#include "hal/lp_aon_hal.h" +#endif extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_test_app_bin_start"); extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_test_app_bin_end"); @@ -64,6 +70,11 @@ extern const uint8_t lp_core_main_isr_bin_end[] asm("_binary_lp_core_test_app_ extern const uint8_t lp_core_main_exception_bin_start[] asm("_binary_lp_core_test_app_exception_bin_start"); extern const uint8_t lp_core_main_exception_bin_end[] asm("_binary_lp_core_test_app_exception_bin_end"); +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE +extern const uint8_t lp_core_main_halt_bin_start[] asm("_binary_lp_core_test_app_halt_bin_start"); +extern const uint8_t lp_core_main_halt_bin_end[] asm("_binary_lp_core_test_app_halt_bin_end"); +#endif + static void load_and_start_lp_core_firmware(ulp_lp_core_cfg_t* cfg, const uint8_t* firmware_start, const uint8_t* firmware_end) { TEST_ASSERT(ulp_lp_core_load_binary(firmware_start, @@ -630,4 +641,43 @@ static void check_reset_reason_ulp_trap_wakeup(void) TEST_CASE_MULTIPLE_STAGES("LP-core exception can wakeup main cpu", "[ulp]", lp_core_prep_exception_wakeup, check_reset_reason_ulp_trap_wakeup); + +#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE +static void do_ulp_wakeup_with_lp_timer_deepsleep_and_halt(void) +{ + /* Load ULP firmware and start the coprocessor */ + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER, + .lp_timer_sleep_duration_us = 1000000, // 1 second +#if ESP_ROM_HAS_LP_ROM + /* ROM Boot takes quite a bit longer, which skews the numbers of wake-ups. skip rom boot to keep the calculation simple */ + .skip_lp_rom_boot = true, +#endif + }; + + load_and_start_lp_core_firmware(&cfg, lp_core_main_halt_bin_start, lp_core_main_halt_bin_end); + + /* Setup wakeup triggers */ + TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK); + + /* Enter Deep Sleep */ + esp_deep_sleep_start(); + + UNITY_TEST_FAIL(__LINE__, "Should not get here!"); +} + +static void check_hp_core_wakeup_cause_saved(void) +{ + uint32_t lp_core_wakeup_cause_status0 = lp_aon_hal_load_wakeup_cause(); + TEST_ASSERT_EQUAL(RTC_LP_CORE_TRIG_EN, lp_core_wakeup_cause_status0 & RTC_LP_CORE_TRIG_EN); + TEST_ASSERT_EQUAL(BIT(ESP_SLEEP_WAKEUP_ULP), esp_sleep_get_wakeup_causes() & BIT(ESP_SLEEP_WAKEUP_ULP)); + + clear_test_cmds(); +} + +TEST_CASE_MULTIPLE_STAGES("HP core wakeup causes are saved after LP core halt", "[ulp]", + do_ulp_wakeup_with_lp_timer_deepsleep_and_halt, + check_hp_core_wakeup_cause_saved); +#endif //SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE + #endif //SOC_DEEP_SLEEP_SUPPORTED From 7f67950e83de8d9410ba1b0c4d96abd6684c0d84 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Tue, 21 Apr 2026 15:25:00 +0800 Subject: [PATCH 3/3] fix(esp_hw_support): fix LP core exception interrupt not being cleared --- components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h | 7 ++++++- components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h | 7 ++++++- components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h | 7 ++++++- components/esp_hw_support/sleep_modes.c | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h index 0c331f5f729..36af3b94080 100644 --- a/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -519,6 +519,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.reject = 1; } +FORCE_INLINE_ATTR void pmu_ll_hp_clear_lp_cpu_exc_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.lp_cpu_exc = 1; +} + FORCE_INLINE_ATTR void pmu_ll_hp_enable_sw_intr(pmu_dev_t *hw, bool enable) { hw->hp_ext.int_ena.sw = enable; diff --git a/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h index 24f31334aa8..3f8ee6ac871 100644 --- a/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -519,6 +519,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.reject = 1; } +FORCE_INLINE_ATTR void pmu_ll_hp_clear_lp_cpu_exc_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.lp_cpu_exc = 1; +} + FORCE_INLINE_ATTR void pmu_ll_hp_enable_sw_intr(pmu_dev_t *hw, bool enable) { hw->hp_ext.int_ena.sw = enable; diff --git a/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h index b43ef8f40c4..1822b1b63de 100644 --- a/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -567,6 +567,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.reject = 1; } +FORCE_INLINE_ATTR void pmu_ll_hp_clear_lp_cpu_exc_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.lp_exception = 1; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 132bb3ac806..54d135b0f74 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1004,6 +1004,7 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl rtc_hal_ulp_wakeup_enable(); #elif CONFIG_ULP_COPROC_TYPE_LP_CORE pmu_ll_hp_clear_sw_intr_status(&PMU); + pmu_ll_hp_clear_lp_cpu_exc_intr_status(&PMU); #else rtc_hal_ulp_int_clear(); #endif