Understanding Task Parameters in FreeRTOS

FreeRTOS Learning Part 4 – Task Parameters Usage

This article aims to teach the usage of task parameters in FreeRTOS.

Following the description in this article, you should be able to run the experiment and apply it to other scenarios.

Prerequisites: Basic knowledge of C language and a development environment installed, such as Keil uVision5.

Using peripherals: USART1, GPIO, I2C

Experiment Objective

Create three tasks named PrintTask with the same priority, which will display the execution count of the task on an OLED screen.

Design Experiment

When creating tasks, pass data as a pointer to the task function through the pvParameters parameter of the xTaskCreate or xTaskCreateStatic function. The task function can retrieve the data through its entry parameter pvParameters. This method is suitable for passing static or global variables, or data that needs to be passed only once. In my case, I use dynamic task creation with xTaskCreate, and the relevant code snippet is as follows:

struct TaskPrintInfo { uint8_t x; uint8_t y; char name[16];};
static struct TaskPrintInfo g_Task1Info = {0, 0, "Task1"};static struct TaskPrintInfo g_Task2Info = {0, 16, "Task2"};static struct TaskPrintInfo g_Task3Info = {0, 32, "Task3"};
  /* Create different tasks using the same function */  xTaskCreate(PrintTask, "task1", 128, &g_Task1Info, osPriorityNormal, NULL);  xTaskCreate(PrintTask, "task2", 128, &g_Task2Info, osPriorityNormal, NULL);  xTaskCreate(PrintTask, "task3", 128, &g_Task3Info, osPriorityNormal, NULL);
Understanding Task Parameters in FreeRTOS
Insert image description here

I use a TaskPrintInfo structure to pass a coordinate value and a string. In my PrintTask, the deepest stack is only 96 bytes, and I create the task with a stack size of 128, which is 512 bytes, more than enough to avoid crashes and other issues.

PrintTask Source Code

void PrintTask(void *params){ struct TaskPrintInfo *pInfo = params; uint32_t cnt = 0; OLED_Init(); while (1) { /* Print information */ if (g_LCDCanUse) { g_LCDCanUse = 0; OLED_ShowString(pInfo->x,pInfo->y,pInfo->name,16); OLED_ShowNum((pInfo->x + 8 * 6),pInfo->y,cnt++,4,16); OLED_Refresh(); // Refresh screen g_LCDCanUse = 1; } mdelay(500); // Necessary delay to yield resources to other tasks } }

The source code simply displays some characters and the number of times the task runs. I use this global variable g_LCDCanUse for simple protection because the OLED screen uses I2C when refreshing the screen. When one task finishes using it, another task follows. This is a simple and rough usage, for learning reference only.

Experiment Phenomenon

After downloading the code to the board, it was found that Task3 refreshed first, followed by Task1, and Task2 refreshed last. This is because tasks with the same priority run in the order they were created, which is also reflected in the source code:

Understanding Task Parameters in FreeRTOS
Insert image description here

Final Phenomenon

Understanding Task Parameters in FreeRTOS
Insert image description here

The OLED screen displayed different execution counts, with Task1 executing the most (291 times), followed by Task3 (237 times), and Task2 (233 times). Therefore, this experiment was successful, successfully using task parameters for experimentation.

Leave a Comment

×