freertos: Fix usage of vTaskSuspendAll()/xTaskResumeAll()

IDF FreeRTOS uses vTaskSuspendAll()/xTaskResumeAll() to stop preemption
on a particular core. However, those functions behave differently in FreeRTOS SMP.
This commit replaces all calls of vTaskSuspendAll()/xTaskResumeAll() with
vTaskPreemptionDisable()/vTaskPreemptionEnable() when compiling with SMP FreeRTOS.
pull/8526/head
Darian Leung 2022-02-25 21:50:58 +08:00
rodzic 883da858b0
commit 27f5c90e2e
5 zmienionych plików z 108 dodań i 0 usunięć

Wyświetl plik

@ -81,8 +81,13 @@ void IRAM_ATTR esp_restart(void)
} }
} }
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
// Disable scheduler on this core. // Disable scheduler on this core.
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
bool digital_reset_needed = false; bool digital_reset_needed = false;
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE

Wyświetl plik

@ -43,8 +43,13 @@ static void do_deep_sleep_from_app_cpu(void)
{ {
xTaskCreatePinnedToCore(&deep_sleep_task, "ds", 2048, NULL, 5, NULL, 1); xTaskCreatePinnedToCore(&deep_sleep_task, "ds", 2048, NULL, 5, NULL, 1);
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
// keep running some non-IRAM code // keep running some non-IRAM code
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
while (true) { while (true) {
; ;

Wyświetl plik

@ -1,4 +1,10 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Tests for FreeRTOS scheduler suspend & resume all tasks */ /* Tests for FreeRTOS scheduler suspend & resume all tasks */
#include "sdkconfig.h"
#include <stdio.h> #include <stdio.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
@ -90,7 +96,12 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
TEST_ASSERT(isr_count > 10); TEST_ASSERT(isr_count > 10);
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
esp_intr_noniram_disable(); esp_intr_noniram_disable();
unsigned no_sched_task = count_config.counter; unsigned no_sched_task = count_config.counter;
@ -107,7 +118,12 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
// will preempt and count at least one more item // will preempt and count at least one more item
esp_intr_noniram_enable(); esp_intr_noniram_enable();
esp_intr_enable(intr_handle); esp_intr_enable(intr_handle);
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
#else
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
TEST_ASSERT_NOT_EQUAL(count_config.counter, no_sched_task); TEST_ASSERT_NOT_EQUAL(count_config.counter, no_sched_task);
} }
@ -152,7 +168,12 @@ TEST_CASE("Scheduler disabled can wake multiple tasks on resume", "[freertos]")
} }
/* Suspend scheduler on this CPU */ /* Suspend scheduler on this CPU */
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
/* Give all the semaphores once. This will wake tasks immediately on the other /* Give all the semaphores once. This will wake tasks immediately on the other
CPU, but they are deferred here until the scheduler resumes. CPU, but they are deferred here until the scheduler resumes.
@ -174,7 +195,12 @@ TEST_CASE("Scheduler disabled can wake multiple tasks on resume", "[freertos]")
} }
/* Resume scheduler */ /* Resume scheduler */
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
#else
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
/* Now the tasks on both CPUs should have been woken once and counted once. */ /* Now the tasks on both CPUs should have been woken once and counted once. */
for (int p = 0; p < portNUM_PROCESSORS; p++) { for (int p = 0; p < portNUM_PROCESSORS; p++) {
@ -197,12 +223,22 @@ TEST_CASE("Scheduler disabled can wake multiple tasks on resume", "[freertos]")
static volatile bool sched_suspended; static volatile bool sched_suspended;
static void suspend_scheduler_5ms_task_fn(void *ignore) static void suspend_scheduler_5ms_task_fn(void *ignore)
{ {
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
sched_suspended = true; sched_suspended = true;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
esp_rom_delay_us(1000); esp_rom_delay_us(1000);
} }
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
#else
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
sched_suspended = false; sched_suspended = false;
vTaskDelete(NULL); vTaskDelete(NULL);
} }

Wyświetl plik

@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Tests for FreeRTOS task suspend & resume */ /* Tests for FreeRTOS task suspend & resume */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -196,11 +201,21 @@ static bool suspend_both_cpus;
static void IRAM_ATTR suspend_scheduler_while_block_set(void *arg) static void IRAM_ATTR suspend_scheduler_while_block_set(void *arg)
{ {
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
while (block) { }; while (block) { };
esp_rom_delay_us(1); esp_rom_delay_us(1);
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
#else
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
} }
static void IRAM_ATTR suspend_scheduler_on_both_cpus(void) static void IRAM_ATTR suspend_scheduler_on_both_cpus(void)
@ -210,13 +225,23 @@ static void IRAM_ATTR suspend_scheduler_on_both_cpus(void)
TEST_ESP_OK(esp_ipc_call((xPortGetCoreID() == 0) ? 1 : 0, &suspend_scheduler_while_block_set, NULL)); TEST_ESP_OK(esp_ipc_call((xPortGetCoreID() == 0) ? 1 : 0, &suspend_scheduler_while_block_set, NULL));
} }
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
} }
static void IRAM_ATTR resume_scheduler_on_both_cpus(void) static void IRAM_ATTR resume_scheduler_on_both_cpus(void)
{ {
block = false; block = false;
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
#else
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
} }
static const int waiting_ms = 2000; static const int waiting_ms = 2000;

Wyświetl plik

@ -112,7 +112,15 @@ void spi_flash_op_unlock(void)
void IRAM_ATTR spi_flash_op_block_func(void *arg) void IRAM_ATTR spi_flash_op_block_func(void *arg)
{ {
// Disable scheduler on this CPU // Disable scheduler on this CPU
#ifdef CONFIG_FREERTOS_SMP
/*
Note: FreeRTOS SMP has changed the behavior of scheduler suspension. But the vTaskPreemptionDisable() function should
achieve the same affect as before (i.e., prevent the current task from being preempted).
*/
vTaskPreemptionDisable(NULL);
#else
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
// Restore interrupts that aren't located in IRAM // Restore interrupts that aren't located in IRAM
esp_intr_noniram_disable(); esp_intr_noniram_disable();
uint32_t cpuid = (uint32_t) arg; uint32_t cpuid = (uint32_t) arg;
@ -128,8 +136,13 @@ void IRAM_ATTR spi_flash_op_block_func(void *arg)
spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]); spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);
// Restore interrupts that aren't located in IRAM // Restore interrupts that aren't located in IRAM
esp_intr_noniram_enable(); esp_intr_noniram_enable();
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
#else
// Re-enable scheduler // Re-enable scheduler
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
} }
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void) void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
@ -167,8 +180,13 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
// Busy loop and wait for spi_flash_op_block_func to disable cache // Busy loop and wait for spi_flash_op_block_func to disable cache
// on the other CPU // on the other CPU
} }
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
#else
// Disable scheduler on the current CPU // Disable scheduler on the current CPU
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
// Can now set the priority back to the normal one // Can now set the priority back to the normal one
vTaskPrioritySet(NULL, old_prio); vTaskPrioritySet(NULL, old_prio);
// This is guaranteed to run on CPU <cpuid> because the other CPU is now // This is guaranteed to run on CPU <cpuid> because the other CPU is now
@ -216,7 +234,12 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu(void)
// But esp_intr_noniram_enable has to be called on the same CPU which // But esp_intr_noniram_enable has to be called on the same CPU which
// called esp_intr_noniram_disable // called esp_intr_noniram_disable
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
#ifdef CONFIG_FREERTOS_SMP
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
#else
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
} }
// Release API lock // Release API lock
spi_flash_op_unlock(); spi_flash_op_unlock();
@ -253,12 +276,26 @@ void spi_flash_init_lock(void)
void spi_flash_op_lock(void) void spi_flash_op_lock(void)
{ {
#ifdef CONFIG_FREERTOS_SMP
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionDisable(NULL);
}
#else
vTaskSuspendAll(); vTaskSuspendAll();
#endif // CONFIG_FREERTOS_SMP
} }
void spi_flash_op_unlock(void) void spi_flash_op_unlock(void)
{ {
#ifdef CONFIG_FREERTOS_SMP
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
vTaskPreemptionEnable(NULL);
}
#else
xTaskResumeAll(); xTaskResumeAll();
#endif // CONFIG_FREERTOS_SMP
} }