Arduino ESP32 FreeRTOS 创建任务, 并启动另一个核心


完整代码

int num = 0; // loop 函数运行次数

TaskHandle_t xHandle1 = NULL; // 第一个任务句柄
TaskHandle_t xHandle2 = NULL; // 第二个任务句柄

void setup() {
// 打开串口输出
Serial.begin(115200);
delay(100);


// 获取当前未分配的内存堆大小:
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());


BaseType_t xReturned1; // 第二个任务返回值
BaseType_t xReturned2; // 第一个任务返回值

// 声明需要传递的参数
char * char1 ="这是第一个任务"; // 传到第一个任务
char * char2 ="这是第二个任务"; // 传到第二个任务

// 创建第一个任务不固定任何核心
xReturned1 = xTaskCreate(
vTask, // pvTaskCode
"vTask1", // pcName
10000, // usStackDepth
(void*) char1, // pvParameters
1, // uxPriority
&xHandle1 // pvCreatedTask
);

// 打印第一个任务创建状态
Serial.println("第一个任务返回值 =============================");
Serial.println(xReturned1);
// 获取当前未分配的内存堆大小:
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());


// 创建第二个任务固定到核心一
xReturned2 = xTaskCreatePinnedToCore(
vTask, // pvTaskCode
"vTask2", // pcName
8192, // usStackDepth
(void*) char2, // pvParameters
1, // uxPriority
NULL, // pvCreatedTask
1 // xCoreID

);

// 打印第二个任务创建状态
Serial.println("第二个任务返回值 =============================");
Serial.println(xReturned2);
// 获取当前未分配的内存堆大小:
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());
}

void loop() {
Serial.println("loop 函数运行次数: " + String(num));

// 获取当前未分配的内存堆大小
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());

if (num > 5) {
if (xHandle1 != NULL) {
// 从外部结束第一个任务
Serial.println("从外部结束第一个任务 =============================");
vTaskDelete(xHandle1);
xHandle1 = NULL;
}
}

num++;
delay(2000);
}

// 任务函数
void vTask(void *pvParameters) {
while(true) {
// 将 pvParameters 参数转换回 char*
char *pcTaskName = (char*)pvParameters;
String st1 = pcTaskName;
Serial.println("当前任务传递的参数为 =============================> " + st1);

if (pcTaskName=="fghij" && num > 10) {
Serial.println("从内部销毁第二个任务");
// 从任务自身代码内部进行任务销毁
vTaskDelete(NULL);
}

delay(1000);
}
}

参数说明:xTaskCreate 其实内部调用的就是 xTaskCreatePinnedToCore, 只不过将 xTaskCreatePinnedToCore 第七个参数设置为 tskNO_AFFINITY, 不指定核心

pvTaskCode:
指向任务输入功能的指针。必须实现任务以永不返回(即连续循环)。

pcName:
任务的描述性名称。这主要用于方便调试。由configMAX_TASK_NAME_LEN定义的最大长度 - 默认值为16。
usStackDepth: 任务堆栈的大小指定为堆栈可以容纳的变量数 - 而不是字节数。例如,如果堆栈为16位宽且usStackDepth定义为100,则将为堆栈存储分配200个字节。
pvParameters: 指针将用作正在创建的任务的参数(下面有说明)。
uxPriority: 任务应运行的优先级。包含MPU支持的系统可以选择通过设置优先级参数的位portPRIVILEGE_BIT以特权(系统)模式创建任务。例如,要以优先级2创建特权任务,应将uxPriority参数设置为(2 | portPRIVILEGE_BIT)。
pvCreatedTask: 用于传回一个句柄,通过该句柄可以引用创建的任务(在外部通过句柄关闭该任务等)。
xCoreID: 如果值 为tskNO_AFFINITY,则创建的任务不会固定到任何CPU,并且调度程序可以在任何可用的核心上运行它。其他值表示任务应固定到的CPU的索引号。比如你的 esp32 是双核心,那么你可以指定 0, 1 这两个核心。

pvParameters说明

pvParameters 是向任务传递的参数,任务里面可以接收使用,只不过传输之前需要


1. 声明变量

2. 转成 (void*) ===> (表示任意类型的指针,或者该指针与一地址值相关,但是不清楚在此地址上的对象的类型)

3. 任务接收后再转回原来的类型


char 例子 char *char1 ="abcde";
(void*)char1
char *pcTaskName = (char*)pvParameters;
int 例子
int int1 = 12345;
(void*)int1
int pcTaskName = (int)pvParameters;


string 例子

String string1 ="abcdef";
(void*)&string1
String pcTaskName = *(String*)pvParameters; string[] 例子

String str3[3] = {"to", "ta", "bo"};  

(void*)&st3

String pcTaskName[3] = {*(String*)pvParameters, *((String*)pvParameters+1), *((String*)pvParameters+2)};





2398
0
2年前