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 e30043804b
commit a1471f4f78
3 changed files with 33 additions and 1 deletions

View File

@@ -158,6 +158,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

@@ -259,6 +259,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;
@@ -290,7 +291,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
@@ -305,6 +307,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);
@@ -1403,6 +1411,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;
@@ -1567,6 +1585,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);
@@ -1655,8 +1674,10 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
#endif #endif
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

@@ -20,6 +20,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"
@@ -480,6 +481,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.