From 417edbb2e2b5f5d1c636b8a79f21b35be6911285 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 7 May 2024 20:07:43 +0800 Subject: [PATCH 1/6] feat(esp_hw_support): introduce sub sleep mode config API --- .../include/esp_private/esp_sleep_internal.h | 28 +++++++++- components/esp_hw_support/sleep_modes.c | 56 +++++++++++++++++-- 2 files changed, 77 insertions(+), 7 deletions(-) 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 09cd05f3cd..87e3860205 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 @@ -31,13 +31,35 @@ typedef struct { void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx); #endif +typedef enum { + ESP_SLEEP_RTC_USE_RC_FAST_MODE, //!< The mode requested by RTC peripherals to keep RC_FAST clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (Will override the RC_FAST domain config by esp_sleep_pd_config) + ESP_SLEEP_DIG_USE_RC_FAST_MODE, //!< The mode requested by digital peripherals to keep RC_FAST clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the RC_FAST domain config by esp_sleep_pd_config) + ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, //!< Will enables the use of ADC and temperature sensor in monitor (ULP) mode. + ESP_SLEEP_ULTRA_LOW_MODE, //!< In ultra low mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. + ESP_SLEEP_RTC_FAST_USE_XTAL_MODE, //!< The mode in which the crystal is used as the RTC_FAST clock source, need keep XTAL on in HP_SLEEP mode when ULP is working. + ESP_SLEEP_DIG_USE_XTAL_MODE, //!< The mode requested by digital peripherals to keep XTAL clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the XTAL domain config by esp_sleep_pd_config) + ESP_SLEEP_MODE_MAX, +} esp_sleep_sub_mode_t; + /** - * @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode + * @brief Set sub-sleep power mode in sleep, mode enabled status is maintained by reference count. + * This submode configuration will kept after deep sleep wakeup. * - * @note This state is kept in RTC memory and will keep its value after a deep sleep wakeup + * @param mode sub-sleep mode type + * @param activate Activate or deactivate the sleep sub mode * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if either of the arguments is out of range */ -void esp_sleep_enable_adc_tsens_monitor(bool enable); +esp_err_t esp_sleep_sub_mode_config(esp_sleep_sub_mode_t mode, bool activate); + +/** + * Dump the sub-sleep power mode enable status + * @param stream The stream to dump to, if NULL then nothing will be dumped + * @return return the reference count array pointer + */ +int32_t* esp_sleep_sub_mode_dump_config(FILE *stream); #if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index d49c1920c8..62f977532f 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -272,6 +272,7 @@ static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED; static const char *TAG = "sleep"; static RTC_FAST_ATTR bool s_adc_tsen_enabled = false; +static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0 }; //in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. static bool s_ultra_low_enabled = false; @@ -893,6 +894,12 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m reject_triggers |= sleep_modem_reject_triggers(); } + + // Override user-configured XTAL power modes. + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_XTAL_MODE] && !deep_sleep) { + pd_flags &= ~RTC_SLEEP_PD_XTAL; + } + //Append some flags in addition to power domains uint32_t sleep_flags = pd_flags; if (s_adc_tsen_enabled) { @@ -2168,6 +2175,42 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_ return ESP_OK; } +esp_err_t esp_sleep_sub_mode_config(esp_sleep_sub_mode_t mode, bool activate) +{ + if (mode >= ESP_SLEEP_MODE_MAX) { + return ESP_ERR_INVALID_ARG; + } + + portENTER_CRITICAL_SAFE(&s_config.lock); + if (activate) { + s_sleep_sub_mode_ref_cnt[mode]++; + } else { + s_sleep_sub_mode_ref_cnt[mode]--; + } + assert(s_sleep_sub_mode_ref_cnt[mode] >= 0); + portEXIT_CRITICAL_SAFE(&s_config.lock); + return ESP_OK; +} + +int32_t* esp_sleep_sub_mode_dump_config(FILE *stream) { + if (stream) { + for (uint32_t mode = 0; mode < ESP_SLEEP_MODE_MAX; mode++) { + fprintf(stream, LOG_COLOR_I "%s : %s (cnt = %" PRId32 ")\n" LOG_RESET_COLOR, + (const char*[]){ + [ESP_SLEEP_RTC_USE_RC_FAST_MODE] = "ESP_SLEEP_RTC_USE_RC_FAST_MODE", + [ESP_SLEEP_DIG_USE_RC_FAST_MODE] = "ESP_SLEEP_DIG_USE_RC_FAST_MODE", + [ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE] = "ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE", + [ESP_SLEEP_ULTRA_LOW_MODE] = "ESP_SLEEP_ULTRA_LOW_MODE", + [ESP_SLEEP_RTC_FAST_USE_XTAL_MODE] = "ESP_SLEEP_RTC_FAST_USE_XTAL_MODE", + [ESP_SLEEP_DIG_USE_XTAL_MODE] = "ESP_SLEEP_DIG_USE_XTAL_MODE", + }[mode], + s_sleep_sub_mode_ref_cnt[mode] ? "ENABLED" : "DISABLED", + s_sleep_sub_mode_ref_cnt[mode]); + } + } + return s_sleep_sub_mode_ref_cnt; +} + /** * The modules in the CPU and modem power domains still depend on the top power domain. * To be safe, the CPU and Modem power domains must also be powered off and saved when @@ -2372,12 +2415,17 @@ esp_deep_sleep_disable_rom_logging(void) rtc_suppress_rom_log(); } -void esp_sleep_enable_adc_tsens_monitor(bool enable) +__attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void esp_sleep_periph_use_8m(bool use_or_not) { - s_adc_tsen_enabled = enable; + esp_sleep_sub_mode_config(ESP_SLEEP_USE_RC_FAST_MODE, use_or_not); } -void rtc_sleep_enable_ultra_low(bool enable) +__attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void esp_sleep_enable_adc_tsens_monitor(bool enable) { - s_ultra_low_enabled = enable; + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, enable); +} + +__attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void rtc_sleep_enable_ultra_low(bool enable) +{ + esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, enable); } From b1df2688ce63e2d6c9505ce110d6588c453f8581 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 30 Aug 2024 19:37:28 +0800 Subject: [PATCH 2/6] change(esp_hw_support): replace esp_sleep_enable_adc_tsens_monitor with new API --- components/esp_adc/adc_oneshot.c | 4 ++-- components/esp_hw_support/sleep_modes.c | 5 ++--- .../test_apps/rtc_power_modes/main/test_rtc_power.c | 13 ++++++------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/components/esp_adc/adc_oneshot.c b/components/esp_adc/adc_oneshot.c index 2d622687c0..bca7ba4ab6 100644 --- a/components/esp_adc/adc_oneshot.c +++ b/components/esp_adc/adc_oneshot.c @@ -127,7 +127,7 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a sar_periph_ctrl_adc_oneshot_power_acquire(); } else { #if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED - esp_sleep_enable_adc_tsens_monitor(true); + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, true); #endif } @@ -230,7 +230,7 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle) sar_periph_ctrl_adc_oneshot_power_release(); } else { #if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED - esp_sleep_enable_adc_tsens_monitor(false); + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, false); #endif } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 62f977532f..989934c98e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -271,7 +271,6 @@ static bool s_light_sleep_wakeup = false; static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED; static const char *TAG = "sleep"; -static RTC_FAST_ATTR bool s_adc_tsen_enabled = false; static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0 }; //in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. static bool s_ultra_low_enabled = false; @@ -679,7 +678,7 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s #if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7370 - if (!(deep_sleep && s_adc_tsen_enabled)){ + if (!(deep_sleep && (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE] != 0))){ sar_periph_ctrl_power_disable(); } #endif @@ -902,7 +901,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m //Append some flags in addition to power domains uint32_t sleep_flags = pd_flags; - if (s_adc_tsen_enabled) { + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE]) { sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR; } if (!s_ultra_low_enabled) { diff --git a/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c b/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c index d29d2fa6dc..3e5201a65d 100644 --- a/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c +++ b/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,7 +31,7 @@ static void test_deepsleep(void) // Deepsleep (with 8MD256 or ADC/TSEN in monitor) TEST_CASE("Power Test: DSLP_8MD256", "[pm]") { - esp_sleep_enable_adc_tsens_monitor(true); + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, true); test_deepsleep(); } @@ -40,7 +40,7 @@ TEST_CASE("Power Test: DSLP_8MD256", "[pm]") // Deepsleep (default) TEST_CASE("Power Test: DSLP_DEFAULT", "[pm]") { - esp_sleep_enable_adc_tsens_monitor(false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. test_deepsleep(); } @@ -48,7 +48,7 @@ TEST_CASE("Power Test: DSLP_DEFAULT", "[pm]") // Deepsleep (ultra-low power) TEST_CASE("Power Test: DSLP_ULTRA_LOW", "[pm]") { - esp_sleep_enable_adc_tsens_monitor(false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. extern void rtc_sleep_enable_ultra_low(bool); rtc_sleep_enable_ultra_low(true); @@ -125,8 +125,7 @@ TEST_CASE("Power Test: LSLP_8MD256", "[pm]") // Lightsleep (with ADC/TSEN in monitor) TEST_CASE("Power Test: LSLP_ADC_TSENS", "[pm]") { - extern void esp_sleep_enable_adc_tsens_monitor(bool); - esp_sleep_enable_adc_tsens_monitor(true); + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, true); test_lightsleep(); } @@ -134,7 +133,7 @@ TEST_CASE("Power Test: LSLP_ADC_TSENS", "[pm]") // Lightsleep (default) TEST_CASE("Power Test: LSLP_DEFAULT", "[pm]") { - esp_sleep_enable_adc_tsens_monitor(false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. test_lightsleep(); } From 7555686649ead47fb6541a438d8bd5cb9f0f1683 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Sat, 7 Sep 2024 02:03:55 +0800 Subject: [PATCH 3/6] change(esp_hw_support): replace rtc_sleep_enable_ultra_low with new API --- components/esp_hw_support/sleep_modes.c | 5 +++-- .../test_apps/rtc_power_modes/main/test_rtc_power.c | 4 +--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 989934c98e..01d82d9694 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "esp_attr.h" #include "esp_rom_caps.h" @@ -273,7 +274,6 @@ static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED; static const char *TAG = "sleep"; static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0 }; //in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. -static bool s_ultra_low_enabled = false; static bool s_periph_use_8m_flag = false; @@ -904,7 +904,8 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE]) { sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR; } - if (!s_ultra_low_enabled) { + + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_ULTRA_LOW_MODE] == 0) { sleep_flags |= RTC_SLEEP_NO_ULTRA_LOW; } if (periph_using_8m) { diff --git a/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c b/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c index 3e5201a65d..2904ec2efd 100644 --- a/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c +++ b/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c @@ -49,9 +49,7 @@ TEST_CASE("Power Test: DSLP_DEFAULT", "[pm]") TEST_CASE("Power Test: DSLP_ULTRA_LOW", "[pm]") { esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. - - extern void rtc_sleep_enable_ultra_low(bool); - rtc_sleep_enable_ultra_low(true); + esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, true); test_deepsleep(); } From 5184d7ec9824910cbfd745b17d285a970d700dca Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 7 May 2024 20:50:08 +0800 Subject: [PATCH 4/6] change(esp_hw_support): replace esp_sleep_periph_use_8m with new API --- components/esp_driver_ledc/src/ledc.c | 17 ++++++--- .../esp_hw_support/port/esp32/rtc_clk.c | 13 ++++++- .../esp_hw_support/port/esp32c2/rtc_clk.c | 12 +++++- .../esp_hw_support/port/esp32c3/rtc_clk.c | 13 ++++++- .../esp_hw_support/port/esp32s2/rtc_clk.c | 13 ++++++- .../esp_hw_support/port/esp32s3/rtc_clk.c | 13 ++++++- components/esp_hw_support/sleep_modes.c | 37 ++++++------------- 7 files changed, 78 insertions(+), 40 deletions(-) diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index a9d93f904a..4836fe422e 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -19,6 +19,7 @@ #include "driver/ledc.h" #include "esp_rom_gpio.h" #include "clk_ctrl_os.h" +#include "esp_private/esp_sleep_internal.h" #include "esp_private/periph_ctrl.h" #include "esp_private/gpio.h" #include "esp_private/esp_gpio_reserve.h" @@ -561,6 +562,16 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n } p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_num] = true; if (p_ledc_obj[speed_mode]->glb_clk != glb_clk) { +#if SOC_LIGHT_SLEEP_SUPPORTED + /* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */ + if (glb_clk == LEDC_SLOW_CLK_RC_FAST) { + /* Keep ESP_PD_DOMAIN_RC_FAST on during light sleep */ + esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, true); + } else if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_RC_FAST) { + /* No need to keep ESP_PD_DOMAIN_RC_FAST on during light sleep anymore */ + esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, false); + } +#endif // TODO: release old glb_clk (if not UNINIT), and acquire new glb_clk [clk_tree] p_ledc_obj[speed_mode]->glb_clk = glb_clk; LEDC_FUNC_CLOCK_ATOMIC() { @@ -571,12 +582,6 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n portEXIT_CRITICAL(&ledc_spinlock); ESP_LOGD(LEDC_TAG, "In slow speed mode, global clk set: %d", glb_clk); - - /* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */ -#if SOC_LIGHT_SLEEP_SUPPORTED - extern void esp_sleep_periph_use_8m(bool use_or_not); - esp_sleep_periph_use_8m(glb_clk == LEDC_SLOW_CLK_RC_FAST); -#endif } /* The divisor is correct, we can write in the hardware. */ diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index 8749102291..6a6e3fa3d5 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -10,6 +10,7 @@ #include #include "soc/rtc.h" #include "esp_private/rtc_clk.h" +#include "esp_private/esp_sleep_internal.h" #include "soc/rtc_periph.h" #include "soc/sens_reg.h" #include "soc/soc_caps.h" @@ -273,15 +274,23 @@ void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32 void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - clk_ll_rtc_slow_set_src(clk_src); +#ifndef BOOTLOADER_BUILD + soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src(); + // Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256. + if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true); + } else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false); + } +#endif + clk_ll_rtc_slow_set_src(clk_src); // The logic should be moved to BT driver if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { clk_ll_xtal32k_digi_enable(); } else { clk_ll_xtal32k_digi_disable(); } - esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } diff --git a/components/esp_hw_support/port/esp32c2/rtc_clk.c b/components/esp_hw_support/port/esp32c2/rtc_clk.c index 425b72b17f..59a6f63bff 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c2/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32c2/rom/rtc.h" #include "esp32c2/rom/uart.h" #include "soc/rtc.h" +#include "esp_private/esp_sleep_internal.h" #include "esp_private/rtc_clk.h" #include "soc/io_mux_reg.h" #include "soc/soc.h" @@ -66,6 +67,16 @@ bool rtc_clk_8md256_enabled(void) void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { +#ifndef BOOTLOADER_BUILD + soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src(); + // Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256. + if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true); + } else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false); + } +#endif + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? @@ -76,7 +87,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) } else { clk_ll_xtal32k_digi_disable(); } - esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk.c b/components/esp_hw_support/port/esp32c3/rtc_clk.c index 41ad7a967f..cec3673dbe 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c3/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32c3/rom/rtc.h" #include "soc/rtc.h" #include "soc/io_mux_reg.h" +#include "esp_private/esp_sleep_internal.h" #include "esp_private/rtc_clk.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" @@ -99,8 +100,17 @@ bool rtc_clk_8md256_enabled(void) void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - clk_ll_rtc_slow_set_src(clk_src); +#ifndef BOOTLOADER_BUILD + soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src(); + // Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256. + if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true); + } else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false); + } +#endif + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? */ @@ -109,7 +119,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) } else { clk_ll_xtal32k_digi_disable(); } - esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index 31836515ce..91637bf300 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32s2/rom/rtc.h" #include "soc/rtc.h" #include "esp_private/rtc_clk.h" +#include "esp_private/esp_sleep_internal.h" #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" #include "soc/soc_caps.h" @@ -174,8 +175,17 @@ void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32 void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - clk_ll_rtc_slow_set_src(clk_src); +#ifndef BOOTLOADER_BUILD + soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src(); + // Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256. + if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true); + } else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false); + } +#endif + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? */ @@ -184,7 +194,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) } else { clk_ll_xtal32k_digi_disable(); } - esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk.c b/components/esp_hw_support/port/esp32s3/rtc_clk.c index 3085c15f9d..4ad2f30239 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32s3/rom/rtc.h" #include "soc/rtc.h" #include "soc/io_mux_reg.h" +#include "esp_private/esp_sleep_internal.h" #include "esp_private/rtc_clk.h" #include "soc/rtc_io_reg.h" #include "esp_rom_sys.h" @@ -114,8 +115,17 @@ bool rtc_clk_8md256_enabled(void) void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - clk_ll_rtc_slow_set_src(clk_src); +#ifndef BOOTLOADER_BUILD + soc_rtc_slow_clk_src_t clk_src_before_switch = clk_ll_rtc_slow_get_src(); + // Keep the RTC8M_CLK on in sleep if RTC clock is rc_fast_d256. + if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch != SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch to RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, true); + } else if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 && clk_src_before_switch == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { // Switch away from RC_FAST_D256 + esp_sleep_sub_mode_config(ESP_SLEEP_RTC_USE_RC_FAST_MODE, false); + } +#endif + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? */ @@ -124,7 +134,6 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) } else { clk_ll_xtal32k_digi_disable(); } - esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 01d82d9694..145b6201a9 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -275,12 +275,6 @@ static const char *TAG = "sleep"; static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0 }; //in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. -static bool s_periph_use_8m_flag = false; - -void esp_sleep_periph_use_8m(bool use_or_not) -{ - s_periph_use_8m_flag = use_or_not; -} static uint32_t get_power_down_flags(void); #if SOC_PM_SUPPORT_EXT0_WAKEUP @@ -768,20 +762,6 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment; -#if SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 - //Keep the RTC8M_CLK on if RTC clock is rc_fast_d256. - bool rtc_using_8md256 = (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256); -#else - bool rtc_using_8md256 = false; -#endif - //Keep the RTC8M_CLK on if the ledc low-speed channel is clocked by RTC8M_CLK in lightsleep mode - bool periph_using_8m = !deep_sleep && s_periph_use_8m_flag; - - //Override user-configured power modes. - if (rtc_using_8md256 || periph_using_8m) { - pd_flags &= ~RTC_SLEEP_PD_INT_8M; - } - // Sleep UART prepare if (deep_sleep) { flush_uarts(); @@ -893,6 +873,10 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m reject_triggers |= sleep_modem_reject_triggers(); } + // Override user-configured FOSC power modes. + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_RTC_USE_RC_FAST_MODE]) { + pd_flags &= ~RTC_SLEEP_PD_INT_8M; + } // Override user-configured XTAL power modes. if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_XTAL_MODE] && !deep_sleep) { @@ -901,16 +885,19 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m //Append some flags in addition to power domains uint32_t sleep_flags = pd_flags; - if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE]) { + + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_RC_FAST_MODE] && !deep_sleep) { + pd_flags &= ~RTC_SLEEP_PD_INT_8M; + sleep_flags |= RTC_SLEEP_DIG_USE_8M; + } + + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE]) { sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR; } if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_ULTRA_LOW_MODE] == 0) { sleep_flags |= RTC_SLEEP_NO_ULTRA_LOW; } - if (periph_using_8m) { - sleep_flags |= RTC_SLEEP_DIG_USE_8M; - } #if CONFIG_ESP_SLEEP_DEBUG if (s_sleep_ctx != NULL) { @@ -2417,7 +2404,7 @@ esp_deep_sleep_disable_rom_logging(void) __attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void esp_sleep_periph_use_8m(bool use_or_not) { - esp_sleep_sub_mode_config(ESP_SLEEP_USE_RC_FAST_MODE, use_or_not); + esp_sleep_sub_mode_config(ESP_SLEEP_DIG_USE_RC_FAST_MODE, use_or_not); } __attribute__((deprecated("Please use esp_sleep_sub_mode_config instead"))) void esp_sleep_enable_adc_tsens_monitor(bool enable) From 0272fc405b9d90b6d143d640a54834d237867372 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 30 Aug 2024 19:31:42 +0800 Subject: [PATCH 5/6] change(esp_hw_support): update test cases with new sub-mode setting API --- .../rtc_power_modes/main/test_rtc_power.c | 58 +++++++++++++------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c b/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c index 2904ec2efd..94003fd63f 100644 --- a/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c +++ b/components/esp_hw_support/test_apps/rtc_power_modes/main/test_rtc_power.c @@ -21,6 +21,11 @@ static const char TAG[] = "rtc_power"; +static void check_deepsleep_reset(void) +{ + TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason()); +} + static void test_deepsleep(void) { esp_sleep_enable_timer_wakeup(2000000); @@ -28,31 +33,48 @@ static void test_deepsleep(void) esp_deep_sleep_start(); } -// Deepsleep (with 8MD256 or ADC/TSEN in monitor) -TEST_CASE("Power Test: DSLP_8MD256", "[pm]") -{ - esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, true); - test_deepsleep(); +static void test_set_adc_tsen_monitor_mode(void) { + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, true); } +static void test_unset_adc_tesen_monitor_mode(void) { + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, false); + TEST_ASSERT_EQUAL(0, esp_sleep_sub_mode_dump_config(NULL)[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE]); +} + +// Deepsleep (with 8MD256 or ADC/TSEN in monitor) +TEST_CASE_MULTIPLE_STAGES( "Power Test: DSLP_8MD256", "[pm]", + test_set_adc_tsen_monitor_mode, + test_deepsleep, + check_deepsleep_reset, + test_unset_adc_tesen_monitor_mode + ) + #if !CONFIG_RTC_CLK_SRC_INT_8MD256 // Deepsleep (default) -TEST_CASE("Power Test: DSLP_DEFAULT", "[pm]") -{ - esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. +TEST_CASE_MULTIPLE_STAGES( "Power Test: DSLP_DEFAULT", "[pm]", + test_deepsleep, + check_deepsleep_reset + ) - test_deepsleep(); +static void test_set_ultra_low_mode(void) { + esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, true); +} + +static void test_unset_ultra_low_mode(void) { + esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, false); + TEST_ASSERT_EQUAL(0, esp_sleep_sub_mode_dump_config(NULL)[ESP_SLEEP_ULTRA_LOW_MODE]); } // Deepsleep (ultra-low power) -TEST_CASE("Power Test: DSLP_ULTRA_LOW", "[pm]") -{ - esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. - esp_sleep_sub_mode_config(ESP_SLEEP_ULTRA_LOW_MODE, true); +TEST_CASE_MULTIPLE_STAGES( "Power Test: DSLP_ULTRA_LOW", "[pm]", + test_set_ultra_low_mode, + test_deepsleep, + check_deepsleep_reset, + test_unset_ultra_low_mode + ) - test_deepsleep(); -} #endif //!CONFIG_RTC_CLK_SRC_INT_8MD256 static void test_lightsleep(void) @@ -123,16 +145,14 @@ TEST_CASE("Power Test: LSLP_8MD256", "[pm]") // Lightsleep (with ADC/TSEN in monitor) TEST_CASE("Power Test: LSLP_ADC_TSENS", "[pm]") { - esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, true); - + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, true); test_lightsleep(); + esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, false); } // Lightsleep (default) TEST_CASE("Power Test: LSLP_DEFAULT", "[pm]") { - esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TESEN_MONITOR_MODE, false); //This is the default option. Add this line to avoid the case executing this case directly after the DSLP_8MD256 case. - test_lightsleep(); } #endif //!CONFIG_RTC_CLK_SRC_INT_8MD256 From fd79c593fb6167fb0e406c14843ccf3002ec8c62 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 3 Sep 2024 17:28:14 +0800 Subject: [PATCH 6/6] fix(ci): increase uart driver test memory leak threshold --- components/esp_driver_uart/test_apps/uart/main/test_app_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_driver_uart/test_apps/uart/main/test_app_main.c b/components/esp_driver_uart/test_apps/uart/main/test_app_main.c index f349470829..8eaeec99ab 100644 --- a/components/esp_driver_uart/test_apps/uart/main/test_app_main.c +++ b/components/esp_driver_uart/test_apps/uart/main/test_app_main.c @@ -9,7 +9,7 @@ #include "unity_test_utils.h" #include "esp_heap_caps.h" -#define TEST_MEMORY_LEAK_THRESHOLD (200) +#define TEST_MEMORY_LEAK_THRESHOLD (212) void setUp(void) {