mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
211 lines
6.6 KiB
C
211 lines
6.6 KiB
C
|
/*
|
||
|
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/timer.h"
|
||
|
#include "esp_ipc.h"
|
||
|
#include "unity.h"
|
||
|
|
||
|
#define NO_OF_NOTIFS 4
|
||
|
#define NO_OF_TASKS 2 //Sender and receiver
|
||
|
#define TIMER_DIVIDER 10000
|
||
|
#define TIMER_COUNT 100
|
||
|
#define MESSAGE 0xFF
|
||
|
|
||
|
static uint32_t send_core_message = 0;
|
||
|
static TaskHandle_t rec_task_handle;
|
||
|
static bool isr_give = false;
|
||
|
|
||
|
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 void sender_task (void* arg){
|
||
|
int curcore = xPortGetCoreID();
|
||
|
|
||
|
//Test xTaskNotify
|
||
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
||
|
notifs_sent++;
|
||
|
xTaskNotify(rec_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite);
|
||
|
|
||
|
//Test xTaskNotifyGive
|
||
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
||
|
notifs_sent++;
|
||
|
xTaskNotifyGive(rec_task_handle);
|
||
|
|
||
|
//Test xTaskNotifyFromISR
|
||
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
||
|
isr_give = false;
|
||
|
timer_start(TIMER_GROUP_0, curcore);
|
||
|
|
||
|
//Test vTaskNotifyGiveFromISR
|
||
|
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
|
||
|
isr_give = true;
|
||
|
timer_start(TIMER_GROUP_0, curcore);
|
||
|
|
||
|
//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 IRAM_ATTR sender_ISR ()
|
||
|
{
|
||
|
int curcore = xPortGetCoreID();
|
||
|
if(curcore == 0){ //Clear timer interrupt
|
||
|
//Clear intr and pause via direct reg access as IRAM ISR cannot access timer APIs
|
||
|
TIMERG0.int_clr_timers.t0 = 1;
|
||
|
TIMERG0.hw_timer[0].config.enable = 0;
|
||
|
}else{
|
||
|
TIMERG0.int_clr_timers.t1 = 1;
|
||
|
TIMERG0.hw_timer[1].config.enable = 0;
|
||
|
}
|
||
|
//Re-enable alarm
|
||
|
TIMERG0.hw_timer[curcore].config.alarm_en = 1;
|
||
|
|
||
|
if(isr_give){ //Test vTaskNotifyGiveFromISR() on same core
|
||
|
notifs_sent++;
|
||
|
vTaskNotifyGiveFromISR(rec_task_handle, NULL);
|
||
|
}
|
||
|
else { //Test xTaskNotifyFromISR()
|
||
|
notifs_sent++;
|
||
|
xTaskNotifyFromISR(rec_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite, NULL);
|
||
|
}
|
||
|
portYIELD_FROM_ISR();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void timerg0_init(void *isr_handle)
|
||
|
{
|
||
|
int timer_group = TIMER_GROUP_0;
|
||
|
int timer_idx = xPortGetCoreID();
|
||
|
|
||
|
timer_config_t config;
|
||
|
config.alarm_en = 1;
|
||
|
config.auto_reload = 1;
|
||
|
config.counter_dir = TIMER_COUNT_UP;
|
||
|
config.divider = TIMER_DIVIDER;
|
||
|
config.intr_type = TIMER_INTR_LEVEL;
|
||
|
config.counter_en = TIMER_PAUSE;
|
||
|
|
||
|
/*Configure timer*/
|
||
|
timer_init(timer_group, timer_idx, &config);
|
||
|
/*Stop timer counter*/
|
||
|
timer_pause(timer_group, timer_idx);
|
||
|
/*Load counter value */
|
||
|
timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL);
|
||
|
/*Set alarm value*/
|
||
|
timer_set_alarm_value(timer_group, timer_idx, TIMER_COUNT);
|
||
|
/*Enable timer interrupt*/
|
||
|
timer_enable_intr(timer_group, timer_idx);
|
||
|
//Auto Reload
|
||
|
timer_set_auto_reload(timer_group, timer_idx, 1);
|
||
|
/*Set ISR handler*/
|
||
|
timer_isr_register(timer_group, timer_idx, sender_ISR, NULL, ESP_INTR_FLAG_IRAM, (intr_handle_t *)isr_handle);
|
||
|
}
|
||
|
|
||
|
static void timerg0_deinit(void* isr_handle)
|
||
|
{
|
||
|
int timer_group = TIMER_GROUP_0;
|
||
|
int timer_idx = xPortGetCoreID();
|
||
|
intr_handle_t handle = *((intr_handle_t *) isr_handle);
|
||
|
//Pause timer then free registered ISR
|
||
|
timer_pause(timer_group, timer_idx);
|
||
|
esp_intr_free(handle);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Test Task_Notify", "[freertos]")
|
||
|
{
|
||
|
//Initialize and pause timers. Used to trigger ISR
|
||
|
intr_handle_t isr_handle_0 = NULL;
|
||
|
timerg0_init(&isr_handle_0); //Core 0 timer
|
||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||
|
intr_handle_t isr_handle_1 = NULL;
|
||
|
esp_ipc_call(1, timerg0_init, &isr_handle_1); //Core 1 timer
|
||
|
#endif
|
||
|
|
||
|
trigger_send_semphr = xSemaphoreCreateBinary();
|
||
|
task_delete_semphr = xQueueCreateCountingSemaphore(NO_OF_TASKS, 0);
|
||
|
|
||
|
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
|
||
|
|
||
|
xTaskCreatePinnedToCore(receiver_task, "rec task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 2, &rec_task_handle, j);
|
||
|
xTaskCreatePinnedToCore(sender_task, "send task", 1000, NULL, 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
|
||
|
xSemaphoreTake(task_delete_semphr, portMAX_DELAY);
|
||
|
}
|
||
|
vTaskDelay(5); //Give time tasks to delete
|
||
|
|
||
|
TEST_ASSERT(notifs_sent == NO_OF_NOTIFS);
|
||
|
TEST_ASSERT(notifs_rec == NO_OF_NOTIFS);
|
||
|
TEST_ASSERT(wrong_core == false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Delete Semaphroes and timer ISRs
|
||
|
vSemaphoreDelete(trigger_send_semphr);
|
||
|
vSemaphoreDelete(task_delete_semphr);
|
||
|
timerg0_deinit(&isr_handle_0);
|
||
|
isr_handle_0 = NULL;
|
||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||
|
esp_ipc_call(1, timerg0_deinit, &isr_handle_1);
|
||
|
isr_handle_1 = NULL;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|