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:
Darian Leung
2022-12-03 00:13:31 +08:00
parent 45badf864f
commit 82f28a3e09

View File

@@ -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