任务的创建和删除本质就是调用FreeRTOS的API函数
API函数 描述 xTaskCreate() 动态方式创建任务 xTaskCreateStatic() 静态方式创建任务 vTaskDelete() 删除任务
动态创建任务
任务的任务控制块以及任务的占空间所需的内存,均由FreeRTOS从FreeRTOS管理的堆中分配
静态创建任务
任务的任务控制块及任务的栈空间所需的内存,需用户分配提供
动态创建任务函数
BaseType_t xTaskCreate (TaskFunction pxTaskCode, //指向任务函数的指针const char* const pcName, //任务名字,最大长度configMAX_TASK_NAME_LENconst configSTACK_DEPTH_TYPE usStackDepth,//任务堆栈大小,注意字为单位void* const pvParameters,//传递给任务函数的参数,一般为NULLUBaseType_t uxPriority, //任务优先级,范围:0~configMAX_PRIORITIES-1TaskHandle_t* const pxCreatedTask//任务句柄,就是任务的任务控制块 )
返回值 描述 pdPASS 任务创建成功 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORT 任务创建失败
实现动态创建任务流程
- 将宏configSUPPORT_DYNAMIC_ALLOCATION配置为1
- 定义函数入口参数
- 编写任务函数
用起来只需以上3步
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
动态创建任务函数内部实现
- 申请堆栈内存&任务控制块内存
- TCB结构体成员赋值
- 添加新任务到就绪态列表中
任务控制块结构体成员介绍
typedef struct tskTaskControlBlock {volatile StackType_t *pxTopOfStack; //任务栈栈顶,必须为TCB的第一个成员Listltem_t xStateListltem; //任务状态列表项Listltem_t xEventListltem; //任务事件列表项UBaseType_t uxPriority; //任务优先级,数值越大,优先级越大StackTypr_t *pxStack; //任务栈起始地址char pcTaskName[configMAX_TASK_NAME_LEN];//任务名字...省略很多条件编译的成员 }tskTCB;
- 任务栈栈顶,在任务切换时的任务上下文保存、任务恢复息息相关
- 每个任务都有属于自己的任务控制块,类似身份证
静态创建任务函数
TaskHandle_xTaskCreateStatic (TaskFunction_t pxTaskCode, //指向任务函数的指针const char* const pcName, //任务函数名const uint32_t ulStackDepth, //任务堆栈大小注意字为单位void* const pvParameters, //传递的任务函数参数UBaseType_t uxPriority, //任务优先级StackType_t* const puxStackBuffer, //任务堆栈,一般为数组,由用户分配StackType_t* const pxTaskBuffer //任务控制块指针,由用户分配 );
返回值 描述 NULL 用户没有提供相应的内存,任务创建失败 其他值 任务句柄,任务创建成功 静态创建任务使用流程
- 需将configSUPPORT_STATIC_ALLOCATION配置为1
- 定义空闲任务&定时器任务的任务堆栈及TCB
- 实现两个接口函数
- vApplicationGetldleTaskMemory()
- vApplicationGetTimerTaskMemory()
- 定义函数入口参数
- 编写任务函数
用起来只需要上面五步
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
静态创建任务内部实现
- TCB结构体成员赋值
- 添加新任务到就序列表中
任务删除函数
形态 描述 xTaskToDelete 待删除任务的任务句柄
- 用于删除已被创建的任务
- 被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除
注意
- 当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)
- 空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存,则需要由用户在任务被删除前提前释放,否则将导致内粗泄露(动态or静态)
删除任务流程
- 使用删除任务函数,需将宏INCLUDE_vTaskDelete配置为1
- 入口参数输入需要删除的任务句柄(NULL代表删除本身)
用起来只需要上面两步
内部实现过程
- 获取所需删除任务的控制块:通过传入的任务句柄,判断所需要删除哪个任务,NULL代表删除自身
- 将被删除任务,移除所在列表:将该任务所在列表中移除,包括:就绪、阻塞、挂起、事件等列表
- 判断所需要删除的任务:
- 删除任务自身,需先添加到等待删除列表,内存释放将在空间任务执行
- 删除其他任务,释放内存,任务数量
- 更新下个任务的阻塞时间:更新下一个任务的阻塞超时时间,以防被删除的任务就是下一个阻塞超时的任务