FreeRTOS任务创建、删除| FreeRTOS三

article/2024/6/24 18:33:21

目录

一、FreeRTOS任务创建与删除有关函数

1.1、创建/删除任务的API函数

1.1.1、动态创建任务

1.1.2、静态创建任务

1.1.3、删除任务

二、FreeRTOS任务创建与删除(动态方法)

2.1、实例

三、FreeRTOS任务创建与删除(静态方法)

四、临界区与任务调度器

4.1、临界区是什么

4.2、临界区使用

4.3、任务调度器


一、FreeRTOS任务创建与删除有关函数

1.1、创建/删除任务的API函数

1.1.1、动态创建任务

任务的创建和删除本质上就是调用FreeRTOS的API函数

函数名:xTaskCreate(xxx参数),作用:动态方式创建任务;

动态创建任务分析:

1)任务的任务控制块以及任务的栈空间所需的内存,均由FreeRTOS从FreeRTOS管理的堆中分配

2)函数存在返回值,当返回paPASS则表示任务创建成功,当返回

errCOULD_ NOT_ ALLOCATE REQUIRED_ MEMORY表示任务创建失败

3)实现动态创建任务流程只需三步:

        1、将宏configSUPPORT_DYNAMIC_ALLOCATION配置为1;

        2、定义函数入口参数;

        3、编写任务函数。

此函数创建的任务会立即进入就绪态,有任务调度器调度运行,内部实现三步:

        1、申请堆栈内存与任务控制块内存;

        2、TCB结构体成员赋值;

        3、添加新任务到就绪列表中。

动态任务创建函数原型:

    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */const configSTACK_DEPTH_TYPE usStackDepth,void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pxCreatedTask )

参数解释:

pxTaskCode,含义:指向任务函数的指针

pcName,含义:任务名称

usStackDepth,含义:栈堆大小

pvParameters,含义:传递给任务的参数

uxPriority,含义:任务优先级

pxCreatedTask,含义:任务句柄

1.1.2、静态创建任务

函数名:xTaskCreateStatic(xxx参数),作用:静态方式创建任务

静态创建任务分析:

1)任务的任务控制块以及任务的栈空间所需内存,需要用户自己分配提供

2)函数存在返回值,返回值为NULL则表示用户没有提供相应的内存,任务创建失败,反正为其他值,则表示任务句柄,任务创建成功

3)静态创建任务流程五大步:

        1、需将宏configSUPPORT_ STATIC_ ALLOCATION 配置为1
        2、定义空闲任务&定时器任务的任务堆栈及TCB
        3、实现两个接口函数:vApplicationGetTimerTaskMemory()、vApplicationGetldleTaskMemory()

        4、定义函数入口参数

        5、编写任务函数

此函数创建的任务会立即进入就绪态,由任务调度器调度运行,内部实现为:

        1、TCB结构体成员赋值(因为内存已经提前设置好了,无需申请内存)

        2、添加新任务到就绪列表中

静态任务创建原型:

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   /*任务控制块指针,由用户分配
);

1.1.3、删除任务

函数名:vTaskDelete(TaskHandle_t xTaskToDelete),作用:删除任务

形参:xTaskToDelete,描述:待删除任务的任务句柄

删除任务函数分析:

1)被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除

2)当传入的参数为NULL时,则任务删除任务自身(当前正在运行任务)

3)空闲任务会负责释放被删除任务中由系统分配的内存,但是用户在任务删除前申请的内存,需要用户在任务被删除前提前释放,否则将导致内存泄露

4)使用只需两步:

        1、使用删除任务函数,需将宏INCLUDE_ _vTaskDelete 配置为1
        2、入口参数输入需要删除的任务句柄(NULL代表删除本身)

5)任务删除内部实现过程:
        1、获取所要删除任务的控制块,通过传入的任务句柄,判断所需要删除哪个任务,NULL代表删除自身
        2、将被删除任务,移除所在列表,将该任务在所在列表中移除,包括:就绪、阻塞、挂起、事件等列表
        3、删除任务自身,需先添加到等待删除列表,内存释放将在空闲任务执行,判断所需要删除的任务,删除其他任务,释放内存,任务数量-1
        4、 更新下个任务的阻塞时间,更新下一个任务的阻塞超时时间,以防被删除的任务就是下一个阻塞超时的任务

二、FreeRTOS任务创建与删除(动态方法)

2.1、实例

说明:

1)下列实例实现了创建了一个开始任务,并在开始任务中创建了任务1和任务2,并在创建完成两个任务后删除自身

2)任务1实现了led0的每隔100ms闪烁,任务1实现了led1的每隔100ms闪烁

3)移植测试要注意对应的配置是否一致,直接复制代码测试基本上都会报错

#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"
#include "timers.h"
#include "event_groups.h"#include "led.h"
#include "usart.h"//初始任务 用于创建其他任务,创建后自动删除
#define INIT_TASK_PRIO 1              /* 任务优先级   */
#define INIT_STK_SIZE  256            /* 任务堆栈大小 */
TaskHandle_t INITTask_Handler;        /* 任务句柄     */
void init_task(void *pvParameters);   /* 任务函数     *///LED0灯闪烁 
#define LED0_TASK_PRIO 2              /* 任务优先级   */
#define LED0_STK_SIZE  128            /* 任务堆栈大小 */
TaskHandle_t LED0Task_Handler;        /* 任务句柄     */
void led0_task(void *pvParameters);   /* 任务函数     *///LED1灯闪烁
#define LED1_TASK_PRIO 3              /* 任务优先级   */
#define LED1_STK_SIZE  128            /* 任务堆栈大小 */
TaskHandle_t LED1Task_Handler;        /* 任务句柄     */
void led1_task(void *pvParameters);   /* 任务函数     */int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4LED_Init();                      //LED初始化USART1_Init(115200);             //USART1初始化LED0_H;LED1_H;//初始任务xTaskCreate((TaskFunction_t )init_task,             //任务函数(const char*    )"init_task",           //任务名称(uint16_t       )INIT_STK_SIZE,         //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )INIT_TASK_PRIO,        //任务优先级(TaskHandle_t*  )&INITTask_Handler);    //任务句柄              vTaskStartScheduler();    
}//初始任务任务函数
void init_task(void *pvParameters)
{taskENTER_CRITICAL();            //进入临界区//创建LED0任务xTaskCreate((TaskFunction_t )led0_task,(const char*    )"led0_task",(uint16_t       )LED0_STK_SIZE,(void*          )NULL,(UBaseType_t    )LED0_TASK_PRIO,(TaskHandle_t*  )&LED0Task_Handler);//创建LED1任务xTaskCreate((TaskFunction_t )led1_task,(const char*    )"led1_task",(uint16_t       )LED1_STK_SIZE,(void*          )NULL,(UBaseType_t    )LED1_TASK_PRIO,(TaskHandle_t*  )&LED1Task_Handler);vTaskDelete(INITTask_Handler); //删除初始任务taskEXIT_CRITICAL();           //退出临界区
}void led0_task(void *pvParameters)
{while(1){LED0_L;vTaskDelay(100);LED0_H;vTaskDelay(100);printf("LED0 Test\r\n");}
}void led1_task(void *pvParameters)
{while(1){LED1_L;vTaskDelay(100);LED1_H;vTaskDelay(100);printf("LED1 Test\r\n");}
}

三、FreeRTOS任务创建与删除(静态方法)

说明:

1)静态创建任务比状态创建任务多的步骤,如下:

1、需要实现两个接口函数-->空闲任务接口必须实现,定时器任务不是必须的,不使用则关闭对应的宏

2)其它步骤与创建动态任务一致

实例暂无

四、临界区与任务调度器

4.1、临界区是什么

1、代码的临界区

        代码的临界区也称为临界区,指处理时不可分割的代码,运行这些代码不允许被打断。一旦这部分代码开始执行,则不允许任何中断打入(这不是绝对的,如果中断不调用任何包含临界区的代码,也不访问任何临界区使用的共享资源,这个中断可能可以执行)。为确保临界区代码的执行,在进入临界区之前要关中断,而临界区代码执行完成以后要立即开中断。

4.2、临界区使用

实例:当我们创建任务时,每创建一个任务,这个任务就会被任务调度器调度到运行态。但是我们希望所有的任务创建好了,按照指定的优先级进行运行,这种情况下就需要使用临界区。

使用思路:在创建任务前,使用FreeRTOS的内置函数-->taskENTER_CRITICAL()进入到临界区,在之后被创建的任务,就保持在就绪态,任务调度器无法进行任务的调度,当所有的任务完成创建时,我们使用FreeRTOS的内置函数-->taskEXIT_CRITICAL()退出临界区。此时所有被创建的任务都是就绪态,但当我们使用抢占式时,任务就回按照优先级进行运行,达到我们的目的。

4.3、任务调度器

函数:vTaskStartScheduler(),作用:开启任务调度

怎么使用:在创建任务后,调用该函数即可,每次程序运行只需调用一次(在第一个创建的任务函数后面调用该函数即可)

当我们创建任务,任务并不会自动的进行排序,我们需要使用FreeRTOS内置的函数-->vTaskStartScheduler()帮助我们把创建的任务按照优先级进行排序,程序才会有序运行。


http://www.ngui.cc/article/show-845551.html

相关文章

设置/恢复系统隐藏文件 - Windows系统

设置/恢复系统隐藏文件 - Windows系统前言普通隐藏文件显示文件设置/取消隐藏系统隐藏文件显示文件设置/取消隐藏前言 本文介绍Windows系统如何设置/恢复隐藏文件,隐藏文件包含普通隐藏文件和系统隐藏文件,系统隐藏文件一般是受保护的系统文件&#xff…

如何使用自己的虚拟机(linux)做个RAID玩?

在虚拟机原有基础上添加两块磁盘(均20G),步骤如下:使用命令“lsblk”检查添加是否生效;使用命令“mdadm”进行linux的raid管理(先安装mdadm工具)创建RAID1,名字为md1,即使用mdadm命令…

并发编程-多线程并发设计原理

并发编程-多线程&并发设计原理并发编程简介多线程&并发设计原理1 多线程回顾1.1 Thread和Runnable1.1.1 Java中的线程1.1.2 Java中的线程:特征和状态1.1.3 Thread和Runnable接口1.1.4 Callable1.2 synchronized关键字1.2.1 锁的对象1.2.2 锁的本质1.2.3 实现…

TCP和UDP用Java实现

查询进程 netstat -ano #查看所有的端口 netstat -ano|findstr "5900" # 查看指定端口 tasklist|findstr "8696 #查看指定端口进程TCP和UDP的区别 TCP相当于打电话 连接稳定三次握手、四次挥手 三次握手: A:你瞅啥? B&…

GuLi商城-简介-项目介绍、分布式基础概念、微服务架构图

一、项目简介 1 、项目背景 1 )、电商模式 市面上有 5 种常见的电商模式 B2B、B2C、C2B、C2C、O2O; 1 、 B2B 模式 B2B (Business to Business), 是指商家与商家建立的商业关系。 如:阿里巴巴 2 、 B2C 模式 B2C (Business…

记录晖哥程序员职业规划一次授课笔记

发现 发明 道 普通知识、特殊知识 形而上学,为道,职场规律 形而下学,为气,python、go 万物生于有,而有生于无! 在职场中做无中生有的事。 利他精神 利他即利己 天予弗取反受其咎&#…

嵌入式串行通信协议

嵌入式系统中,不同芯片之间通常使用串行总线的方式进行连接,根据器件行业规范、应用场景,不同芯片通常选择不同的串行通信接口进行通信。常用的串行通信接口有:1-Wire、I2C、SPI、UART。 一、1-Wire 1-wire单总线是Maxim的全资子…

bug解决:Uncaught (in promise) TypeError: Toast.loading is not a function

在使用vue3做项目时,在其中使用了vant框架,在使用toast的加载组件或者是一些其他组件时,出现了如下的错误:Uncaught (in promise) TypeError: Toast.loading is not a function错误代码如下:Toast.loading({ message: …

文献阅读笔记 # Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks

《Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks》 用于快速搭建NLP任务的demo的开源项目sbert的原始论文,star数很多,ACL 2019。资源: pdf | code | doc本文文献完成于 2019 年,因此仅代表当时的数据。相关工作&#xff…

FFmpeg基础:音视频中的那些核心参数

文章目录帧率修改帧率码率修改码率计算文件Size码率和帧率是视频文件的关键指标参数,这些参数决定了一个视频文件的质量。如果我们知道了一个视频文件中所有流的码率我们就可以计算出这个视频文件的大小了。深刻理解码率和帧率概念对于使用ffmpeg进行音视频开发是很…