From 96c2b34eb9d1f5a0c5168c042ecf363d63c67f51 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 1 Nov 2018 19:38:48 +0800 Subject: [PATCH] pm: prevent entering light sleep again immediately after wakeup When light sleep is finished on one CPU, it is possible that the other CPU will enter light sleep again very soon, before interrupts on the first CPU get a chance to run. To avoid such situation, set a flag for the other CPU to skip light sleep attempt. --- components/esp32/pm_esp32.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/components/esp32/pm_esp32.c b/components/esp32/pm_esp32.c index b53ea079b..0cf7e2d20 100644 --- a/components/esp32/pm_esp32.c +++ b/components/esp32/pm_esp32.c @@ -86,6 +86,15 @@ static uint32_t s_ccount_mul; * to be invoked or not. */ static bool s_skipped_light_sleep[portNUM_PROCESSORS]; + +#if portNUM_PROCESSORS == 2 +/* When light sleep is finished on one CPU, it is possible that the other CPU + * will enter light sleep again very soon, before interrupts on the first CPU + * get a chance to run. To avoid such situation, set a flag for the other CPU to + * skip light sleep attempt. + */ +static bool s_skip_light_sleep[portNUM_PROCESSORS]; +#endif // portNUM_PROCESSORS == 2 #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE /* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU. @@ -481,14 +490,35 @@ void esp_pm_impl_waiti() #if CONFIG_FREERTOS_USE_TICKLESS_IDLE -void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) +static inline bool IRAM_ATTR should_skip_light_sleep(int core_id) { - portENTER_CRITICAL(&s_switch_lock); - int core_id = xPortGetCoreID(); +#if portNUM_PROCESSORS == 2 + if (s_skip_light_sleep[core_id]) { + s_skip_light_sleep[core_id] = false; + s_skipped_light_sleep[core_id] = true; + return true; + } +#endif // portNUM_PROCESSORS == 2 if (s_mode != PM_MODE_LIGHT_SLEEP || s_is_switching) { s_skipped_light_sleep[core_id] = true; } else { s_skipped_light_sleep[core_id] = false; + } + return s_skipped_light_sleep[core_id]; +} + +static inline void IRAM_ATTR other_core_should_skip_light_sleep(int core_id) +{ +#if portNUM_PROCESSORS == 2 + s_skip_light_sleep[!core_id] = true; +#endif +} + +void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) +{ + portENTER_CRITICAL(&s_switch_lock); + int core_id = xPortGetCoreID(); + if (!should_skip_light_sleep(core_id)) { /* Calculate how much we can sleep */ int64_t next_esp_timer_alarm = esp_timer_get_next_alarm(); int64_t now = esp_timer_get_time(); @@ -523,6 +553,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) ; } } + other_core_should_skip_light_sleep(core_id); } } portEXIT_CRITICAL(&s_switch_lock);