任务管理是FreeRTOS的核心功能,涉及任务的创建,任务的删除,任务挂起,任务的恢复和任务调度等内容,任务句柄用来标识一个任务,其类型名为TaskHandle_t,指向任务控制块。
函数名 | 函数功能 |
xTaskCteat() | 用动态内存分配方法创建任务 |
xTaskCteatStatic() | 用静态内存分配方法创建任务 |
xTaskCteatRestricted() | 创建MPU内存保护任务,任务堆栈用静态内存分配,任务控制块用动态内存分配 |
xTaskCteatRestrictedStatic() | 创建MPU内存保护任务,任务堆栈和任务控制块都用静态内存分配 |
vTaskDelete() | 删除任务 |
无论用什么方法创建任务都要使用任务函数,任务函数的返回值必须为void;FreeRTOS任务是一个死循环【while(1)】,任务不允许任何方式从实现函数中返回,即不可以有一条return语句,也不可以执行到函数末尾,如果一个函数不被需要,可以显示将其删除。
BaseType_t xTaskCteat(
任务函数;
任务名;
任务堆栈大小,单位word;
任务参数;
任务优先级;
任务句柄;
)
举例:
步骤一:创建任务函数Led0Task();
static void Led0Task(void *pvParameters)
{
while(1)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_15);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
步骤二:定义任务句柄,用xTaskCreat()创建任务
static TaskHandle_t Led0TaskHandle = NULL; //任务句柄
xTaskCreate(Led0Task, //任务函数
"Led0Task", //任务名
128, //堆栈大小
NULL, //参数
3, //优先级
&Led0TaskHandle); //句柄
vTaskStartScheduler(); //开启调度器
void vTaskDelete(任务句柄);
使用此函数需要在FreeRTOSConfig.h中将宏INCLUDE_vTaskDelete设置为1。如果传入参数为NULL,那么就是删除当前正在运行的任务。
void vTaskDeiete(TaskHandle_t Led0TaskHandle); //删除任务LEd0Task
在项目根目录中添加appTask文件,在文件中添加一对文件appTask.c和appTask.h,将appTask.c和appTask.h分别添加到Application/MDK-ARM和FreeRTOS/include中;在C/C++选项卡中添加文件路径。
任务创建与删除示例 :本示例通过 appStartTask()函数创建两个 FreeRTOS 任务。任务 1 的任务函数为Led0Task(),其功能是使LED0每秒闪烁1次,在完成5次闪烁后删除任务1。任务2的任务函数是Led1Task(),其功能是使LED1每秒闪烁2次。硬件的连接参考图,如果选用的是其他开发板,则请参考自己所选开发板的电路原理图。
开发板原理图
#ifndef _APPTASK_H_
#define _APPTASK_H_
#include "freertos.h" //FreeRTOS任务头文件
#include "task.h" //FreeRTOS任务实现头文件
static void Led0Task(void *pvParameters); //LED0闪烁任务
static void Led1Task(void *pvParameters); //LED1闪烁任务
void appStartTask(void); //用于创建其他任务的函数
#endif
#include "appTask.h"
#include "usart.h"
#include "string.h"
#include "stdio.h"
#include "FreeRTOS.h"
static TaskHandle_t Led0TaskHandle = NULL;
static TaskHandle_t Led1TaskHandle = NULL;
//Led0Task()任务函数创建
static void Led0Task(void *pvParameters)
{
uint16_t cnt = 0; //用于计数的局部变量
while(1)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
vTaskDelay(pdMS_TO_TICKS(500)); //每秒闪烁一次
printf("LED0正以1秒为周期闪烁。\r\n");
if(++cnt>=10)
{
if(eTaskGetState(Led0TaskHandle) != eDeleted) //如果没有被删除
{
vTaskDelete(Led0TaskHandle); //删除任务
printf("LED0任务被删除\r\n");
}
}
}
vTaskDelete(NULL); //删除自身
}
//Led1Task()任务函数创建
static void Led1Task(void *pvParmeters)
{
while(1)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_9);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
vTaskDelay(pdMS_TO_TICKS(250)); //每秒闪烁一次
printf("LED1每秒闪烁一次¸\r\n");
}
vTaskDelete(NULL); //删除自身
}
//开始任务函数,用于创建其他任务并开启调度器
void appStartTask(void)
{
taskENTER_CRITICAL(); //进入临界段,关中断
xTaskCreate(Led0Task,
"Led0Task",
128,
NULL,
4,
&Led0TaskHandle );
xTaskCreate(Led1Task,
"Led1Task",
128,
NULL,
4,
&Led1TaskHandle );
taskEXIT_CRITICAL(); //退出临界段,开中断
vTaskStartScheduler(); //开启调度器
}
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "freertos.h"
#include "task.h"
#include "stdio.h"
#include "string.h"
#include "appTask.h" //添加头文件
int main(void)
{
/* USER CODE END 2 */
appStartTask(); //创建任务并开启调度器
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while(1){
}
}
代码放在/* USER CODE END 2 */和 /* USER CODE BEGIN WHILE */之间,否则项目更新时会被删除!main()中appStartTask();后的代码不会被执行!
编译无误后将程序下载到开发板上,打开串口调试助手,可以看到LED0以每秒1次的频率闪烁,LED1以每秒2次的频率闪烁,LED0闪烁5次后,LED0停止闪烁,因为此时LED0闪烁任务已经被删除。
如果不可运行,可以试着修改堆栈大小(FreeRTOSConfig.h中)
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 15 * 1024 ) ) //修改堆栈大小