34 2.6 xTaskCreate()
[[FreeRTOS_Reference_Manual_V10.0.0.pdf#page=34&selection=0,2,4,13|FreeRTOS_Reference_Manual_V10.0.0, page 34]]
FreeRTOS的任务创建与删除包括:
xTaskCreate:任务创建^b63126
task.h
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
const [configSTACK_DEPTH_TYPE]
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
);
创建一个新任务并将其添加到准备运行的任务列表中。configSUPPORT_DYNIMIC_ALLOCATION必须在FreeRTOSConfig.h中被设置为 1,或保留为定义状态(此时,它默认为 1),才能使用此RTOS API函数。
每个任务都需要RAM来保存任务状态,并由任务用作起堆栈。如果使用xTaskCreateStatic(),则RAM由应用程序编写者提供,因此可以在编译时进行静态分配。
如果使用了FreeRTOS-MPU,建议使用xTaskCreateRestricted()而不是xTaskCreate()。
参数:
pvTaskCode:指向任务入口函数的指针(即 实现任务的函数名称)。
pcName:任务的描述性名称。主要是为了方便调试,但也可以用于获取任务句柄。
FreeRTOSConfig.h中的configMAX_TASK_LEN定义。uxStackDepth:要分配用于 任务堆栈的 堆栈。例如:如果任务堆栈的宽度为16位,uxStackDepth为100,则将分配200个字节用于该任务的堆栈;例如,如果堆栈的宽度为32位,uxStackDepth为400,则将分配1600个字节用于该任务的堆栈。[[堆栈宽度与深度]]
size_t类型变量所能包含的最大值。pvParameters:作为参数传递给创建任务的值。 ^168f8e
pvParameters设置为变量的地址,则在执行创建的任务时该变量必须仍然存在——因此 传递堆栈变量的地址是无效的。[[传递变量给任务的注意事项]](void *)类型的指针,可以指向任意类型的变量,使用时注意类型转换。uxPriority:创建任务执行的优先级。
uxPriority中设置portPRIVILEGE_BIT位。configMAX_priority,如果未定义configASSET,则优先级会被静默限制为(configMAX_priority - 1)pxCreatedTask:用于将句柄传递至由xTaskCreate()函数创建的任务,句柄可以获取当前Task的一些信息。pxCreateTask是可选的,可设置为NULL。
返回:
如果任务创建成功,则返回pdPASS。否则返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY。
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
void myTask1(void *pvPara)
{
while (1) {
printf("Hello, moker, I'm in the task1 now!\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void app_main(void)
{
printf("Hello world! It's ESP32!\n");
TaskHandle_t myHandle1 = NULL;
xTaskCreate(myTask1, "myTask1 say hello", 1024, NULL, 1, &myHandle1);
}

可以看到,任务被创建后,正常执行。因为并没有删除任务,所以任务在app_main()返回后仍然在继续执行。接下来删除任务。
vTaskDelete:任务删除^906a4d
task.h
void vTaskDelete( TaskHandle_t xTask );
INCLUDE_vTaskDelete必须被定义为 1 才能使用此函数。vTaskCreate(),空闲任务不会失去微控制器的处理时间。任务代码分配的内存不会自动释放,并应在删除任务之前释放。参数:
xTask: 待删除的任务句柄,传递NULL将导致调用任务被删除。
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
void myTask1(void *pvPara)
{
while (1) {
printf("Hello, moker, I'm in the task1 now!\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void myTask2(void *pvPara)
{
while (1) {
printf("Hello, moker, I'm in the task2 now!\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void app_main(void)
{
printf("Hello world! It's ESP32!\n");
TaskHandle_t myHandle1 = NULL;
TaskHandle_t myHandle2 = NULL;
xTaskCreate(myTask1, "myTask1 say hello", 1024, NULL, 1, &myHandle1);
xTaskCreate(myTask2, "myTask2 say hello", 1024, NULL, 1, &myHandle2);
// 等待4s后删除任务myTask1
vTaskDelay(2000 / portTICK_PERIOD_MS);
if (myHandle1 != NULL) {
vTaskDelete(myHandle1);
printf("myTask1 is deleted!\n");
} else {
printf("myHandle1 is not empty!\n");
}
// 等待2s后删除myTask2
if (myHandle2 != NULL) {
vTaskDelete(myHandle2);
printf("myTask2 is deleted!\n");
} else {
printf("myHandle2 is not empty!\n");
}
}

可以看到,task1和task2同时开始运行,并且运行2s后删除任务,任务删除完成后才从app_main()返回。
^0a1af5
还有一种方法可以删除创建的任务,即 在任务函数内部追加vTaskDelete(NULL),即可达到任务运行完成后,自己删除自己的目的。
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
void myTask1(void *pvPara)
{
int delay = 2; // 设置为2s后自我删除
while (delay--) {
printf("Hello, moker, I'm in the task1 now! Delete in %d second(s).\n", delay);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
void myTask2(void *pvPara)
{
int delay = 3; // 设置为3s后自我删除
while (delay--) {
printf("Hello, moker, I'm in the task2 now! Detele in %d second(s)\n", delay);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
void app_main(void)
{
printf("Hello world! It's ESP32!\n");
xTaskCreate(myTask1, "myTask1 say hello", 2048, NULL, 1, NULL);
xTaskCreate(myTask2, "myTask2 say hello", 2048, NULL, 1, NULL);
}

可以看到,task1在运行2s后自我删除,task2在运行3s后自我删除,app_main在任务完成后返回。