FreeRTOS—任务创建和删除的API函数和方法
文章目录
- 一、任务创建和删除的API函数
- 二、任务创建和删除(动态方法)
- 2.1.动态创建任务函数的内容
- 2.2.实现动态创建任务流程
- 2.3.任务控制块结构体成员介绍
- 三、任务创建和删除(静态方法)
- 3.1.静态创建任务函数的内容
- 3.2.静态创建任务使用流程
- 四、任务删除
- 4.1.任务删除函数的介绍
- 4.2.任务删除的流程
一、任务创建和删除的API函数
任务的创建和删除本质就是调用FreeRTOS的API函数,下表是动态创建任务、静态创建任务和删除任务对应的函数:
API函数 | 描述 |
---|---|
xTaskCreate( ) | 动态方式创建任务 |
xTaskCreateStatic( ) | 静态方式创建任务 |
vTaskDelete( ) | 删除任务 |
动态创建和静态创建不同之处:
- 动态创建任务:任务的任务控制块以及任务的栈空间所需要的内存,均有FreeRTOS从FreeRTOS管理的堆中提供,也就是FreeRTOS自动为用户申请堆空间,并由FreeRTOS管理
- 静态创建任务:任务的任务控制块以及任务的栈空间所需要的内存,需要用户自己分配提供,例如定义一个数值,需要自己获取空间内存,与动态创建任务相比,静态获取的空间是独立的,不由FreeRTOS管理
二、任务创建和删除(动态方法)
2.1.动态创建任务函数的内容
当该函数返回值是pdPASS
,为任务创建成功;返回值是errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
,为任务创建失败。
BaseType_t xTaskCreate
( TaskFunction_t pxTaskCode, //指向任务函数的指针const char * const pcName, //任务名字,最大长度 configMAX_TASK_NAME_LENconst configSTACK_DEPTH_TYPE usStackDepth, //任务堆栈大小,以字为单位void * const pvParameters, //传递给任务函数的参数UBaseType_t uxPriority, //任务优先级,范围:0 ~ configMAX_PRIORITIES - 1,也就是0 ~ 31TaskHandle_t * const pxCreatedTask //任务句柄,就是任务的任务控制块
)
2.2.实现动态创建任务流程
该函数创建的任务之后会立即进入就绪态,由任务调度器调度运行,接下来时动态创建任务的流程:
- 将宏
configSUPPORT_DYNAMIC_ALLOCATION
配置为1,该宏在 FreeRTOSConfig.h 文件中执行 - 定义函数入口参数
- 编写任务函数
动态创建任务函数内部的实现如下:
- 申请堆栈内存和任务控制块内存
- TCB结构体(任务控制块)成员赋值
2.3.任务控制块结构体成员介绍
下面代码是任务控制块结构体的各个成员介绍,其中任务栈栈顶与任务切换时的任务上下文保存、任务恢复息息相关,每个任务都有属于自己的任务控制块,就像每个人有自己的身份证。
typedef struct tskTaskControlBlock
{volatile StackType_t * pxTopOfStack; //指向任务栈栈顶的指针,必须是TCB的第一个成员ListItem_t xStateListItem; //任务状态列表项ListItem_t xEventListItem; //任务等待事件列表项UBaseType_t uxPriority; //任务的任务优先级StackType_t * pxStack; //任务栈的起始地址char pcTaskName[ configMAX_TASK_NAME_LEN ]; //任务的任务名//以下还有很多条件编译的成员......
} tskTCB;
三、任务创建和删除(静态方法)
3.1.静态创建任务函数的内容
下面是静态创建任务函数结构体的成员,当返回值为NULL
用户没有提供相应的内存,任务创建失败;当返回值为其他值时,如返回一个任务句柄,说明创建成功。
TaskHandle_t xTaskCreateStatic
(TaskFunction_t pxTaskCode, //指向任务函数的指针const char * const pcName, //任务函数名const uint32_t ulStackDepth, //任务堆栈大小,以字为单位,不是字节void * const pvParameters, //传递的任务函数参数UBaseType_t uxPriority, //任务优先级StackType_t * const puxStackBuffer, //任务堆栈,一般为数组,由用户分配StaticTask_t * const pxTaskBuffer //任务控制块指针,由用户分配)
3.2.静态创建任务使用流程
该函数创建的任务会立刻进入就绪态,由任务调度器调度运行。
- 将宏
configSUPPORT_STATIC_ALLOCATION
配置为1,该宏在 FreeRTOSConfig.h 文件中执行 - 定义空闲任务(这个是必须的,不要让CUP停下来)、定时器任务的任务堆栈及TCB
- 实现两个接口函数
①vApplicationGetdleTaskMemory( )
空闲任务,这个函数是必须要有的
②vApplicationGetTimerTaskMemory( )
定时器 - 定义函数入口参数
- 编写任务函数
静态创建任务函数内部的实现如下:
- TCB结构体(任务控制块)成员赋值
- 添加到新任务到就绪列表中
四、任务删除
4.1.任务删除函数的介绍
任务删除的函数是void vTaskDelete(TaskHandle_t xTaskToDelete);
它的形参是xTaskToDelete
,是待删除任务的任务句柄,该删除函数必须用于已被创建的任务,被删除的任务将从就绪任务列表、阻塞态任务列表、挂起态任务列表和事情列表中删除,注意以下几点
- 当传入的参数为NULL,代表删除任务自身(当前正在运行的任务),需要等自身运行结束之后才删除
- 空闲任务会负责释放被删除任务中由系统分配的内存,这是针对动态创建任务
- 由用户在任务删除前申请的内存,需要用户自己在任务被删除前提前释放,这是针对静态创建任务,否则将导致内存泄露
4.2.任务删除的流程
- 使用删除任务函数,需将宏
INCLUDE_vTaskDelete
配置为1,该宏在 FreeRTOSConfig.h 文件中执行 - 入口参数输入需要删除的任务句柄(NULL代表删除本身)
任务删除的内部流程:
- 获取所要删除任务的控制块:通过传入的任务句柄,判断所需要删除哪一个任务,NULL代表删除自身
- 将被删除任务,移除所在列表:将该任务在所在列表中删除,包括:就绪、阻塞、挂起、时间等列表
- 判断所需要删除的任务:删除任务自身,需先添加到等待删除列表,内存释放将在空闲任务执行;删除其他任务,释放内存,任务数量等
- 更新下个任务的阻塞时间:更新下一个任务的阻塞超时时间,以防被删除的任务就是下一个阻塞超时的任务
例如:当 t1、t2、t3 这三个任务,t2 任务里面有20ms的系统延迟,t3 任务里面有50ms的系统延迟,把这两个延迟放在阻塞列表中,t2 的20ms在50ms之前,如果 t1 任务刚好需要删除 t2 任务,阻塞时间就由20ms更新成50ms。