mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
c24222dcde
Added state transition in gptimer_start/stop functions. So that it's not possible to make a stopped timer continue to run because of race condition.
198 lines
6.5 KiB
C
198 lines
6.5 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/*
|
|
Test of FreeRTOS task notifications. This test creates a sender and receiver
|
|
task under different core permutations. For each permutation, the sender task
|
|
will test the xTaskNotify(), xTaskNotifyGive(), xTaskNotifyFromISR(), and
|
|
vTaskNotifyGiveFromISR(), whereas the receiver task will test
|
|
xTaskNotifyWait() and ulTaskNotifyTake().
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/semphr.h"
|
|
#include "driver/gptimer.h"
|
|
#include "unity.h"
|
|
#include "test_utils.h"
|
|
|
|
#define NO_OF_NOTIFS 4
|
|
#define NO_OF_TASKS 2 //Sender and receiver
|
|
#define MESSAGE 0xFF
|
|
|
|
static uint32_t send_core_message = 0;
|
|
static TaskHandle_t recv_task_handle;
|
|
static bool isr_give = false;
|
|
static bool test_start = false;
|
|
static gptimer_handle_t gptimers[portNUM_PROCESSORS];
|
|
static SemaphoreHandle_t trigger_send_semphr;
|
|
static SemaphoreHandle_t task_delete_semphr;
|
|
|
|
//Test tracking vars
|
|
static volatile uint32_t notifs_sent = 0;
|
|
static volatile uint32_t notifs_rec = 0;
|
|
static bool wrong_core = false;
|
|
|
|
static bool on_alarm_sender_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
|
|
{
|
|
gptimer_stop(timer);
|
|
if (!test_start) {
|
|
return false;
|
|
}
|
|
int curcore = xPortGetCoreID();
|
|
if (isr_give) { //Test vTaskNotifyGiveFromISR() on same core
|
|
notifs_sent++;
|
|
vTaskNotifyGiveFromISR(recv_task_handle, NULL);
|
|
} else { //Test xTaskNotifyFromISR()
|
|
notifs_sent++;
|
|
xTaskNotifyFromISR(recv_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite, NULL);
|
|
}
|
|
// always trigger a task switch when exit ISR context
|
|
return true;
|
|
}
|
|
|
|
static void test_gptimer_start(void *arg)
|
|
{
|
|
gptimer_handle_t gptimer = (gptimer_handle_t)arg;
|
|
gptimer_alarm_config_t alarm_config = {
|
|
.reload_count = 0,
|
|
.alarm_count = 1000,
|
|
};
|
|
TEST_ESP_OK(gptimer_set_raw_count(gptimer, 0));
|
|
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
|
|
TEST_ESP_OK(gptimer_start(gptimer));
|
|
}
|
|
|
|
static void sender_task(void *arg)
|
|
{
|
|
gptimer_handle_t gptimer = (gptimer_handle_t)arg;
|
|
int curcore = xPortGetCoreID();
|
|
|
|
//Test xTaskNotify
|
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
|
notifs_sent++;
|
|
xTaskNotify(recv_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite);
|
|
|
|
//Test xTaskNotifyGive
|
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
|
notifs_sent++;
|
|
xTaskNotifyGive(recv_task_handle);
|
|
|
|
//Test xTaskNotifyFromISR
|
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
|
isr_give = false;
|
|
test_gptimer_start(gptimer);
|
|
|
|
//Test vTaskNotifyGiveFromISR
|
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
|
isr_give = true;
|
|
test_gptimer_start(gptimer);
|
|
|
|
//Delete Task and Semaphores
|
|
xSemaphoreGive(task_delete_semphr);
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
static void receiver_task(void *arg)
|
|
{
|
|
uint32_t notify_value;
|
|
|
|
//Test xTaskNotifyWait from task
|
|
xTaskNotifyWait(0, 0xFFFFFFFF, ¬ify_value, portMAX_DELAY);
|
|
if (notify_value != send_core_message) {
|
|
wrong_core = true;
|
|
}
|
|
notifs_rec++;
|
|
|
|
//Test ulTaskNotifyTake from task
|
|
xSemaphoreGive(trigger_send_semphr);
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
notifs_rec++;
|
|
|
|
//Test xTaskNotifyWait from ISR
|
|
xSemaphoreGive(trigger_send_semphr);
|
|
xTaskNotifyWait(0, 0xFFFFFFFF, ¬ify_value, portMAX_DELAY);
|
|
if (notify_value != send_core_message) {
|
|
wrong_core = true;
|
|
}
|
|
notifs_rec++;
|
|
|
|
//Test ulTaskNotifyTake from ISR
|
|
xSemaphoreGive(trigger_send_semphr);
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
notifs_rec++;
|
|
|
|
//Test complete, stop timer and delete task
|
|
xSemaphoreGive(task_delete_semphr);
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
static void install_gptimer_on_core(void *arg)
|
|
{
|
|
int core_id = (int)arg;
|
|
gptimer_config_t timer_config = {
|
|
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
|
.direction = GPTIMER_COUNT_UP,
|
|
.resolution_hz = 1000000, // 1MHz, 1 tick = 1us
|
|
};
|
|
TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimers[core_id]));
|
|
gptimer_event_callbacks_t cbs = {
|
|
.on_alarm = on_alarm_sender_cb,
|
|
};
|
|
TEST_ESP_OK(gptimer_register_event_callbacks(gptimers[core_id], &cbs, NULL));
|
|
TEST_ESP_OK(gptimer_enable(gptimers[core_id]));
|
|
test_gptimer_start(gptimers[core_id]);
|
|
xSemaphoreGive(task_delete_semphr);
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
TEST_CASE("Test Task_Notify", "[freertos]")
|
|
{
|
|
test_start = false;
|
|
trigger_send_semphr = xSemaphoreCreateBinary();
|
|
task_delete_semphr = xQueueCreateCountingSemaphore(10, 0);
|
|
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
|
xTaskCreatePinnedToCore(install_gptimer_on_core, "install_gptimer", 4096, (void *const)i, UNITY_FREERTOS_PRIORITY + 1, NULL, i);
|
|
TEST_ASSERT(xSemaphoreTake(task_delete_semphr, pdMS_TO_TICKS(1000)));
|
|
}
|
|
// wait the gptimer installation done on specific core
|
|
vTaskDelay(10);
|
|
// test start
|
|
test_start = true;
|
|
for (int i = 0; i < portNUM_PROCESSORS; i++) { //Sending Core
|
|
for (int j = 0; j < portNUM_PROCESSORS; j++) { //Receiving Core
|
|
//Reset Values
|
|
notifs_sent = 0;
|
|
notifs_rec = 0;
|
|
wrong_core = false;
|
|
send_core_message = (0xFF << i); //0xFF if core 0, 0xFF0 if core 1
|
|
// receiver task has higher priority than sender task
|
|
xTaskCreatePinnedToCore(receiver_task, "recv task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 2, &recv_task_handle, j);
|
|
xTaskCreatePinnedToCore(sender_task, "send task", 1000, gptimers[i], UNITY_FREERTOS_PRIORITY + 1, NULL, i);
|
|
vTaskDelay(5); //Wait for task creation to complete
|
|
|
|
xSemaphoreGive(trigger_send_semphr); //Trigger sender task
|
|
for (int k = 0; k < NO_OF_TASKS; k++) { //Wait for sender and receiver task deletion
|
|
TEST_ASSERT(xSemaphoreTake(task_delete_semphr, pdMS_TO_TICKS(2000)));
|
|
}
|
|
vTaskDelay(5); //Give time tasks to delete
|
|
|
|
TEST_ASSERT_EQUAL(NO_OF_NOTIFS, notifs_sent);
|
|
TEST_ASSERT_EQUAL(NO_OF_NOTIFS, notifs_rec);
|
|
TEST_ASSERT_EQUAL(false, wrong_core);
|
|
}
|
|
}
|
|
|
|
//Delete Semaphroes and timer ISRs
|
|
vSemaphoreDelete(trigger_send_semphr);
|
|
vSemaphoreDelete(task_delete_semphr);
|
|
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
|
TEST_ESP_OK(gptimer_disable(gptimers[i]));
|
|
TEST_ESP_OK(gptimer_del_timer(gptimers[i]));
|
|
}
|
|
}
|