|
@@ -81,11 +81,20 @@ static uint32_t s_ccount_div;
|
|
|
static uint32_t s_ccount_mul;
|
|
static uint32_t s_ccount_mul;
|
|
|
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
-/* Indicates if light sleep entry was successful for given CPU.
|
|
|
|
|
|
|
+/* Indicates if light sleep entry was skipped in vApplicationSleep for given CPU.
|
|
|
* This in turn gets used in IDLE hook to decide if `waiti` needs
|
|
* This in turn gets used in IDLE hook to decide if `waiti` needs
|
|
|
* to be invoked or not.
|
|
* to be invoked or not.
|
|
|
*/
|
|
*/
|
|
|
-static bool s_entered_light_sleep[portNUM_PROCESSORS];
|
|
|
|
|
|
|
+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
|
|
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
|
|
|
/* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU.
|
|
/* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU.
|
|
@@ -465,10 +474,14 @@ void esp_pm_impl_waiti()
|
|
|
{
|
|
{
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
int core_id = xPortGetCoreID();
|
|
int core_id = xPortGetCoreID();
|
|
|
- if (!s_entered_light_sleep[core_id]) {
|
|
|
|
|
|
|
+ if (s_skipped_light_sleep[core_id]) {
|
|
|
asm("waiti 0");
|
|
asm("waiti 0");
|
|
|
- } else {
|
|
|
|
|
- s_entered_light_sleep[core_id] = false;
|
|
|
|
|
|
|
+ /* Interrupt took the CPU out of waiti and s_rtos_lock_handle[core_id]
|
|
|
|
|
+ * is now taken. However since we are back to idle task, we can release
|
|
|
|
|
+ * the lock so that vApplicationSleep can attempt to enter light sleep.
|
|
|
|
|
+ */
|
|
|
|
|
+ esp_pm_impl_idle_hook();
|
|
|
|
|
+ s_skipped_light_sleep[core_id] = false;
|
|
|
}
|
|
}
|
|
|
#else
|
|
#else
|
|
|
asm("waiti 0");
|
|
asm("waiti 0");
|
|
@@ -477,10 +490,35 @@ void esp_pm_impl_waiti()
|
|
|
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
|
|
|
|
|
+static inline bool IRAM_ATTR should_skip_light_sleep(int core_id)
|
|
|
|
|
+{
|
|
|
|
|
+#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 )
|
|
void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
|
|
|
{
|
|
{
|
|
|
portENTER_CRITICAL(&s_switch_lock);
|
|
portENTER_CRITICAL(&s_switch_lock);
|
|
|
- if (s_mode == PM_MODE_LIGHT_SLEEP && !s_is_switching) {
|
|
|
|
|
|
|
+ int core_id = xPortGetCoreID();
|
|
|
|
|
+ if (!should_skip_light_sleep(core_id)) {
|
|
|
/* Calculate how much we can sleep */
|
|
/* Calculate how much we can sleep */
|
|
|
int64_t next_esp_timer_alarm = esp_timer_get_next_alarm();
|
|
int64_t next_esp_timer_alarm = esp_timer_get_next_alarm();
|
|
|
int64_t now = esp_timer_get_time();
|
|
int64_t now = esp_timer_get_time();
|
|
@@ -494,7 +532,6 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
|
|
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
|
|
#endif
|
|
#endif
|
|
|
/* Enter sleep */
|
|
/* Enter sleep */
|
|
|
- int core_id = xPortGetCoreID();
|
|
|
|
|
ESP_PM_TRACE_ENTER(SLEEP, core_id);
|
|
ESP_PM_TRACE_ENTER(SLEEP, core_id);
|
|
|
int64_t sleep_start = esp_timer_get_time();
|
|
int64_t sleep_start = esp_timer_get_time();
|
|
|
esp_light_sleep_start();
|
|
esp_light_sleep_start();
|
|
@@ -516,7 +553,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
|
|
|
;
|
|
;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- s_entered_light_sleep[core_id] = true;
|
|
|
|
|
|
|
+ other_core_should_skip_light_sleep(core_id);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
portEXIT_CRITICAL(&s_switch_lock);
|
|
portEXIT_CRITICAL(&s_switch_lock);
|