kopia lustrzana https://github.com/espressif/esp-idf
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
rodzic
883da858b0
commit
27f5c90e2e
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
;
|
;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue