mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/tickless_idle_single_core' into 'master'
freertos, pm: fix tickless idle not entered in single core mode See merge request idf/esp-idf!3584
This commit is contained in:
commit
28f1e1597b
@ -81,11 +81,20 @@ static uint32_t s_ccount_div;
|
||||
static uint32_t s_ccount_mul;
|
||||
|
||||
#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
|
||||
* 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
|
||||
|
||||
/* 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
|
||||
int core_id = xPortGetCoreID();
|
||||
if (!s_entered_light_sleep[core_id]) {
|
||||
if (s_skipped_light_sleep[core_id]) {
|
||||
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
|
||||
asm("waiti 0");
|
||||
@ -477,10 +490,35 @@ void esp_pm_impl_waiti()
|
||||
|
||||
#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 )
|
||||
{
|
||||
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 */
|
||||
int64_t next_esp_timer_alarm = esp_timer_get_next_alarm();
|
||||
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);
|
||||
#endif
|
||||
/* Enter sleep */
|
||||
int core_id = xPortGetCoreID();
|
||||
ESP_PM_TRACE_ENTER(SLEEP, core_id);
|
||||
int64_t sleep_start = esp_timer_get_time();
|
||||
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);
|
||||
|
@ -2147,6 +2147,8 @@ void vTaskSuspendAll( void )
|
||||
|
||||
#if ( configUSE_TICKLESS_IDLE != 0 )
|
||||
|
||||
#if ( portNUM_PROCESSORS > 1 )
|
||||
|
||||
static BaseType_t xHaveReadyTasks()
|
||||
{
|
||||
for (int i = tskIDLE_PRIORITY + 1; i < configMAX_PRIORITIES; ++i)
|
||||
@ -2163,6 +2165,7 @@ void vTaskSuspendAll( void )
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
#endif // portNUM_PROCESSORS > 1
|
||||
|
||||
static TickType_t prvGetExpectedIdleTime( void )
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user