FreeRTOS中Task的创建与删除

FreeRTOS中Task的创建与删除

官方文档参考 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的任

官方文档参考

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的任务创建与删除包括:

  1. 任务创建 [[3. FreeRTOS中Task的创建与删除#^b63126]]
  2. 任务删除 [[3. FreeRTOS中Task的创建与删除#^906a4d]]
  3. 任务的自我删除 [[3. FreeRTOS中Task的创建与删除#^0a1af5]]

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:指向任务入口函数的指针(即 实现任务的函数名称)。

  • 任务通常以无限循环的形式实现;实现任务的函数绝不能返回或者退出。但是,任务可以自我删除。[[3. FreeRTOS中Task的创建与删除#^0a1af5]]

pcName:任务的描述性名称。主要是为了方便调试,但也可以用于获取任务句柄。

  • 任务名称的最大长度由FreeRTOSConfig.h中的configMAX_TASK_LEN定义。

uxStackDepth:要分配用于 任务堆栈的 堆栈。例如:如果任务堆栈的宽度为16位,uxStackDepth为100,则将分配200个字节用于该任务的堆栈;例如,如果堆栈的宽度为32位,uxStackDepth为400,则将分配1600个字节用于该任务的堆栈。[[堆栈宽度与深度]]

  • 堆栈深度与堆栈宽度的乘积不得超过size_t类型变量所能包含的最大值

pvParameters:作为参数传递给创建任务的值。 ^168f8e

  • 如果pvParameters设置为变量的地址,则在执行创建的任务时该变量必须仍然存在——因此 传递堆栈变量的地址是无效的。[[传递变量给任务的注意事项]]
  • 次参数类型是一个(void *)类型的指针,可以指向任意类型的变量,使用时注意类型转换。

uxPriority:创建任务执行的优先级。

  • 包含MPU支持的系统可在特权模式下选择性地创建任务,方法是在uxPriority中设置portPRIVILEGE_BIT位。
  • 断言优先级低于configMAX_priority,如果未定义configASSET,则优先级会被静默限制为(configMAX_priority - 1
  • 低优先级数字表示低优先级任务。 空闲任务的优先级为零 (tskIDLE_PRIORITY)。

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);
}

示例输出

截屏2024-06-11 22.33.53.png

可以看到,任务被创建后,正常执行。因为并没有删除任务,所以任务在app_main()返回后仍然在继续执行。接下来删除任务。


vTaskDelete:任务删除

^906a4d

task.h

void vTaskDelete( TaskHandle_t xTask );
  • INCLUDE_vTaskDelete必须被定义为 1 才能使用此函数。
    此函数的作用为从RTOS内核管理中移除任务。被删除的任务将从所有的就绪、阻塞、挂起和事件的列表中移除。
    请注意,空闲任务负责从已删除任务中释放RTOS内核分配的内存。因此,重要的是,如果应用调用了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");
    }
}

示例输出

3. FreeRTOS中Task的创建与删除-20240611223816291.webp

可以看到,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);
}

示例输出

3. FreeRTOS中Task的创建与删除-20240611231955372.webp

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

Comment