FreeRTOS的移植
FreeRTOS官网:https://www.freertos.org/
系统相关配置文件详解
相关宏大致分为三类:
(1)INCLUDE:配置FreeRTOS中可选的API函数
(2)config: 完成FreeRTOS的功能配置和裁剪
(3)其他配置项:PendSV宏定义,SVC宏定义
任务的创建和删除API函数介绍
任务的创建和删除的本质就是调用FreeRTOS的API函数
API函数 | 描述 |
xTaskCreate() | 动态方式创建任务 |
xTaskCreateStatic() | 静态方式创建任务 |
xTaskDelete() | 删除任务 |
动态任务创建:
任务的任务控制块以及任务的栈空间所需要的内存,均由FreeRTOS从FreeRTOS管理的堆中分配。
静态任务创建
任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供。
动态创建任务函数
BaseType_t xTaskCreate
{
TaskFunction_t pxTaskCode,//指向任务函数的指针
const char*const pcName, //任务名字,最大长度是configMAX_TASK_NAME_LEN
const configSTACK_DEPTH_TYPE usStackDepth, //任务堆栈大小 ,注意字为单位
void*const pvParameters, //传递给任务函数的参数
UBaseType_t uxPiority, //任务优先级,范围:0~configMAX_PRIORITIES-1
TaskHandle_t* const pxCreatedTask //任务句柄,就是任务的任务控制块
}
返回值 | 描述 |
pdPASS | 任务创建成功 |
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY | 任务创建失败 |
实现动态任务创建任务流程(三步)
1、将宏configSUPPORT_DYNAMIC_ALLOCATION配置为1
2、定义函数的入口参数
3、编写任务函数
此函数创建的任务会立刻进入就绪态,由任务调度器运行。
动态创建任务内部实现
1、申请堆栈内存&任务控制块内存
2、TCB结构体成员赋值
3、添加新任务到就绪列表中
静态创建任务函数
BaseType_t xTaskCreateStatic
{
TaskFunction_t pxTaskCode,//指向任务函数的指针
const char*const pcName, //任务名字,最大长度是configMAX_TASK_NAME_LEN
const configSTACK_DEPTH_TYPE ulStackDepth, //任务堆栈大小 ,注意字为单位
void*const pvParameters, //传递给任务函数的参数
UBaseType_t uxPiority, //任务优先级
StackType_t* const puxStackBuffer,//任务堆栈,一般为数组,由用户分配
StackTask_t* const pxTaskBuffer //任务控制块指针,由用户分配
}
返回值 | 描述 |
NULL | 用户没有提供相应的内存,任务创建失败 |
其他值 | 任务句柄,任务创建成功 |
实现静态任务创建任务流程
1、将宏configSUPPORT_STATIC_ALLOCATION配置为1
2、定义空闲任务&定时器任务的任务堆栈及TCB
3、实现两个接口函数
4、定义函数的入口参数
5、编写任务函数
此函数创建的任务会立刻进入就绪态,由任务调度器运行。
任务删除函数
void vTaskDelete(TaskHandle_t xTaskToDelete);
形参 | 描述 |
xTaskToDelete | 待删除任务的任务句柄 |
用于删除已被创建的任务
注意
1、当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)
2、空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存,则需要由用户在任务被删除前提前释放,否则将导致内存泄漏。
任务创建和删除(动态方法)
1、实验目的:学会xTaskCreate()和vTaskDelete()的使用
2、实验设计:将设计四个任务:start_task 、task1、task2、task3
四个任务功能如下:
start_task:用来创建其他三个任务
task1:实现LED0每500ms闪烁一次
task2:实现LED1每500ms闪烁一次
task3:判断按键KEY0是否按下,按下则删除task1
typedef void*TaskHandle_t;
#define START_TASK_PRIO 1 //任务优先级
#define START_STK_SIZE 128 //任务堆栈大小
TaskHandle_t StartTask_Handler;//任务句柄
void start_task(void *pvParameters);
#define TASK1_PRIO 2 //任务优先级
#define task1_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Task1_Handler;//任务句柄
void task1(void *pvParameters);
#define TASK2_PRIO 3 //任务优先级
#define task2_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Task2_Handler;//任务句柄
void task2(void *pvParameters);
#define TASK3_PRIO 4 //任务优先级
#define task3_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Task3_Handler;//任务句柄
void task3(void *pvParameters);
int main()
{
//开始任务
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)
{
//创建任务1
xTaskCreate(
(TaskFunction_t ) task1, //任务函数
(const char* ) "task1", //任务名称
(uint16_t ) task1_STK_SIZE, //任务堆栈大小
(void* ) NULL, //传递给任务函数的参数
(UBaseType_t ) TASK1_PRIO, //任务优先级
(TaskHandle_t* ) &Task1_Handler //任务句柄
);
//创建任务2
xTaskCreate(
(TaskFunction_t ) task2, //任务函数
(const char* ) "task2", //任务名称
(uint16_t ) task2_STK_SIZE, //任务堆栈大小
(void* ) NULL, //传递给任务函数的参数
(UBaseType_t ) TASK2_PRIO, //任务优先级
(TaskHandle_t* ) &Task2_Handler //任务句柄
);
//创建任务3
xTaskCreate(
(TaskFunction_t ) task3, //任务函数
(const char* ) "task3", //任务名称
(uint16_t ) task3_STK_SIZE, //任务堆栈大小
(void* ) NULL, //传递给任务函数的参数
(UBaseType_t ) TASK3_PRIO, //任务优先级
(TaskHandle_t* ) &Task3_Handler //任务句柄
);
vTaskDelete(NULL);//开始任务创建了三个任务后,就需要删除开始任务,删除自己NULL或者StartTask_Handler
}
//task1:实现LED0每500ms闪烁一次
void task1(void *pvParameters)
{
while(1)
{
}
}
//task2:实现LED1每500ms闪烁一次
void task2(void *pvParameters)
{
while(1)
{
}
}
//判断按键KEY0是否按下,按下则删除task1
void task3(void *pvParameters)
{
while(1)
{
}
}
上述写法会出现一个问题,我们已知任务3的优先级高于任务2高于任务1,但是在我们上述代码实现的却是先运行任务1,再运行任务2,最后运行任务3。
修改:进入临界区后,会等他执行完创建的三个任务,直到退出临界区后,才开始我们任务调度,这样优先级就会根据优先级大小进行执行。
int main()
{
//开始任务
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();//进入临界区
//创建任务1
xTaskCreate(
(TaskFunction_t ) task1, //任务函数
(const char* ) "task1", //任务名称
(uint16_t ) task1_STK_SIZE, //任务堆栈大小
(void* ) NULL, //传递给任务函数的参数
(UBaseType_t ) TASK1_PRIO, //任务优先级
(TaskHandle_t* ) &Task1_Handler //任务句柄
);
//创建任务2
xTaskCreate(
(TaskFunction_t ) task2, //任务函数
(const char* ) "task2", //任务名称
(uint16_t ) task2_STK_SIZE, //任务堆栈大小
(void* ) NULL, //传递给任务函数的参数
(UBaseType_t ) TASK2_PRIO, //任务优先级
(TaskHandle_t* ) &Task2_Handler //任务句柄
);
//创建任务3
xTaskCreate(
(TaskFunction_t ) task3, //任务函数
(const char* ) "task3", //任务名称
(uint16_t ) task3_STK_SIZE, //任务堆栈大小
(void* ) NULL, //传递给任务函数的参数
(UBaseType_t ) TASK3_PRIO, //任务优先级
(TaskHandle_t* ) &Task3_Handler //任务句柄
);
vTaskDelet(NULL);//开始任务创建了三个任务后,就需要删除开始任务,删除自己NULL或者StartTask_Handler
taskEXIT_CRITICAL();//退出临界区