feat(esp_hw_support): remeasure sleep_time_overhead_out if min_freq_mhz changed

This commit is contained in:
wuzhenghui
2025-03-21 20:49:24 +08:00
parent 81860c55d6
commit 41e6e25e2d
4 changed files with 36 additions and 5 deletions

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -124,6 +124,15 @@ void esp_sleep_mmu_retention(bool backup_or_restore);
bool mmu_domain_pd_allowed(void); bool mmu_domain_pd_allowed(void);
#endif #endif
/**
* @brief Notify the sleep process that `sleep_time_overhead_out` needs to be remeasured, which must be called
* in the following scenarios:
* 1. When the CPU frequency changes to below the crystal oscillator frequency.
* 2. When a new callback function is registered in the sleep process.
* 3. Other events occur that affect the execution time of the CPU sleep process.
*/
void esp_sleep_overhead_out_time_refresh(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -248,6 +248,7 @@ typedef struct {
#if SOC_DCDC_SUPPORTED #if SOC_DCDC_SUPPORTED
uint64_t rtc_ticks_at_ldo_prepare; uint64_t rtc_ticks_at_ldo_prepare;
#endif #endif
bool overhead_out_need_remeasure;
} sleep_config_t; } sleep_config_t;
@ -276,7 +277,8 @@ static sleep_config_t s_config = {
.lock = portMUX_INITIALIZER_UNLOCKED, .lock = portMUX_INITIALIZER_UNLOCKED,
.ccount_ticks_record = 0, .ccount_ticks_record = 0,
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
.wakeup_triggers = 0 .wakeup_triggers = 0,
.overhead_out_need_remeasure = true
}; };
/* Internal variable used to track if light sleep wakeup sources are to be /* Internal variable used to track if light sleep wakeup sources are to be
@ -291,6 +293,12 @@ static const char *TAG = "sleep";
static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0 }; 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. //in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT.
void esp_sleep_overhead_out_time_refresh(void)
{
portENTER_CRITICAL(&s_config.lock);
s_config.overhead_out_need_remeasure = true;
portEXIT_CRITICAL(&s_config.lock);
}
static uint32_t get_power_down_flags(void); static uint32_t get_power_down_flags(void);
static uint32_t get_sleep_flags(uint32_t pd_flags, bool deepsleep); static uint32_t get_sleep_flags(uint32_t pd_flags, bool deepsleep);
@ -1397,6 +1405,16 @@ esp_err_t esp_light_sleep_start(void)
// Re-calibrate the RTC clock // Re-calibrate the RTC clock
sleep_low_power_clock_calibration(false); sleep_low_power_clock_calibration(false);
if (s_config.overhead_out_need_remeasure) {
uint32_t cur_cpu_freq = esp_clk_cpu_freq() / MHZ;
uint32_t xtal_freq = rtc_clk_xtal_freq_get();
if (cur_cpu_freq < xtal_freq) {
s_config.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US * xtal_freq / cur_cpu_freq;
} else {
s_config.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US;
}
}
/* /*
* Adjustment time consists of parts below: * Adjustment time consists of parts below:
* 1. Hardware time waiting for internal 8M oscillate clock and XTAL; * 1. Hardware time waiting for internal 8M oscillate clock and XTAL;
@ -1561,6 +1579,7 @@ esp_err_t esp_light_sleep_start(void)
if (s_light_sleep_wakeup) { if (s_light_sleep_wakeup) {
s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
s_config.overhead_out_need_remeasure = false;
} }
portEXIT_CRITICAL(&s_config.lock); portEXIT_CRITICAL(&s_config.lock);
@ -1645,9 +1664,10 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
if (time_in_us > ((BIT64(SOC_LP_TIMER_BIT_WIDTH_LO + SOC_LP_TIMER_BIT_WIDTH_HI) - 1) / esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX)) * MHZ ) { if (time_in_us > ((BIT64(SOC_LP_TIMER_BIT_WIDTH_LO + SOC_LP_TIMER_BIT_WIDTH_HI) - 1) / esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX)) * MHZ ) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
portENTER_CRITICAL(&s_config.lock);
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN; s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
s_config.sleep_duration = time_in_us; s_config.sleep_duration = time_in_us;
portEXIT_CRITICAL(&s_config.lock);
return ESP_OK; return ESP_OK;
} }

View File

@ -19,6 +19,7 @@
#include "esp_clk_tree.h" #include "esp_clk_tree.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/crosscore_int.h" #include "esp_private/crosscore_int.h"
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
@ -478,6 +479,7 @@ esp_err_t esp_pm_configure(const void* vconfig)
// Enable the wakeup source here because the `esp_sleep_disable_wakeup_source` in the `else` // Enable the wakeup source here because the `esp_sleep_disable_wakeup_source` in the `else`
// branch must be called if corresponding wakeup source is already enabled. // branch must be called if corresponding wakeup source is already enabled.
esp_sleep_enable_timer_wakeup(0); esp_sleep_enable_timer_wakeup(0);
esp_sleep_overhead_out_time_refresh();
} else if (s_light_sleep_en) { } else if (s_light_sleep_en) {
// Since auto light-sleep will enable the timer wakeup source, to avoid affecting subsequent possible // Since auto light-sleep will enable the timer wakeup source, to avoid affecting subsequent possible
// deepsleep requests, disable the timer wakeup source here. // deepsleep requests, disable the timer wakeup source here.

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |