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)