【嵌入式——FreeRTOS】任务

【嵌入式——FreeRTOS】任务

  • 任务创建和删除
    • 动态方式创建任务
    • 静态方式创建任务
  • 删除任务
  • 任务切换
    • 调度器
    • 任务切换流程
  • 任务挂起
  • 任务恢复
  • 相关API函数

任务创建和删除

动态方式创建任务

任务的任务控制块以及任务的栈空间所需的内存,均由freeRTOS从freeRTOS管理的堆中分配。此函数创建任务会立刻进入就绪态,由任务调度器调度运行。
任务的优先级,值越大,优先级越高

函数

xTaskCreate();
//返回值为pdPASS,任务创建成功。
//返回值为errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY,任务创建失败BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,  				//指向任务函数的指针const char * const pcName,  				//任务名字 最大长度configMAX_TASK_NAME_LEN(20)const configSTACK_DEPTH_TYPE usStackDepth,	//任务堆栈大小 字为单位void * const pvParameters,  				//传递给任务函数的参数UBaseType_t uxPriority, 					//任务优先级 范围 0 ~ configMAX_PRIORITIES(32)-1 TaskHandle_t * const pxCreatedTask ) 		//任务句柄,任务的任务控制块

示例

static void udpserver_sendto_client (void* argument){}static TaskHandle_t	udpserver_tid;#define UDPSERVER_THREAD_NAME       "task name"
#define UDPSERVER_THREAD_STKSZ      (configMINIMAL_STACK_SIZE * 4)
#define UDPSERVER_THREAD_PRIO       (tskIDLE_PRIORITY + 3)BaseType_t ret = xTaskCreate(udpserver_sendto_client, UDPSERVER_THREAD_NAME, UDPSERVER_THREAD_STKSZ, 
NULL, UDPSERVER_THREAD_PRIO, &udpserver_tid);

实现动态创建任务流程

  1. 将FreeRTOSConfig.h文件中的configSUPPORT_DYNAMIC_ALLOCATION宏配置为1;
  2. 定义函数入口参数;
  3. 编写任务函数。

动态创建任务内部实现

  1. 申请堆栈内存和任务控制块内存;
  2. TCB结构体成员赋值;(把前面申请的堆栈地址,赋值给控制块的堆栈成员)
  3. 初始化控制块中的成员
  4. 添加新任务到就绪列表。

静态方式创建任务

任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供。

函数

xTaskCreateStatic();
//返回值为句柄或者其他值,任务创建成功。
//返回值为NULL,任务创建失败。TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,			//指向任务函数的指针const char * const pcName, 			//任务名字 最大长度configMAX_TASK_NAME_LEN(20)const uint32_t ulStackDepth,		//任务堆栈大小 字为单位void * const pvParameters,			//传递给任务函数的参数UBaseType_t uxPriority,				//任务优先级 范围 0 ~ configMAX_PRIORITIES(32)-1 StackType_t * const puxStackBuffer,	//任务堆栈,一般为数组由用户分配StaticTask_t * const pxTaskBuffer ) //任务控制块指针,由用户分配PRIVILEGED_FUNCTION;

示例

#define STACK_SIZE 200//空闲任务配置
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];//软件定时器任务配置
StaticTask_t time_task_tcb;
StackType_t time_task_stack[configTIMER_TASK_STACK_DEPTH];StaticTask_t xTaskBuffer;
StackType_t xStack[ STACK_SIZE ];//空闲任务内存分配
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &idle_task_tcb;*ppxIdleTaskStackBuffer = idle_task_stack;*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;}//软件定时器内存分配
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,StackType_t ** ppxTimerTaskStackBuffer,uint32_t * pulTimerTaskStackSize )
{*ppxTimerTaskTCBBuffer = &time_task_tcb;*ppxTimerTaskStackBuffer = time_task_stack;pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;}void vTaskCode( void * pvParameters ){}TaskHandle_t xHandle = xTaskCreateStatic(vTaskCode,       // Function that implements the task."NAME",          // Text name for the task.STACK_SIZE,      // Stack size in words, not bytes.( void * ) 1,    // Parameter passed into the task.tskIDLE_PRIORITY,// Priority at which the task is created.xStack,          // Array to use as the task's stack.&xTaskBuffer );  // Variable to hold the task's data structure.

静态创建任务使用流程

  1. 将FreeRTOSConfig.h文件中的configSUPPORT_STATIC_ALLOCATION宏配置为1;

  2. 定义空闲任务和定时器任务的任务堆栈即TCB;

  3. 实现两个接口函数

    1. vApplicationGetIdleTaskMemory()
    2. vApplicationGetTimerTaskMemory();可选的
  4. 定义函数入口参数;

  5. 编写任务函数;

静态创建任务内部实现

  1. TCB结构体成员赋值;
  2. 添加新任务到就绪列表;

删除任务

用于删除已经被创建的任务。被删除的任务将从就绪态任务列表,阻塞态任务列表,挂起态任务列表和事件列表中移除。

函数

vTaskDelete();void vTaskDelete( TaskHandle_t xTaskToDelete )
//xTaskToDelete 待删除的任务句柄

注意

  1. 当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)。
  2. 空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存,则需要由用户在任务被删除前提前释放,否则将导致内存泄漏。

删除任务流程

  1. 将INCLUDE_vTaskDelete宏配置为1;
  2. 入口参数输入需要删除的任务句柄(NULL代表自身);

删除任务内部实现过程

  1. 获取所要删除任务的控制块;

  2. 将被删除的任务移除所在列表;

  3. 判断所需删除的任务

    1. 删除任务自身,需先添加到等待删除列表,内存释放将在空闲任务进行。
    2. 删除其他任务,释放内存,任务数量–
  4. 更新下个任务的阻塞时间;

任务切换

调度器

实现任务间的切换。本质就是CPU寄存器的切换

//启动任务,开启调度
vTaskStartScheduler();

当由任务A切换到任务B时,主要分为两步

第一步:需暂停任务A的执行,并将此时任务A的寄存器保存到任务堆栈,这个过程叫做保存现场。
第二步:将任务B的各个寄存器值(被存于任务堆栈中)恢复到CPU寄存器中,这个过程叫做恢复现场。对任务A保存现场,对任务B恢复现场,这个过程被称为上下文切换。

任务切换流程

  1. 触发PendSV中断
  2. 当前的psp是正在运行的任务的栈指针,读取当前psp进程指针,存入r0
  3. 压栈(保存现场)
  4. 获取当前最高优先级任务的任务控制块
  5. 出栈(恢复现场)
  6. 更新切换后的任务的栈指针给psp
  7. bx r14指向新任务函数

PendSV中断如何触发

  1. 滴答定时器中断调用。
  2. 执行FreeRTOS提供的相关API函数,portYIELD();

任务挂起

挂起任务

函数

此函数用于挂起任务,使用时将FreeRTOSConfig.h文件中宏INCLUDE_vTaskSuspend配置为1。
无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复。
当传入参数为NULL,则代表挂起任务自身(当前正在运行的任务)。

void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
//xTaskToSuspend  待挂起任务的句柄

任务恢复

恢复被挂起的任务

函数

此函数用于恢复任务,使用时将FreeRTOSConfig.h文件中宏INCLUDE_vTaskSuspend配置为1。
任务无论被挂起多少次,只需在任务中调用vTaskResume()恢复一次,就可以继续运行,且被恢复的任务会进入就绪状态。
在中断中恢复被挂起的任务。带有“FromISR”后缀是在终端函数中专用的API函数

void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
//xTaskToResume 待恢复任务的任务句柄

此函数用于恢复任务,使用时将FreeRTOSConfig.h文件中宏INCLUDE_vTaskSuspend配置为1,宏INCLUDE_xTaskResumeFromISR配置为1。
被恢复的任务的优先级大于当前执行的任务的优先级,就会返回pdTRUE需要手动执行任务切换(portYIELD_FROM_ISR()函数)。
中断服务程序中要调用freeRTOS的API函数则中断优先级不能高于freeRTOS所管理的最高优先级(5~15)。

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
//xTaskToResume 待恢复任务的任务句柄
//返回值 pdTRUE 任务恢复后需要进行任务切换  pdFALSE任务恢复后不需要进行任务切换

相关API函数

函数描述
uxTaskPriorityGet()获取任务优先级
vTaskPrioritySet()设置任务优先级
uxTaskGetNumberOfTasks()获取系统中任务的数量
uxTaskGetSystemState()获取所有任务状态信息
vTaskGetInfo()获取指定单个任务信息
xTaskGetCurrentTaskHandle()获取当前任务的任何句柄
xTaskGetHandle()根据任务名获取该任务的任何句柄
uxTaskGetStackHighWaterMark()获取任务的任务栈历史剩余最小值
eTaskGetState()获取任务状态
vTaskList()以表格形式获取所有任务的信息
vTaskGetRunTimeStats()获取任务的运行时间

更多API请查看官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/38730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c#asp.net中字典的使用

字典是一个键值对,可以用来保存数据,再查询; 下面是一个案例:依据多个学号查询多个学生的姓名,只能到数据库查询一次数据!!! 先在数据库查询学号对应的学生,把数据保存在…

mysql8.0.19安装zip版本

下载地址https://downloads.mysql.com/archives/community/ 下载版本 下载后解压,不包括data 和my.ini文件。其中data 文件是自动生成的【mysqld --initialize --console】,my.ini需要自己编写设置。 新建my.ini文件 需要自己设置 basedirG:\soft\mysql…

内网服务器时间校正

新购买的云服务器发现内网机器和可以访问外网的机器时间慢了三分钟,导致有些访问会报错,那么我们配置一下ntp校正一下时间。外网配置起来比较简单,直接下载ntp执行校正命令即可。 比当前时间慢了三分钟 注意当前服务器是可以访问外网的机器这…

【gitee使用教程】(创建项目仓库并上传代码简易版)

gitee使用教程,创建项目仓库并上传代码简易版 1.在码云上创建一个仓库2.将代码克隆到本地1.复制仓库地址2.找到你想要放置的文件位置,右键点击更多选项,选择Git Clone3.将复制的仓库地址填入URL 3. IDEA结合GIT和Gitee的简单使用idea需要识别…

【python】最新版抖音s逆向拿到数据,非常详细教程(附完整代码)

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

Excel 宏录制与VBA编程 ——VBA编程技巧篇一 (Union方法、Resize方法、Cells方法、UseSelect方法、With用法)

Uniom方法 使用Union方法可以将多个非连续区域连接起来成为一个区域,从而可以实现对多个非连续区域一起进行操作。 Resize方法 使用Range对象的Resize属性调整指定区域的大小,并返回调整大小后的单元格区域。 Cells方法 Cells属性返回一个Range对象。 Us…

Domino应用中的HTML5

大家好,才是真的好。 在xpages多年不见有效更新,前景不明的时候,Domino传统Web应用开发方式还是受到了应有的青睐。毕竟,在Nomad Web时代,连最传统的Notes CS原生应用也突然焕发了勃勃生机一样。 但,对有…

什么是strcmp函数

目录 开头1.什么是strcmp函数2.strcmp函数里的内部结构3.strcmp函数的实际运用(这里只列举其一)脑筋急转弯 结尾 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们要来认识一下C语言中的strcmp函数。 1.什么是strcmp函数 strcmp函数来自于C语言中的头文件<str…

ARP 原理详解 一

ARP 原理 ARP&#xff08;Address Resolution Protocol&#xff09;地址解析协议&#xff0c;是根据 IP 地址获取物理地址的一个 TCP/IP 协议。 OSI 网络七层模型中&#xff0c;IP 地址在 OSI 模型第三层&#xff0c;MAC 地址在第二层&#xff0c;彼此不直接通信。 在通过以…

Spring Cloud Alibaba AI 大模型使用示例

1 pom.xml, 注意版本(jdk17) &#xff0c;仓库地址&#xff0c;排除的依赖&#xff08;日志错误&#xff09; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www…

性能测试中的场景设计和测试执行

假设一个内部系统要求响应时间在 3s 以内&#xff0c;支持最大用户数为4万。根据二八原则&#xff0c;80%用户在20%时间使用系统(4w80%)/(24h20%)≈1.9点击/秒。并发数TPS&#xff08;运行时间思考时间&#xff09;1.9&#xff08;30.50.330.50.30.53&#xff09;21。 注意&am…

Flutter循序渐进==>数据结构(列表、映射和集合)和错误处理

导言 填鸭似的教育确实不行&#xff0c;我高中时学过集合&#xff0c;不知道有什么用&#xff0c;毫无兴趣&#xff0c;等到我学了一门编程语言后&#xff0c;才发现集合真的很有用&#xff1b;可以去重&#xff0c;可以看你有我没有的&#xff0c;可以看我有你没有的&#xf…

毫米波雷达深度学习技术-1.7训练一个神经网络

1.7 训练一个神经网络 对于训练神经网络&#xff0c;有两个步骤&#xff0c;即前向传递和误差反向传播。 1.7.1 前向传播和反向传播 在前向传递中&#xff0c;输入被馈送到模型并与权重向量相乘&#xff0c;并为每一层添加偏差以计算模型的输出。密集层或全连接层第l层的输入、…

SQL面试题练习 —— 查询前2大和前2小用户并有序拼接

目录 1 题目2 建表语句3 题解 1 题目 有用户账户表&#xff0c;包含年份&#xff0c;用户id和值,请按照年份分组&#xff0c;取出值前两小和前两大对应的用户id&#xff0c;需要保持值最小和最大的用户id排首位。 样例数据 ------------------------- | year | user_id | v…

网络基础-RIP协议

RIP&#xff08;Routing Information Protocol&#xff09;是一个基于距离矢量的动态路由协议&#xff0c;常用于小型到中型网络。RIP是较早的路由协议之一&#xff0c;具有简单易用的特点。以下是关于RIP协议的详细介绍&#xff1a; RIP的主要特点 ①使用跳数&#xff08;ho…

非标设备行业的数智化项目管理

近年来&#xff0c;中国制造快速发展&#xff0c;企业迫切需要加快转型升级。与传统制造业相比&#xff0c;高端制造业具有明显的优势&#xff1a;高技术、高附加值、低污染、低排放、竞争优势强。一方面&#xff0c;企业对于生产效率和自动化水平的要求不断提高&#xff0c;期…

开发个人OpenUI--1 项目介绍

开发个人OpenUI--1 项目介绍 开发个人OpenUI--1 项目介绍知识点大纲文章目录项目地址 开发个人OpenUI–1 项目介绍 本文将以一个使用Ollama部署的ChatGPT为背景&#xff0c;主要还是介绍和学习使用 go-zero 框架&#xff0c;开发个人OpenUI的服务器后端&#xff0c;使用Docker…

武汉星起航:成功挂牌上股交,领航亚马逊跨境电商,共创未来辉煌

在全球电商的竞争格局中&#xff0c;亚马逊凭借其卓越的服务、丰富的商品种类和高效的物流体系&#xff0c;始终稳坐全球电商市场的头把交椅。而在这股不可阻挡的电商浪潮中&#xff0c;武汉星起航电子商务有限公司凭借其前瞻性的战略布局和强大的运营能力&#xff0c;成功在20…

名企面试必问30题(十二)——简单介绍一下你的家庭情况

1.思路 对于面试官来说&#xff0c;他提出这个问题&#xff0c;只是为了深挖您的性格、稳定性、行事风格&#xff0c;包括未来定居规划、生育规划等基础信息&#xff0c;这是正常情况。您不要过多围绕其他家庭成员来讲&#xff0c;否则面试官无法获取他想要的&#xff0c;您也难…

【单片机毕业设计选题24040】-基于STM32的蓝牙防丢器设计

系统功能: 系统上电后显示“欢迎使用蓝牙防丢系统请稍后”两秒钟显示正常界面&#xff0c;如果蓝牙正常连接OLED显示Connected, 蓝牙未连接则显示DisConnected同时蜂鸣器报警 蓝牙正常连接后在APP上每隔三秒显示一个Connected 系统功能框图: 主要功能模块原理图: 电源时钟…