任务创建和删除函数
相关若函数如图
在task.c中定义
1.xTaskCreate()
pxTaskCode //任务函数
pcName 任务名字//有限定长度,不超过configMAX_TASK_NAME_LEN。
usStackDepth //任务堆栈大小,字节数等于config MINIMAL_STACK_SIZE
pvParameters //传递给任务函数参数
uxPriotiry //任务优先级,不能使用最低最高优先级,前者由空闲任务占据,后者是时钟配置,必须为最高级
pxCreatedTask //任务句柄,任务创建后返回此任务句柄,即任务堆栈;动态创建的句柄名自定义,内存自动分配
返回值:
pdPASS 任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 创建失败,内存不够
2.xTaskCreateStatic()
pxTaskCode //任务函数
pcName 任务名字//有限定长度,不超过configMAX_TASK_NAME_LEN。
usStackDepth //任务堆栈大小,字节数等于config MINIMAL_STACK_SIZE
pvParameters //传递给任务函数参数
uxPriotiry //任务优先级
puxStackBuffer//任务堆栈,一般为数组,数组类型要为StackType_t
pxTaskBuffer//任务控制块
//静态创建的堆栈自定义,句柄名自动返回
返回值
NULL 任务创建失败,在puxStackBuffer或者pxTaskBuffer为NULL时候会导致错误发生
其他值:任务创建成功,返回任务的任务句柄
3.xTaskCreateRestricted()
pxTaskDefinition //指向一个结构体TaskParameters_t,这个结构体描述了任务的任务函数,堆栈大小,优先级等,于task.h定义
pxCreatedTask //任务句柄
返回值 pdPASS
4.函数vTaskDelete()
删除一个已经创建的任务,被删除后任务不再存在,也就是说再也不会进入运行态。任务被删除后就不再使用此任务句柄。
在使用动态创建(无Static)时,该任务之前申请的堆栈和控制块内存会在空闲任务被清除,因此删除后需要等待一段时间
如果是静态创建,则需要自己来释放掉,当任务删除后使用vPortFree()将50字节释放掉,否则会导致内存泄漏
如果在一个任务中程序为做完相关任务后删除自己,则可以直接写xTaskDelete(NULL);
参数
xTaskToDelete() //要删除的任务的任务句柄
动态创建
主要使用xTaskCreate()和vTaskDelete()这两个函数,函数来自于task.h
源代码兼过程如下:
首先,确保task.h的configSUPPORT_DYNAMIC_ALLOCATION == 1
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"//这个头文件必须在task.h之前被包含进来,否则报错,
#include "task.h"
void start_task(void *pvParameters);//引用起始函数,因为函数定义于main后边
TaskHandle_t *StartTask_Handler; //因为在start_task任务生成时候是直接用&xx(xx指的是自定义句柄名称。&即取址符号)的
void task1_task(void *pvParameters);
TaskHandle_t *Task1Task_Handler;
void task2_task(void *pvParameters);
TaskHandle_t *Task2Task_Handler;
int main(void)
{
delay_init(168);
LED_Init();
LED0=1;
LED1=1;
xTaskCreate((TaskFunction_t) start_task,
(const char * ) "start_task",//任务名
(const uint16_t) 50,//堆栈大小
(void * ) NULL, // 参数
(UBaseType_t ) 1,//优先级
(TaskHandle_t *) &StartTask_Handler );//句柄取址
vTaskStartScheduler() ;//开启任务调度,之后在内存中的代码/任务们开始运行,按照优先级大小
}
void start_task(void *pvParameters)
{
xTaskCreate((TaskFunction_t) task1_task,
(const char * ) "task1_task",
(const uint16_t) 50,
(void * ) NULL,
(UBaseType_t ) 2,
(TaskHandle_t *) &Task1Task_Handler );
xTaskCreate((TaskFunction_t) task2_task,
(const char * ) "task2_task",
(const uint16_t) 50,
(void * ) NULL,
(UBaseType_t ) 3,
(TaskHandle_t *) &Task2Task_Handler );
vTaskDelete(NULL);//删除任务,这里由于是自尽所以用NULL
}
void task1_task(void *pvParameters)
{
LED0=~LED0;
vTaskDelay(500);
LED0=~LED0;
vTaskDelay(500);
}
void task2_task(void *pvParameters)
{
while(1)
{
LED1=~LED1;
vTaskDelay(400);
LED1=~LED1;
vTaskDelay(400);
}
}
最后将其编译并上传,两个灯泡就会同时以不同频率闪烁,感觉就像两个任务同时执行一样
静态创建
源代码以及讲解
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "FreeRTOS.h"//一样,必须是FreeRTOS.h在task.h前面
#include "task.h"
//由于默认不支持静态堆栈,因此需要在FreeRTOSconfig.h中定义一下
#define configSUPPORT_STATIC_ALLOCATION 1
//由于静态内存创建函数会返回句柄,因此需要定一下接受返回值的句柄
void start_task(void );
StaticTask_t StartTaskTCB;
StackType_t StartTaskStack[128];
void task1_task(void);
StaticTask_t Task1TaskTCB;
StackType_t Task1TaskStack[128];
TaskHandle_t Task1Task_Handler;
void task2_task(void );
StaticTask_t Task2TaskTCB;
StackType_t Task2TaskStack[128];
TaskHandle_t Task2Task_Handler;
///
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];//130,来自于FreeRTOS.h中的configMINIMAL_STACK_SIZE,用于定义空闲任务,优先级0
static StaticTask_t IdleTaskTCB;
static StackType_t TimerTaskStack[configMINIMAL_STACK_SIZE];//用于定义定时器任务,优先级最高
static StaticTask_t TimerTaskTCB;
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)//这个包括下边这个由于没有在给定文件中定义,因此需要自己解决
{
*ppxIdleTaskTCBBuffer=&IdleTaskTCB;//根据参数类型直接定义即可,如StaticTask_t
*ppxIdleTaskStackBuffer=IdleTaskStack;
*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer=&TimerTaskTCB;
*ppxIdleTaskStackBuffer=TimerTaskStack;
*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
int main(void)
{
delay_init(168); //³õʼ»¯ÑÓʱº¯Êý
LED_Init(); //³õʼ»¯LED¶Ë¿Ú
LED0=1;
LED1=1;
xTaskCreateStatic( (TaskFunction_t) start_task,
(char *) "start_task",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) 1,
(StackType_t *) StartTaskStack,
(StaticTask_t *) &StartTaskTCB );//注意,上边一行是数组不用&,这个不是数组,为给指针地址需要取址符
vTaskStartScheduler() ;
}
void start_task( void )
{
Task1Task_Handler=xTaskCreateStatic( (TaskFunction_t) task1_task,
(char *) "task1_task",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) 2,
(StackType_t *) Task1TaskStack,
(StaticTask_t *) &Task1TaskTCB );
Task2Task_Handler=xTaskCreateStatic( (TaskFunction_t) task2_task,
(char *) "task2_task",
(uint32_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(StackType_t *) Task2TaskStack,
(StaticTask_t *) &Task2TaskTCB );
vTaskDelete(NULL);
}
void task1_task(void)
{
while(1)
{
LED0=~LED0;
vTaskDelay(500);
}
}
void task2_task(void)
{
while(1)
{
LED1=~LED1;
vTaskDelay(400);
}
}