From 8847d25638306b6a2f6093126e3e280fcf30aa1e Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 28 Dec 2023 19:43:02 +0800 Subject: [PATCH] fix(esp_pm): safely check ccompare validity in DFS update_ccompare --- components/esp_pm/pm_impl.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 5370a29d69..2e5ec4c622 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -71,10 +71,13 @@ */ #define CCOMPARE_UPDATE_TIMEOUT 1000000 -/* When changing CCOMPARE, don't allow changes if the difference is less - * than this. This is to prevent setting CCOMPARE below CCOUNT. +/* The number of CPU cycles required from obtaining the base ccount to configuring + the calculated ccompare value. (In order to avoid ccompare being updated to a value + smaller than the current ccount, this update should be discarded if the next tick + is too close to this moment, and this value is used to calculate the threshold for + determining whether or not a skip is required.) */ -#define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000 +#define CCOMPARE_PREPARE_CYCLES_IN_FREQ_UPDATE 60 #endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /* When light sleep is used, wake this number of microseconds earlier than @@ -540,15 +543,17 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode) * would happen without the frequency change. * Assumes that the new_frequency = old_frequency * s_ccount_mul / s_ccount_div. */ -static void IRAM_ATTR update_ccompare(void) +static __attribute__((optimize("-O2"))) void IRAM_ATTR update_ccompare(void) { + uint32_t ccompare_min_cycles_in_future = ((s_ccount_div + s_ccount_mul - 1) / s_ccount_mul) * CCOMPARE_PREPARE_CYCLES_IN_FREQ_UPDATE; #if CONFIG_PM_UPDATE_CCOMPARE_HLI_WORKAROUND /* disable level 4 and below */ uint32_t irq_status = XTOS_SET_INTLEVEL(XCHAL_DEBUGLEVEL - 2); #endif uint32_t ccount = cpu_hal_get_cycle_count(); uint32_t ccompare = XTHAL_GET_CCOMPARE(XT_TIMER_INDEX); - if ((ccompare - CCOMPARE_MIN_CYCLES_IN_FUTURE) - ccount < UINT32_MAX / 2) { + + if ((ccompare - ccompare_min_cycles_in_future) - ccount < UINT32_MAX / 2) { uint32_t diff = ccompare - ccount; uint32_t diff_scaled = (diff * s_ccount_mul + s_ccount_div - 1) / s_ccount_div; if (diff_scaled < _xt_tick_divisor) {