From d4c76b1f60902d2186f82490625c8cb845df9c86 Mon Sep 17 00:00:00 2001 From: Eren Terzioglu Date: Mon, 3 Nov 2025 10:17:34 +0100 Subject: [PATCH] arch/risc-v/esp32[-c3|-c6|-h2]: Add deep sleep support Add deep sleep support for risc-v based Espressif devices Signed-off-by: Eren Terzioglu --- arch/risc-v/src/common/espressif/Kconfig | 16 +++++- arch/risc-v/src/common/espressif/Make.defs | 2 +- arch/risc-v/src/common/espressif/esp_idle.c | 13 ++++- arch/risc-v/src/common/espressif/esp_pm.c | 53 +++++++++++++++++++ arch/risc-v/src/common/espressif/esp_pm.h | 34 +++++++++++- arch/risc-v/src/esp32h2/hal_esp32h2.mk | 1 + .../common/scripts/esp32c6_sections.ld | 39 ++++++++++++++ .../common/scripts/esp32h2_sections.ld | 35 ++++++++++++ 8 files changed, 187 insertions(+), 6 deletions(-) diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index dd5f835a3d7..c3e2abb29dc 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -274,7 +274,7 @@ config PM_EXT1_WAKEUP default n ---help--- Enable EXT1 wakeup functionality. - This allows the system to wake up from PM_STANDBY + This allows the system to wake up from PM_STANDBY or PM_SLEEP when a GPIO pin configured as an EXT1 wakeup source is triggered. menu "PM EXT1 Wakeup Sources" @@ -405,7 +405,7 @@ config PM_ULP_WAKEUP default n ---help--- Enable ULP coprocessor wakeup functionality. - This allows the system to wake up from PM_STANDBY + This allows the system to wake up from PM_STANDBY or PM_SLEEP when ULP app triggers HP core to wakeup with "ulp_lp_core_wakeup_main_processor" call on ULP app. @@ -707,6 +707,18 @@ config PM_ALARM_NSEC ---help--- Number of additional nanoseconds to wait in PM_STANDBY mode. +config PM_SLEEP_WAKEUP_SEC + int "PM_SLEEP delay (seconds)" + default 20 + ---help--- + Number of seconds to wait in PM_SLEEP. + +config PM_SLEEP_WAKEUP_NSEC + int "PM_SLEEP delay (nanoseconds)" + default 0 + ---help--- + Number of additional nanoseconds to wait in PM_SLEEP. + endif # PM endmenu # PM Configuration diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs index ad184059eeb..51e9efa9655 100644 --- a/arch/risc-v/src/common/espressif/Make.defs +++ b/arch/risc-v/src/common/espressif/Make.defs @@ -207,7 +207,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = a4ffd506e8f77632b90b053b21a788b29191bd93 + ESP_HAL_3RDPARTY_VERSION = 4f1113915eb5e9048cc885e38290a57dddb283c0 endif ifndef ESP_HAL_3RDPARTY_URL diff --git a/arch/risc-v/src/common/espressif/esp_idle.c b/arch/risc-v/src/common/espressif/esp_idle.c index f84c4ed0e24..de891629c64 100644 --- a/arch/risc-v/src/common/espressif/esp_idle.c +++ b/arch/risc-v/src/common/espressif/esp_idle.c @@ -55,6 +55,12 @@ # ifndef CONFIG_PM_ALARM_NSEC # define CONFIG_PM_ALARM_NSEC 0 # endif +# ifndef CONFIG_PM_SLEEP_WAKEUP_SEC +# define CONFIG_PM_SLEEP_WAKEUP_SEC 20 +# endif +# ifndef CONFIG_PM_SLEEP_WAKEUP_NSEC +# define CONFIG_PM_SLEEP_WAKEUP_NSEC 0 +# endif #endif /**************************************************************************** @@ -149,10 +155,13 @@ static void up_idlepm(void) break; case PM_SLEEP: - + { /* Enter Deep-sleep mode */ - break; + esp_pmsleep(CONFIG_PM_SLEEP_WAKEUP_SEC * 1000000 + + CONFIG_PM_SLEEP_WAKEUP_NSEC / 1000); + } + break; default: break; diff --git a/arch/risc-v/src/common/espressif/esp_pm.c b/arch/risc-v/src/common/espressif/esp_pm.c index bd28e66127b..7d3dfcbf69e 100644 --- a/arch/risc-v/src/common/espressif/esp_pm.c +++ b/arch/risc-v/src/common/espressif/esp_pm.c @@ -198,6 +198,8 @@ static void IRAM_ATTR esp_pm_ext1_wakeup_prepare(void) esp_sleep_enable_ext1_wakeup_io(pin_mask, level_mode); } } + + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); } #endif /* CONFIG_PM_EXT1_WAKEUP */ @@ -462,6 +464,31 @@ int esp_pm_light_sleep_start(uint64_t *sleep_time) return ret; } +/**************************************************************************** + * Name: esp_pm_deep_sleep_start + * + * Description: + * Enter deep sleep mode + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_pm_deep_sleep_start(void) +{ + esp_deep_sleep_start(); + + /* Because RTC is in a slower clock domain than the CPU, it + * can take several CPU cycles for the sleep mode to start. + */ + + while (1); +} + /**************************************************************************** * Name: esp_pmstandby * @@ -526,3 +553,29 @@ void esp_pmstandby(uint64_t time_in_us) } #endif } + +/**************************************************************************** + * Name: esp_pmsleep + * + * Description: + * Enter pm sleep (deep sleep) mode. + * + * Input Parameters: + * time_in_us - The maximum time to sleep in microseconds. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_pmsleep(uint64_t time_in_us) +{ +#ifdef CONFIG_PM_EXT1_WAKEUP + esp_pm_ext1_wakeup_prepare(); +#endif +#ifdef CONFIG_PM_ULP_WAKEUP + esp_sleep_enable_ulp_wakeup(); +#endif + esp_pm_sleep_enable_timer_wakeup(time_in_us); + esp_pm_deep_sleep_start(); +} diff --git a/arch/risc-v/src/common/espressif/esp_pm.h b/arch/risc-v/src/common/espressif/esp_pm.h index cb50a4fcab8..892278ad4f7 100644 --- a/arch/risc-v/src/common/espressif/esp_pm.h +++ b/arch/risc-v/src/common/espressif/esp_pm.h @@ -67,7 +67,23 @@ extern "C" int esp_pm_light_sleep_start(uint64_t *sleep_time); /**************************************************************************** - * Name: esp_pmstandby + * Name: esp_pm_deep_sleep_start + * + * Description: + * Enter deep sleep mode + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_pm_deep_sleep_start(void); + +/**************************************************************************** + * Name: esp_pm_pmstandby * * Description: * Enter pm standby (light sleep) mode. @@ -82,6 +98,22 @@ int esp_pm_light_sleep_start(uint64_t *sleep_time); void esp_pmstandby(uint64_t time_in_us); +/**************************************************************************** + * Name: esp_pmsleep + * + * Description: + * Enter pm sleep (deep sleep) mode. + * + * Input Parameters: + * time_in_us - The maximum time to sleep in microseconds. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_pmsleep(uint64_t time_in_us); + #endif /* CONFIG_PM */ #ifdef __cplusplus diff --git a/arch/risc-v/src/esp32h2/hal_esp32h2.mk b/arch/risc-v/src/esp32h2/hal_esp32h2.mk index c039224082a..9baa02ec277 100644 --- a/arch/risc-v/src/esp32h2/hal_esp32h2.mk +++ b/arch/risc-v/src/esp32h2/hal_esp32h2.mk @@ -157,6 +157,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sar_periph_ctrl.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)systimer.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)power_supply$(DELIM)brownout.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)power_supply$(DELIM)vbat.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_mm$(DELIM)esp_mmu_map.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_mm$(DELIM)esp_cache.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_mm$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)ext_mem_layout.c diff --git a/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld b/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld index 577d157a93e..ea1e08d7c0f 100644 --- a/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld +++ b/boards/risc-v/esp32c6/common/scripts/esp32c6_sections.ld @@ -556,21 +556,60 @@ SECTIONS .rtc.text : { . = ALIGN(4); + _rtc_fast_start = ABSOLUTE(.); + _rtc_text_start = ABSOLUTE(.); *(.rtc.literal .rtc.text) *(.rtc.entry.text) /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */ . += 16; . = ALIGN(4); + _rtc_text_end = ABSOLUTE(.); + } > lp_ram_seg AT > ROM + /* RTC fast memory section */ + + .rtc.force_fast : + { + . = ALIGN(4); + _rtc_force_fast_start = ABSOLUTE(.); + + *(.rtc.force_fast .rtc.force_fast.*) + . = ALIGN(4); + _rtc_force_fast_end = ABSOLUTE(.); } > lp_ram_seg AT > ROM /* RTC BSS section. */ .rtc.bss (NOLOAD) : { + _rtc_bss_start = ABSOLUTE(.); *(.rtc.bss) + _rtc_bss_end = ABSOLUTE(.); } > lp_ram_seg + + /* RTC NOINIT section. */ + + .rtc_noinit (NOLOAD) : + { + . = ALIGN(4); + _rtc_noinit_start = ABSOLUTE(.); + *(.rtc_noinit .rtc_noinit.*) + . = ALIGN(4) ; + _rtc_noinit_end = ABSOLUTE(.); + } > lp_ram_seg + + /* RTC slow memory section */ + + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4); + _rtc_force_slow_end = ABSOLUTE(.); + } > lp_ram_seg AT > ROM + .rtc.data : { _rtc_data_start = ABSOLUTE(.); diff --git a/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld b/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld index 06375668a3f..677d916f363 100644 --- a/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld +++ b/boards/risc-v/esp32h2/common/scripts/esp32h2_sections.ld @@ -558,6 +558,19 @@ SECTIONS *(.rtc.entry.text) *(.rtc.literal .rtc.text) + _rtc_text_end = ABSOLUTE(.); + } >rtc_iram_seg + + /* RTC fast memory section */ + + .rtc.force_fast : + { + . = ALIGN(4); + _rtc_force_fast_start = ABSOLUTE(.); + + *(.rtc.force_fast .rtc.force_fast.*) + . = ALIGN(4); + _rtc_force_fast_end = ABSOLUTE(.); } >rtc_iram_seg /* RTC BSS section. */ @@ -577,6 +590,28 @@ SECTIONS *(.rtc.rodata.*) } >rtc_iram_seg + /* RTC NOINIT section. */ + + .rtc_noinit (NOLOAD) : + { + . = ALIGN(4); + _rtc_noinit_start = ABSOLUTE(.); + *(.rtc_noinit .rtc_noinit.*) + . = ALIGN(4) ; + _rtc_noinit_end = ABSOLUTE(.); + } >rtc_iram_seg + + /* RTC slow memory section */ + + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4); + _rtc_force_slow_end = ABSOLUTE(.); + } >rtc_iram_seg + /* This section holds RTC data that should have fixed addresses. * The data are not initialized at power-up and are retained during deep sleep. */