kopia lustrzana https://github.com/espressif/esp-idf
freertos: Test untested functions
Test cases were added for the following functions - xTaskNotify(), xTaskNotifyGive(), xTaskNotifyFromISR(), vTaskNotifyGiveFromISR(), - xTaskNotifyWait(), ulTaskNotifyTake() - vTaskDelayUntil() The following function was made smp compatible and tested as well - eTaskGetState()pull/1239/head
rodzic
0ee9d93e58
commit
637ba2e8bb
|
@ -1294,7 +1294,6 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
|||
TickType_t xTimeToWake;
|
||||
BaseType_t xAlreadyYielded=pdFALSE, xShouldDelay = pdFALSE;
|
||||
|
||||
UNTESTED_FUNCTION();
|
||||
configASSERT( pxPreviousWakeTime );
|
||||
configASSERT( ( xTimeIncrement > 0U ) );
|
||||
configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] == 0 );
|
||||
|
@ -1457,18 +1456,17 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_eTaskGetState == 1 )
|
||||
/* ToDo: Make this multicore-compatible. */
|
||||
eTaskState eTaskGetState( TaskHandle_t xTask )
|
||||
{
|
||||
eTaskState eReturn;
|
||||
List_t *pxStateList;
|
||||
const TCB_t * const pxTCB = ( TCB_t * ) xTask;
|
||||
TCB_t * curTCB = xTaskGetCurrentTaskHandle();
|
||||
TCB_t * curTCBcurCore = xTaskGetCurrentTaskHandle();
|
||||
TCB_t * curTCBothrCore = xTaskGetCurrentTaskHandleForCPU(!xPortGetCoreID()); //Returns NULL if Unicore
|
||||
|
||||
UNTESTED_FUNCTION();
|
||||
configASSERT( pxTCB );
|
||||
|
||||
if( pxTCB == curTCB )
|
||||
if( pxTCB == curTCBcurCore || pxTCB == curTCBothrCore )
|
||||
{
|
||||
/* The task calling this function is querying its own state. */
|
||||
eReturn = eRunning;
|
||||
|
@ -4526,7 +4524,6 @@ TickType_t uxReturn;
|
|||
TickType_t xTimeToWake;
|
||||
uint32_t ulReturn;
|
||||
|
||||
UNTESTED_FUNCTION();
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
{
|
||||
/* Only block if the notification count is not already non-zero. */
|
||||
|
@ -4849,7 +4846,6 @@ TickType_t uxReturn;
|
|||
eNotifyValue eOriginalNotifyState;
|
||||
BaseType_t xReturn = pdPASS;
|
||||
|
||||
UNTESTED_FUNCTION();
|
||||
configASSERT( xTaskToNotify );
|
||||
|
||||
pxTCB = ( TCB_t * ) xTaskToNotify;
|
||||
|
@ -4947,7 +4943,6 @@ TickType_t uxReturn;
|
|||
TCB_t * pxTCB;
|
||||
eNotifyValue eOriginalNotifyState;
|
||||
|
||||
UNTESTED_FUNCTION();
|
||||
configASSERT( xTaskToNotify );
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
|
||||
#define TSK_PRIORITY (UNITY_FREERTOS_PRIORITY + 1)
|
||||
|
||||
static TaskHandle_t blocked_task_handle;
|
||||
static TaskHandle_t suspended_task_handle;
|
||||
static SemaphoreHandle_t done_sem;
|
||||
|
||||
void test_task_get_state(void* arg)
|
||||
{
|
||||
//Current task should return eRunning
|
||||
TEST_ASSERT(eTaskGetState(xTaskGetCurrentTaskHandle()) == eRunning);
|
||||
//Idle task of current core should return eReady
|
||||
TEST_ASSERT(eTaskGetState(xTaskGetIdleTaskHandle()) == eReady);
|
||||
//Blocked Task should return eBlocked
|
||||
TEST_ASSERT(eTaskGetState(blocked_task_handle) == eBlocked);
|
||||
//Suspended Task should return eSuspended
|
||||
TEST_ASSERT(eTaskGetState(suspended_task_handle) == eSuspended);
|
||||
|
||||
xSemaphoreGive(done_sem);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void blocked_task(void *arg)
|
||||
{
|
||||
while(1){
|
||||
vTaskDelay(portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void suspended_task(void *arg)
|
||||
{
|
||||
while(1){
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test eTaskGetState", "[freertos]")
|
||||
{
|
||||
done_sem = xQueueCreateCountingSemaphore(portNUM_PROCESSORS, 0);
|
||||
//Create blocked and suspended task
|
||||
xTaskCreatePinnedToCore(blocked_task, "Blocked task", 1024, NULL, TSK_PRIORITY, &blocked_task_handle, tskNO_AFFINITY);
|
||||
xTaskCreatePinnedToCore(suspended_task, "Suspended task", 1024, NULL, TSK_PRIORITY, &suspended_task_handle, tskNO_AFFINITY);
|
||||
//Create testing task
|
||||
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
||||
xTaskCreatePinnedToCore(test_task_get_state, "Test task", 1024, NULL, TSK_PRIORITY, NULL, i);
|
||||
}
|
||||
|
||||
//Wait until done
|
||||
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
||||
xSemaphoreTake(done_sem, portMAX_DELAY);
|
||||
}
|
||||
//Clean up blocked and suspended tasks
|
||||
vTaskDelete(blocked_task_handle);
|
||||
blocked_task_handle = NULL;
|
||||
vTaskDelete(suspended_task_handle);
|
||||
suspended_task_handle = NULL;
|
||||
vSemaphoreDelete(done_sem);
|
||||
|
||||
vTaskDelay(10); //Give time for idle to actually delete the tasks
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Test for FreeRTOS vTaskDelayUntil() function by comparing the delay period of
|
||||
the function to comparing it to ref clock.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/FreeRTOSConfig.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#define TSK_PRIORITY (UNITY_FREERTOS_PRIORITY + 1)
|
||||
|
||||
#define NO_OF_CYCLES 5
|
||||
#define NO_OF_TASKS_PER_CORE 2
|
||||
#define TICKS_TO_DELAY 10
|
||||
#define TICK_RATE configTICK_RATE_HZ
|
||||
#define TICK_PERIOD_US (1000000/TICK_RATE)
|
||||
#define IDEAL_DELAY_PERIOD_MS ((1000*TICKS_TO_DELAY)/TICK_RATE)
|
||||
#define IDEAL_DELAY_PERIOD_US (IDEAL_DELAY_PERIOD_MS*1000)
|
||||
|
||||
#define TICKS_TO_MS(x) (((x)*1000)/TICK_RATE)
|
||||
#define REF_TO_ROUND_MS(x) (((x)+500)/1000)
|
||||
|
||||
static SemaphoreHandle_t task_delete_semphr;
|
||||
|
||||
static void delaying_task(void* arg)
|
||||
{
|
||||
uint64_t ref_prev, ref_current;
|
||||
TickType_t last_wake_time;
|
||||
TickType_t ticks_before_delay;
|
||||
|
||||
vTaskDelay(1); //Delay until next tick to synchronize operations to tick boundaries
|
||||
|
||||
last_wake_time = xTaskGetTickCount();
|
||||
ticks_before_delay = last_wake_time;
|
||||
ref_prev = ref_clock_get();
|
||||
|
||||
for(int i = 0; i < NO_OF_CYCLES; i++){
|
||||
//Delay of TICKS_TO_DELAY
|
||||
vTaskDelayUntil(&last_wake_time, TICKS_TO_DELAY);
|
||||
//Get current ref clock
|
||||
TEST_ASSERT_EQUAL(IDEAL_DELAY_PERIOD_MS, TICKS_TO_MS(xTaskGetTickCount() - ticks_before_delay));
|
||||
ref_current = ref_clock_get();
|
||||
TEST_ASSERT_UINT32_WITHIN(TICK_PERIOD_US, IDEAL_DELAY_PERIOD_US, (uint32_t)(ref_current - ref_prev));
|
||||
ref_prev = ref_current;
|
||||
ticks_before_delay = last_wake_time;
|
||||
}
|
||||
|
||||
//Delete Task after prescribed number of cycles
|
||||
xSemaphoreGive(task_delete_semphr);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Test vTaskDelayUntil", "[freertos]")
|
||||
{
|
||||
task_delete_semphr = xQueueCreateCountingSemaphore(NO_OF_TASKS_PER_CORE*portNUM_PROCESSORS, 0);
|
||||
ref_clock_init();
|
||||
|
||||
for(int i = 0; i < portNUM_PROCESSORS; i++){
|
||||
xTaskCreatePinnedToCore(delaying_task, "delay_pinned", 1024, NULL, TSK_PRIORITY, NULL, i);
|
||||
xTaskCreatePinnedToCore(delaying_task, "delay_no_aff", 1024, NULL, TSK_PRIORITY, NULL, tskNO_AFFINITY);
|
||||
}
|
||||
|
||||
for(int i = 0; i < NO_OF_TASKS_PER_CORE*portNUM_PROCESSORS; i++){
|
||||
xSemaphoreTake(task_delete_semphr, portMAX_DELAY);
|
||||
}
|
||||
//Cleanup
|
||||
vSemaphoreDelete(task_delete_semphr);
|
||||
ref_clock_deinit();
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
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
|
||||
}
|
||||
|
||||
|
Ładowanie…
Reference in New Issue