-
Notifications
You must be signed in to change notification settings - Fork 7.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(riscv): adjust TCBs lowest stack address when the FPU is used
- Loading branch information
1 parent
4f96919
commit c7e6307
Showing
4 changed files
with
129 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
components/freertos/test_apps/freertos/port/test_fpu_watermark.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "sdkconfig.h" | ||
#include <string.h> | ||
#include "soc/soc_caps.h" | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "unity.h" | ||
|
||
#define TASKS_STATUS_ARRAY_LEN 16 | ||
|
||
/** | ||
* On RISC-V targets that have coprocessors, the contexts are saved at the lowest address of the stack, | ||
* which can lead to wrong stack watermark calculation in FreeRTOS in theory. | ||
* As such, the port layer of FreeRTOS will adjust the lowest address of the stack when a coprocessor | ||
* context is saved. | ||
*/ | ||
#if CONFIG_IDF_TARGET_ARCH_RISCV && SOC_CPU_COPROC_NUM > 0 | ||
|
||
volatile float s_float = 0.1999f; | ||
|
||
static float add_floats(float f1, float f2) | ||
{ | ||
return f1 + f2; | ||
} | ||
|
||
static void other_task(void* arg) | ||
{ | ||
const TaskHandle_t main_task = (TaskHandle_t) arg; | ||
|
||
/* The second task shall also use the FPU to force a context flush on the main task */ | ||
add_floats(s_float, s_float); | ||
|
||
xTaskNotifyGive(main_task); | ||
|
||
/* The FPU context should be flushed on the main task, notify it and return */ | ||
vTaskDelete(NULL); | ||
} | ||
|
||
|
||
TEST_CASE("FPU: Context save does not affect stack watermark", "[freertos]") | ||
{ | ||
TaskHandle_t pvCreatedTask; | ||
/* Force the FreeRTOS port layer to store an FPU context in the current task. | ||
* So let's use the FPU and make sure another task, on the SAME CORE, also uses it */ | ||
const int core_id = xPortGetCoreID(); | ||
const TaskHandle_t current_handle = xTaskGetCurrentTaskHandle(); | ||
|
||
/* Get the current stack watermark */ | ||
const UBaseType_t before_watermark = uxTaskGetStackHighWaterMark(current_handle); | ||
|
||
/* Use the FPU unit, the context will NOT be flushed until another task starts using it */ | ||
add_floats(s_float, s_float); | ||
|
||
xTaskCreatePinnedToCore( other_task, | ||
"OtherTask", | ||
2048, | ||
(void*) current_handle, | ||
CONFIG_UNITY_FREERTOS_PRIORITY - 1, | ||
&pvCreatedTask, | ||
core_id); | ||
|
||
vTaskDelay(10); | ||
|
||
/* Wait for other task to complete */ | ||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); | ||
|
||
const UBaseType_t after_watermark = uxTaskGetStackHighWaterMark(current_handle); | ||
|
||
/* The current task has seen a general-purpose registers context save as well as an FPU context save | ||
* so we have at least 32*2 registers saved on the stack, which represents 256 bytes. | ||
* In practice, it may be very different, for example a call to printf would result is more than 1KB | ||
* of additional stack space used. So let's just make sure that the watermark is bigger than 50% of the | ||
* former watermark. */ | ||
TEST_ASSERT_TRUE(after_watermark > before_watermark / 2); | ||
} | ||
|
||
#endif // CONFIG_IDF_TARGET_ARCH_RISCV && SOC_CPU_COPROC_NUM > 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters