创建多任务
我们还是以上节课的多任务点灯为例,讲解使用FreeRTOS如何创建多个可以并行执行的任务
static inline IRAM_ATTR BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask) 我们可以使用xTaskCreate函数创建一个新的任务,该函数有如下参数:
pvTaskCode:创建的任务需要执行的逻辑,为一个函数,该函数返回值必须为void,只有一个参数,参数类型必须为void*
pcName:任务的名称,一个字符串,自己定义,主要为了方便排查问题;
usStackDepth:给任务分配的最大堆栈大小,比如2048,单位是字节,这个值需要根据任务复杂度来选择,一般简单的任务,2048~4096范围的值就足够,如果该任务需要处理的逻辑确实比较繁重,可以适当增大,比如8192
pvParameters:传递给任务的参数,类型是void*;
uxPriority:任务优先级,一个数字,取值范围为[0, 24],数字越大,优先级越高
pxCreatedTask:用于接收该任务的句柄,后续对该任务的操作,需要基于该句柄完成
我们基于上述函数,创建多任务点灯程序
#include <Arduino.h>
#define LED1 23 // 控制第一颗LED灯的引脚
#define LED2 22 // 控制第二颗LED灯的引脚
TaskHandle_t task1;
TaskHandle_t task2;
void handle_led1(void *ptr)
{
pinMode(LED1, OUTPUT);
char *param = (char *)ptr;
Serial.print(param);
Serial.println(" started");
while (1)
{
digitalWrite(LED1, HIGH);
vTaskDelay(1000);
digitalWrite(LED1, LOW);
vTaskDelay(1000);
}
vTaskDelete(NULL);
}
void handle_led2(void *ptr)
{
pinMode(LED2, OUTPUT);
char *param = (char *)ptr;
Serial.print(param);
Serial.println(" started");
while (1)
{
digitalWrite(LED2, HIGH);
vTaskDelay(3000);
digitalWrite(LED2, LOW);
vTaskDelay(3000);
}
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(115200);
xTaskCreate(handle_led1, "task1", 2048, (void *)"led1", 1, &task1);
xTaskCreate(handle_led2, "task2", 2048, (void *)"led2", 1, &task2);
//vTaskDelete(task1);
//vTaskDelete(task2);
}
void loop()
{
}任务绑定CPU
如果我们需要将创建的任务分配到指定的CPU上运行,则可以使用如下函数实现:
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
const char * const pcName,
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pvCreatedTask,
const BaseType_t xCoreID);该函数的作用和上节课介绍的xTaskCreate基本一致,只是它多了一个绑定到CPU的功能,函数前面几个参数功能一样,最后一个参数:
xCoreID:需要将任务分配到的CPU编号,esp32可选编号为0和1,也可以指定常量tskNO_AFFINITY,表示随机分配,查看源码可知xTaskCreate内部调用的也是这个函数,只不过传入的CPU编号为tskNO_AFFINITY
接下来我们改造上面的代码,使用xTaskCreatePinnedToCore函数创建任务,并将它绑定到1号CPU:
#include <Arduino.h>
void echo(void *ptr)
{
while (1)
{
Serial.println(xPortGetCoreID());
}
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(115200);
xTaskCreatePinnedToCore(echo, "echo", 2048, nullptr, 1, NULL, 1);
}
void loop()
{
}