| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- * SPDX-FileCopyrightText: 2022 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_stop(gptimers[i]));
- TEST_ESP_OK(gptimer_disable(gptimers[i]));
- TEST_ESP_OK(gptimer_del_timer(gptimers[i]));
- }
- }
|