Merge branch 'feature/FreeRTOS_Trace_Facilities' into 'master'

feature/make freertos trace facility configurable

See merge request !1420
This commit is contained in:
Angus Gratton 2017-10-20 16:42:15 +08:00
commit 22756b6c02
7 changed files with 246 additions and 72 deletions

View file

@ -275,6 +275,23 @@ config TIMER_QUEUE_LENGTH
For most uses the default value of 10 is OK.
config FREERTOS_USE_TRACE_FACILITY
bool "Enable FreeRTOS trace facility"
default n
help
If enabled, configUSE_TRACE_FACILITY will be defined as 1 in FreeRTOS.
This will allow the usage of trace facility functions such as
uxTaskGetSystemState().
config FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
bool "Enable FreeRTOS stats formatting functions"
depends on FREERTOS_USE_TRACE_FACILITY
default n
help
If enabled, configUSE_STATS_FORMATTING_FUNCTIONS will be defined as 1 in
FreeRTOS. This will allow the usage of stats formatting functions such
as vTaskList().
menuconfig FREERTOS_DEBUG_INTERNALS
bool "Debug FreeRTOS internals"
default n

View file

@ -190,8 +190,19 @@
#define configTOTAL_HEAP_SIZE (&_heap_end - &_heap_start)//( ( size_t ) (64 * 1024) )
#define configMAX_TASK_NAME_LEN ( CONFIG_FREERTOS_MAX_TASK_NAME_LEN )
#define configUSE_TRACE_FACILITY 0 /* Used by vTaskList in main.c */
#define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* Used by vTaskList in main.c */
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
#define configUSE_TRACE_FACILITY 1 /* Used by uxTaskGetSystemState(), and other trace facility functions */
#endif
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
#define configUSE_STATS_FORMATTING_FUNCTIONS 1 /* Used by vTaskList() */
#endif
#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
#define configGENERATE_RUN_TIME_STATS 1 /* Used by vTaskGetRunTimeStats() */
#endif
#define configUSE_TRACE_FACILITY_2 0 /* Provided by Xtensa port patch */
#define configBENCHMARK 0 /* Provided by Xtensa port patch */
#define configUSE_16_BIT_TICKS 0

View file

@ -2292,7 +2292,6 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
{
UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
UNTESTED_FUNCTION();
taskENTER_CRITICAL(&xTaskQueueMutex);
{
/* Is there a space in the array for each task in the system? */
@ -3678,7 +3677,6 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
volatile TCB_t *pxNextTCB, *pxFirstTCB;
UBaseType_t uxTask = 0;
UNTESTED_FUNCTION();
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
{
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
@ -4268,7 +4266,6 @@ For ESP32 FreeRTOS, vTaskExitCritical implements both portEXIT_CRITICAL and port
TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x;
char cStatus;
UNTESTED_FUNCTION();
/*
* PLEASE NOTE:

View file

@ -5,6 +5,7 @@
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "driver/timer.h"
#include "unity.h"
#define BIT_CALL (1 << 0)
@ -117,3 +118,85 @@ TEST_CASE("FreeRTOS Event Group Sync", "[freertos]")
vEventGroupDelete(eg);
}
/*-----------------Test case for event group trace facilities-----------------*/
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
/*
* Test event group Trace Facility functions such as
* xEventGroupClearBitsFromISR(), xEventGroupSetBitsFromISR()
*/
//Use a timer to trigger an ISr
#define TIMER_DIVIDER 10000
#define TIMER_COUNT 1000
#define TIMER_NUMBER 0
#define SET_BITS 0xAA
#define CLEAR_BITS 0x55
static bool event_grp_cleared = false;
static void IRAM_ATTR event_group_isr()
{
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[xPortGetCoreID()].config.alarm_en = 1;
if(!event_grp_cleared){
xEventGroupClearBitsFromISR(eg, CLEAR_BITS);
event_grp_cleared = true;
}else{
xEventGroupSetBitsFromISR(eg, SET_BITS, NULL);
timer_pause(TIMER_GROUP_0, TIMER_NUMBER);
}
}
static void test_event_group_trace_facility(void* arg)
{
//Setup timer for ISR
int timer_group = TIMER_GROUP_0;
int timer_idx = TIMER_NUMBER;
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;
timer_init(timer_group, timer_idx, &config); //Configure timer
timer_pause(timer_group, timer_idx); //Stop timer counter
timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); //Load counter value
timer_set_alarm_value(timer_group, timer_idx, TIMER_COUNT); //Set alarm value
timer_enable_intr(timer_group, timer_idx); //Enable timer interrupt
timer_set_auto_reload(timer_group, timer_idx, 1); //Auto Reload
timer_isr_register(timer_group, timer_idx, event_group_isr, NULL, ESP_INTR_FLAG_IRAM, NULL); //Set ISR handler
//Start timer to trigger isr
timer_start(TIMER_GROUP_0, TIMER_NUMBER);
TEST_ASSERT(xEventGroupWaitBits(eg, SET_BITS, pdFALSE, pdTRUE, portMAX_DELAY));
//Check clear was successful
TEST_ASSERT((xEventGroupGetBits(eg) & CLEAR_BITS) == 0);
//Give semaphore to signal done
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("FreeRTOS Event Group ISR", "[freertos]")
{
done_sem = xSemaphoreCreateBinary();
eg = xEventGroupCreate();
xEventGroupSetBits(eg, CLEAR_BITS); //Set bits to be cleared by ISR
xTaskCreatePinnedToCore(test_event_group_trace_facility, "Testing Task", 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0);
//Wait until task and isr have finished testing
xSemaphoreTake(done_sem, portMAX_DELAY);
//Clean up
vSemaphoreDelete(done_sem);
vEventGroupDelete(eg);
vTaskDelay(10); //Give time for idle task to clear up delted tasks
}
#endif //CONFIG_FREERTOS_USE_TRACE_FACILITY

View file

@ -0,0 +1,132 @@
/*
* Test FreeRTOS trace facility functions. These following functions are enabled
* when configUSE_TRACE_FACILITY is defined 1 in FreeRTOS.
* Tasks: uxTaskGetTaskNumber(), uxTaskSetTaskNumber()
* Queues: ucQueueGetQueueType(), vQueueSetQueueNumber(), uxQueueGetQueueNumber()
* Event Groups: xEventGroupSetBitsFromISR(), xEventGroupClearBitsFromISR(), uxEventGroupGetNumber()
*
* Note: uxTaskGetSystemState() is tested in a separate unit test
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "unity.h"
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
#define TSK_PRIORITY (UNITY_FREERTOS_PRIORITY + 1)
#define NO_OF_CORES portNUM_PROCESSORS
#define BIN_SEM_QUEUE_TYPE queueQUEUE_TYPE_BINARY_SEMAPHORE //Expected Queue Type
static QueueHandle_t test_queues[NO_OF_CORES];
static TaskHandle_t task_handles[NO_OF_CORES];
void task_test_trace_utilities(void *arg)
{
int core = xPortGetCoreID();
TaskHandle_t handle = xTaskGetCurrentTaskHandle();
uint32_t id = (uint32_t)arg;
vTaskSetTaskNumber(handle, (UBaseType_t)id); //cast and store id as task number
vQueueSetQueueNumber(test_queues[core], id); //store id as queue number
//Wait to start
xSemaphoreTake(test_queues[core], portMAX_DELAY);
//Tests on this core
TEST_ASSERT(uxTaskGetTaskNumber(task_handles[core]) == (0x0F << (core)));
TEST_ASSERT(uxQueueGetQueueNumber(test_queues[core]) == (0x0F << (core)));
TEST_ASSERT(ucQueueGetQueueType(test_queues[core]) == BIN_SEM_QUEUE_TYPE)
//Test on other core
#ifndef CONFIG_FREERTOS_UNICORE
TEST_ASSERT(uxTaskGetTaskNumber(task_handles[!core]) == (0x0F << (!core)));
TEST_ASSERT(uxQueueGetQueueNumber(test_queues[!core]) == (0x0F << (!core)));
TEST_ASSERT(ucQueueGetQueueType(test_queues[!core]) == BIN_SEM_QUEUE_TYPE)
#endif
xSemaphoreGive(test_queues[core]); //Signal done
vTaskDelete(NULL);
}
TEST_CASE("Test freertos trace facility functions", "[freertos]")
{
for(int i = 0; i < NO_OF_CORES; i++){
test_queues[i] = xSemaphoreCreateBinary(); //Create a queue as binary semaphore for each core
xTaskCreatePinnedToCore(task_test_trace_utilities, "Test Task", 4096, (void *)(0x0F << i), TSK_PRIORITY, &task_handles[i], i);
}
vTaskDelay(10);
//Start the tasks
for(int i = NO_OF_CORES - 1; i >= 0; i--){
xSemaphoreGive(test_queues[i]);
}
vTaskDelay(10); //Small delay to ensure semaphores are taken
//Wait for done
for(int i = 0; i < NO_OF_CORES; i++){
xSemaphoreTake(test_queues[i], portMAX_DELAY);
vSemaphoreDelete(test_queues[i]);
}
vTaskDelay(10); //Give time for idle task to clean up
}
#define MAX_TASKS 15
#define TASKS_TO_CREATE 5
static TaskHandle_t created_handles[TASKS_TO_CREATE];
static TaskStatus_t *tsk_status_array;
void created_task(void* arg)
{
while(1){
vTaskDelay(100);
}
}
TEST_CASE("Test freertos uxTaskGetSystemState", "[freertos]")
{
tsk_status_array = calloc(MAX_TASKS, sizeof(TaskStatus_t));
for(int i = 0; i < TASKS_TO_CREATE; i++){
xTaskCreatePinnedToCore(created_task, "Created Task", 1024, NULL, TSK_PRIORITY, &created_handles[i], 0);
}
//Get System states
int no_of_tasks = uxTaskGetSystemState(tsk_status_array, MAX_TASKS, NULL);
TEST_ASSERT((no_of_tasks > 0) && (no_of_tasks <= MAX_TASKS));
//Check if get system state has got all created tasks
bool not_found = false;
for(int i = 0; i < TASKS_TO_CREATE; i++){
bool found = false;
for(int j = 0; j < MAX_TASKS; j++){
if(tsk_status_array[j].xHandle == created_handles[i]){
found = true;
break;
}
}
if(!found){
not_found = true;
break;
}
}
TEST_ASSERT(not_found == false);
//Cleanup
for(int i = 0; i < TASKS_TO_CREATE; i++){
vTaskDelete(created_handles[i]);
}
free(tsk_status_array);
vTaskDelay(10);
}
#endif //CONFIG_FREERTOS_USE_TRACE_FACILITY

View file

@ -1,67 +0,0 @@
/*
Test Bugfix for uxTaskGetSystemState where getting system state immediately after creating
new tasks would lead them being include twice in the TaskStatusArray. Changed suspendScheduler
in function to taskENTER_CRITICAL
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#define CreatedTaskDelayTicks 1
#define NumberOfTasksToCreate 4
#define CreatedTaskPriority 10
#define CoreToUse 1
#if (configUSE_TRACE_FACILITY)
void TaskCallback (void* pxParam){
int counter = 0;
while(1){
counter++;
vTaskDelay(CreatedTaskDelayTicks);
}
}
TEST_CASE("uxTaskGetSystemState Bugfix Test", "[freertos]")
{
TaskStatus_t *TaskStatusArray;
TaskHandle_t *TaskHandles;
UBaseType_t NumberOfTasks = 0;
UBaseType_t StartingNumberOfTasks = 0;
//Give Time for OS to remove dport tasks
vTaskDelay(1000);
//Allocate TaskStatusArray
StartingNumberOfTasks = uxTaskGetNumberOfTasks();
TaskStatusArray = pvPortMalloc((StartingNumberOfTasks+NumberOfTasksToCreate) * sizeof(TaskStatus_t));
TaskHandles = pvPortMalloc((StartingNumberOfTasks+NumberOfTasksToCreate) * sizeof(TaskHandle_t));
//Create Tasks
for(int i = 0; i < NumberOfTasksToCreate; i++){
xTaskCreatePinnedToCore(&TaskCallback, "Task" , 2048, NULL, CreatedTaskPriority, (TaskHandle_t*) &TaskHandles[i], CoreToUse);
}
NumberOfTasks = uxTaskGetSystemState(TaskStatusArray, (StartingNumberOfTasks+NumberOfTasksToCreate), NULL);
//Check if any taska have been repeated in TaskStatusArray
if(NumberOfTasks != 0){
printf("Tasks Created, Checking for Repeated Additions \n");
for(int i = 0; i <NumberOfTasks; i++){
for(int j = i + 1; j< NumberOfTasks; j++){
//Give error task handle matches another
configASSERT(!(TaskStatusArray[i].xHandle == TaskStatusArray[j].xHandle));
}
}
}
}
#endif

View file

@ -11,6 +11,7 @@ CONFIG_ESP32_XTAL_FREQ_AUTO=y
CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=3
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_MBEDTLS_HARDWARE_MPI=y
CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y