FreeRTOS零基础手把手教学笔记2

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();//退出临界区

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小奶盖儿月月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值