fix(esp_pm): safely check ccompare validity in DFS update_ccompare

This commit is contained in:
wuzhenghui 2023-12-28 19:43:02 +08:00 committed by BOT
parent 090dd4047c
commit 6a63a5b69c

View File

@ -72,10 +72,13 @@
*/ */
#define CCOMPARE_UPDATE_TIMEOUT 1000000 #define CCOMPARE_UPDATE_TIMEOUT 1000000
/* When changing CCOMPARE, don't allow changes if the difference is less /* The number of CPU cycles required from obtaining the base ccount to configuring
* than this. This is to prevent setting CCOMPARE below CCOUNT. 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 #endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/* When light sleep is used, wake this number of microseconds earlier than /* When light sleep is used, wake this number of microseconds earlier than
@ -542,15 +545,17 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
* would happen without the frequency change. * would happen without the frequency change.
* Assumes that the new_frequency = old_frequency * s_ccount_mul / s_ccount_div. * 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 #if CONFIG_PM_UPDATE_CCOMPARE_HLI_WORKAROUND
/* disable level 4 and below */ /* disable level 4 and below */
uint32_t irq_status = XTOS_SET_INTLEVEL(XCHAL_DEBUGLEVEL - 2); uint32_t irq_status = XTOS_SET_INTLEVEL(XCHAL_DEBUGLEVEL - 2);
#endif #endif
uint32_t ccount = esp_cpu_get_cycle_count(); uint32_t ccount = esp_cpu_get_cycle_count();
uint32_t ccompare = XTHAL_GET_CCOMPARE(XT_TIMER_INDEX); 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 = ccompare - ccount;
uint32_t diff_scaled = (diff * s_ccount_mul + s_ccount_div - 1) / s_ccount_div; uint32_t diff_scaled = (diff * s_ccount_mul + s_ccount_div - 1) / s_ccount_div;
if (diff_scaled < _xt_tick_divisor) { if (diff_scaled < _xt_tick_divisor) {