Merge branch 'bugfix/fix_systick_lost_in_esp32_dfs_v5.1' into 'release/v5.1'

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

See merge request espressif/esp-idf!28562
This commit is contained in:
Jiang Jiang Jian 2024-01-19 16:44:39 +08:00
commit e1b257934c

View File

@ -56,10 +56,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
@ -662,15 +665,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 = esp_cpu_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) {