一、FreeRTOS任务相关API函数
1、任务创建和删除API函数
FreeRTOS最基本的功能就是任务管理,而任务管理最基本的操作就是创建和删除任务,FreeRTOS的任务创建和删除API函数如下表所示:
函数 | 描述 |
---|---|
xTaskCreate() | 使用动态的方法创建一个任务 |
xTaskCreateStatic() | 使用静态的方法创建一个任务 |
xTaskCrearteRestricted() | 创建一个使用MPU进行限制的任务,相关内存使用动态内存分配 |
vTaskDelete() | 删除一个任务 |
1. 函数xTaskCreate()
此函数用来创建一个任务,任务需要RAM来保存与任务有关的状态信息(任务控制块),任务也需要一定的RAM来作为任务堆栈。如果使用函数xTaskCreate()来创建任务的话,那么这些所需的RAM就会自动的从FreeRTOS的堆中分配,因此必须提供内存管理文件,默认我们使用
heap_4.c这个内存管理文件,
而且宏configSUPPORT_DYNAMIC_ALLOCATION必须为1。如
果使用函数xTaskCreateStatic()创建的话这些RAM就需要用户来提供了。新创建的任务默认就是就绪态的,如果当前没有比它更高优先级的任务运行,那么此任务就会立即进入运行态开始运行,不管在任务调度器启动前还是启动后,都可以创建任务。函数原型如下:
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
参数:
参数 | 描述 |
---|---|
pxTaskCode | 任务函数 |
pcName | 任务名字,一般用于追踪和调试,任务名字长度不能超过configMAX_TASK_NAME_LEN |
usStackDepth | 任务堆栈大小,注意实际申请到的堆栈是usStackDepth的4倍。其中空闲任务的任务堆栈大小为configMINIMAL_STACK_SIZE |
pvParameters | 传递给任务函数的参数 |
uxPriotiry | 任务优先级,范围0~configMAX_PRIORITIES-1 |
pxCreatedTask | 任务句柄,任务创建成功以后会返回此任务的任务句柄,这个句柄其实就是任务的任务堆栈。此参数就用来保存这个任务句柄。其他API函数可能会使用到这个句柄 |
BaseType_t | 返回值 pdPASS:创建成功,其他为不成功 |
2. 函数xTaskCreateStatic()
此函数和xTaskCreate()的功能相同,也是用来创建任务的,但是使用此函数创建的任务所需的RAM需要用用户来提供。如果要使用此函数的话需要将宏
configSUPPORT STATIC ALLOCATION 定义为1。函数原型如下:
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 ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
参数:
参数 | 描述 |
---|---|
pxTaskCode | 任务函数 |
pcName | 任务名字,一般用于追踪和调试,任务名字长度不能超过configMAX_TASK_NAME_LEN |
usStackDepth | 任务堆栈大小,注意实际申请到的堆栈是usStackDepth的4倍。其中空闲任务的任务堆栈大小为configMINIMAL_STACK_SIZE |
pvParameters | 传递给任务函数的参数 |
uxPriotiry | 任务优先级,范围0~configMAX_PRIORITIES-1 |
puxStackBuffer | 任务堆栈,一般为数组,数组类型要定义为StackType_t类型 |
pxTaskBuffer | 任务控制块 |
TaskHandle_t | 返回值,NULL为任务创建失败,其他值,任务创建成功,返回任务的任务句柄 |
3、函数xTaskCreateRestricted()
此函数也是用来创建任务的,只不过此函数要求所使用的MCU有MPU(内存保护单元),用此函数创建的任务会受到MPU的保护。其他的功能和函数xTaxkCreate()一样。函数原型:
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
参数 | 描述 |
---|---|
pxTaskDefinition | 指向一个结构体TaskParameters_t,这个结构体描述了任务的任务函数、堆栈大小、优先级等,在task.h文件有定义 |
pxCreatedTask | 任务句柄 |
BaseType_t | 返回值 pdPASS:任务创建成功,其他值:任务创建失败 |
4、函数vTaskDelete()
删除一个用函数xTaskCreate()或者xTaskCreateStatic()创建的任务,被删除了的任务不再存在,也就是说再也不会进入运行态。任务被删除以后就不能再使用此任务的句柄!如果此任务是使用动态方法创建的,也就是使用函数xTaskCreate()创建的,那么在此任务被删除以后此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数vTaskDelete()删除任务以后必须给空闲任务一定的运行时间。只有那些由内核分配给任务的内存才会在任务被删除以后自动的释放掉,用户分配给任务的内存需要用户自行释放掉,比如某个任务中用户调用函数pvPortMalloc()分配了500字节的内存,那么在此任务被删除以后用户也必须调用函数vPortFree()将这500字节的内存释放掉,否则会导致内存泄露。此函数原型如下:
vTaskDelete(TaskHandle_t xTaskToDelete)
参数 | 描述 |
---|---|
xTaskToDelete | 要删除的任务的任务句柄 |
二、任务创建和删除的代码展示
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "lcd.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED_TASK_PRIO 2
//任务堆栈大小
#define LED_STK_SIZE 128
//任务句柄
TaskHandle_t LEDTask_Handler;
//任务函数
void led_task(void *pvParameters);
//任务优先级
#define LCD_TASK_PRIO 3
//任务堆栈大小
#define LCD_STK_SIZE 128
//任务句柄
TaskHandle_t LCDTask_Handler;
//任务函数
void lcd_task(void *pvParameters);
//LCD刷屏使用的颜色
int lcd_discolor[14] = { WHITE,BLACK,BLUE,BRED,
GRED,GBLUE,RED,MAGENTA,
GREEN,CYAN,YELLOW,BROWN,
BRRED,GRAY };
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口
LED_Init(); //初始化LED端口
LCD_Init();
POINT_COLOR = RED;
LCD_ShowString(30,10,200,16,16,"LIU YI NIU BI");
LCD_ShowString(30,40,200,16,16,"2021/10/18");
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED0任务
xTaskCreate((TaskFunction_t )led_task,
(const char* )"led_task",
(uint16_t )LED_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED_TASK_PRIO,
(TaskHandle_t* )&LEDTask_Handler);
//创建LED1任务
xTaskCreate((TaskFunction_t )lcd_task,
(const char* )"lcd_task",
(uint16_t )LCD_STK_SIZE,
(void* )NULL,
(UBaseType_t )LCD_TASK_PRIO,
(TaskHandle_t* )&LCDTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED任务函数
void led_task(void *pvParameters)
{
u8 led_num = 0;
POINT_COLOR = BLACK;
LCD_DrawRectangle(5,110,115,314);
LCD_DrawLine(5,130,115,130);
POINT_COLOR=BLUE;
LCD_ShowString(6,111,110,16,16,"led run:000");
while(1)
{
led_num++;
LED0=~LED0;
LCD_Fill(6,131,114,313,lcd_discolor[led_num % 14]);
LCD_ShowxNum(86,111,led_num,3,16,0x80);
vTaskDelay(1000);
}
}
//LCD任务函数
void lcd_task(void *pvParameters)
{
u8 lcd_num = 0;
POINT_COLOR=BLACK;
LCD_DrawRectangle(125,110,234,314);
LCD_DrawLine(125,130,234,130);
POINT_COLOR= BLUE;
LCD_ShowString(126,111,110,16,16,"lcd run:000");
while(1)
{
lcd_num++;
LED1=!LED1;
// vTaskDelay(200);
LCD_ShowxNum(206,111,lcd_num,3,16,0x80);
LCD_Fill(126,131,233,313,lcd_discolor[13-lcd_num%14]);
vTaskDelay(1000);
}
}