mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 22:24:33 +02:00
freertos: Update FPU unit tests to run for multiple iterations
This commit updates the FreeRTOS port FPU unit tests so that they run for multiple iterations, thus checking that a task's FPU context is properly cleaned up on deletion.
This commit is contained in:
@@ -23,16 +23,21 @@ Test FPU usage from a task context
|
|||||||
Purpose:
|
Purpose:
|
||||||
- Test that the FPU can be used from a task context
|
- Test that the FPU can be used from a task context
|
||||||
- Test that FPU context is properly saved and restored
|
- Test that FPU context is properly saved and restored
|
||||||
|
- Test that FPU context is cleaned up on task deletion by running multiple iterations
|
||||||
Procedure:
|
Procedure:
|
||||||
- Create TEST_PINNED_NUM_TASKS tasks pinned to each core
|
- Create TEST_PINNED_NUM_TASKS tasks pinned to each core
|
||||||
- Start each task
|
- Start each task
|
||||||
- Each task updates a float variable and then blocks (to allow other tasks to run thus forcing the an FPU context
|
- Each task updates a float variable and then blocks (to allow other tasks to run thus forcing the an FPU context
|
||||||
save and restore).
|
save and restore).
|
||||||
|
- Delete each task
|
||||||
|
- Repeat test for TEST_PINNED_NUM_ITERS iterations
|
||||||
Expected:
|
Expected:
|
||||||
- Correct float value calculated by each task
|
- Correct float value calculated by each task
|
||||||
|
- Each task cleans up its FPU context on deletion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define TEST_PINNED_NUM_TASKS 3
|
#define TEST_PINNED_NUM_TASKS 3
|
||||||
|
#define TEST_PINNED_NUM_ITERS 5
|
||||||
|
|
||||||
static void pinned_task(void *arg)
|
static void pinned_task(void *arg)
|
||||||
{
|
{
|
||||||
@@ -62,35 +67,38 @@ TEST_CASE("FPU: Usage in task", "[freertos]")
|
|||||||
SemaphoreHandle_t done_sem = xSemaphoreCreateCounting(configNUM_CORES * TEST_PINNED_NUM_TASKS, 0);
|
SemaphoreHandle_t done_sem = xSemaphoreCreateCounting(configNUM_CORES * TEST_PINNED_NUM_TASKS, 0);
|
||||||
TEST_ASSERT_NOT_EQUAL(NULL, done_sem);
|
TEST_ASSERT_NOT_EQUAL(NULL, done_sem);
|
||||||
|
|
||||||
TaskHandle_t task_handles[configNUM_CORES][TEST_PINNED_NUM_TASKS];
|
for (int iter = 0; iter < TEST_PINNED_NUM_ITERS; iter++) {
|
||||||
|
TaskHandle_t task_handles[configNUM_CORES][TEST_PINNED_NUM_TASKS];
|
||||||
|
|
||||||
// Create test tasks for each core
|
// Create test tasks for each core
|
||||||
for (int i = 0; i < configNUM_CORES; i++) {
|
for (int i = 0; i < configNUM_CORES; i++) {
|
||||||
for (int j = 0; j < TEST_PINNED_NUM_TASKS; j++) {
|
for (int j = 0; j < TEST_PINNED_NUM_TASKS; j++) {
|
||||||
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(pinned_task, "task", 4096, (void *)done_sem, UNITY_FREERTOS_PRIORITY + 1, &task_handles[i][j], i));
|
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(pinned_task, "task", 4096, (void *)done_sem, UNITY_FREERTOS_PRIORITY + 1, &task_handles[i][j], i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Start the created tasks simultaneously
|
// Start the created tasks simultaneously
|
||||||
for (int i = 0; i < configNUM_CORES; i++) {
|
for (int i = 0; i < configNUM_CORES; i++) {
|
||||||
for (int j = 0; j < TEST_PINNED_NUM_TASKS; j++) {
|
for (int j = 0; j < TEST_PINNED_NUM_TASKS; j++) {
|
||||||
xTaskNotifyGive(task_handles[i][j]);
|
xTaskNotifyGive(task_handles[i][j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the tasks to complete
|
// Wait for the tasks to complete
|
||||||
for (int i = 0; i < configNUM_CORES * TEST_PINNED_NUM_TASKS; i++) {
|
for (int i = 0; i < configNUM_CORES * TEST_PINNED_NUM_TASKS; i++) {
|
||||||
xSemaphoreTake(done_sem, portMAX_DELAY);
|
xSemaphoreTake(done_sem, portMAX_DELAY);
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the tasks
|
|
||||||
for (int i = 0; i < configNUM_CORES; i++) {
|
|
||||||
for (int j = 0; j < TEST_PINNED_NUM_TASKS; j++) {
|
|
||||||
vTaskDelete(task_handles[i][j]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete the tasks
|
||||||
|
for (int i = 0; i < configNUM_CORES; i++) {
|
||||||
|
for (int j = 0; j < TEST_PINNED_NUM_TASKS; j++) {
|
||||||
|
vTaskDelete(task_handles[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(10); // Short delay to allow idle task to be free task memory and FPU contexts
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelay(10); // Short delay to allow idle task to be free task memory and FPU contexts
|
|
||||||
vSemaphoreDelete(done_sem);
|
vSemaphoreDelete(done_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,18 +109,24 @@ Test FPU usage will pin an unpinned task
|
|||||||
|
|
||||||
Purpose:
|
Purpose:
|
||||||
- Test that unpinned tasks are automatically pinned to the current core on the task's first use of the FPU
|
- Test that unpinned tasks are automatically pinned to the current core on the task's first use of the FPU
|
||||||
|
- Test that FPU context is cleaned up on task deletion by running multiple iterations
|
||||||
Procedure:
|
Procedure:
|
||||||
- Create an unpinned task
|
- Create an unpinned task
|
||||||
- Task disables scheduling/preemption to ensure that it does not switch cores
|
- Task disables scheduling/preemption to ensure that it does not switch cores
|
||||||
- Task uses the FPU
|
- Task uses the FPU
|
||||||
- Task checks its core affinity after FPU usage
|
- Task checks its core affinity after FPU usage
|
||||||
|
- Task deletes itself
|
||||||
|
- Repeat test for TEST_UNPINNED_NUM_ITERS iterations
|
||||||
Expected:
|
Expected:
|
||||||
- Task remains unpinned until its first usage of the FPU
|
- Task remains unpinned until its first usage of the FPU
|
||||||
- The task becomes pinned to the current core after first use of the FPU
|
- The task becomes pinned to the current core after first use of the FPU
|
||||||
|
- Each task cleans up its FPU context on deletion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if configNUM_CORES > 1
|
#if configNUM_CORES > 1
|
||||||
|
|
||||||
|
#define TEST_UNPINNED_NUM_ITERS 5
|
||||||
|
|
||||||
static void unpinned_task(void *arg)
|
static void unpinned_task(void *arg)
|
||||||
{
|
{
|
||||||
// Disable scheduling/preemption to make sure current core ID doesn't change
|
// Disable scheduling/preemption to make sure current core ID doesn't change
|
||||||
@@ -162,11 +176,13 @@ static void unpinned_task(void *arg)
|
|||||||
TEST_CASE("FPU: Usage in unpinned task", "[freertos]")
|
TEST_CASE("FPU: Usage in unpinned task", "[freertos]")
|
||||||
{
|
{
|
||||||
TaskHandle_t unity_task_handle = xTaskGetCurrentTaskHandle();
|
TaskHandle_t unity_task_handle = xTaskGetCurrentTaskHandle();
|
||||||
// Create unpinned task
|
for (int iter = 0; iter < TEST_UNPINNED_NUM_ITERS; iter++) {
|
||||||
xTaskCreate(unpinned_task, "unpin", 4096, (void *)unity_task_handle, UNITY_FREERTOS_PRIORITY + 1, NULL);
|
// Create unpinned task
|
||||||
// Wait for task to complete
|
xTaskCreate(unpinned_task, "unpin", 4096, (void *)unity_task_handle, UNITY_FREERTOS_PRIORITY + 1, NULL);
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
// Wait for task to complete
|
||||||
vTaskDelay(10); // Short delay to allow task memory to be freed
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
vTaskDelay(10); // Short delay to allow task memory to be freed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // configNUM_CORES > 1
|
#endif // configNUM_CORES > 1
|
||||||
|
Reference in New Issue
Block a user