FreeRTOS内部机制学习04(任务通知和软件定时器)

news2024/11/24 12:32:36

文章目录

  • 何为任务通知?
    • 任务通知使用例子
    • 任务通知的优势以及劣势
      • 优势
      • 劣势
    • 深入源码看看API函数内部干了什么
    • 函数的种类
    • 函数都做了啥?
  • 软件定时器
    • 软件定时器的作用
    • 软件定时器内部到底做了什么实现了“闹钟”功能
    • 引入守护任务,守护任务做了啥?
    • 守护任务的调度
    • 简单深入源码学习软件定时器

何为任务通知?

所谓"任务通知",你可以反过来读"通知任务"。就是就是一个简单唤醒其他任务的功能吗?那这样我队列、信号量、互斥量一样可以啊!那为什么要引进任务通知呢?那么我们就可以去看看任务通知到底有什么宇宙不同。
任务通知的通信是没有间隔的
使用队列、信号量、事件组时,我们都要事先创建对应的结构体,双方通过中间的结构体通信:
在这里插入图片描述
使用任务通知时,任务结构体TCB中就包含了内部对象,可以直接接收别人发过来的"通知":在这里插入图片描述
就是说创建任务的时候,任务里面创建的TCB结构体里面的某些变量就足以使用任务通知了
在这里插入图片描述
通知状态:
在这里插入图片描述
任务通知就是根据这个TCB里面的通知状态进行通信的。

任务通知使用例子

在这里插入图片描述
被通知的任务TCB结构体的通信状态的变换:
在这里插入图片描述

任务通知的优势以及劣势

优势

明确性、效率高:我们使用队列、信号量、事件组等等方法时,并不知道对方是谁。使用任务通知时,可以明确指定:通知哪个任务。
节省资源:相信深入学习过队列、信号量、互斥量的都知道它们在使用之前都需要创建,创建的时候里面都会分配一个结构体空间,里面会有链表、以及其他数据,队列传递数据时更多成了一个Buffer缓冲区,这些都是需要空间的,对于队列的细节可以看看我的这个文章:队列内部机制,在嵌入式里面,所谓是寸土寸金,对于空间利用来说所谓是斤斤计较,所以能省则省!任务通知则是不用创建,节省了很多空间!

劣势

不能发送数据给ISR
ISR并没有任务结构体,所以无法使用任务通知的功能给ISR发送数据。但是ISR可以使用任务通知的功能,发数据给任务。
数据只能给该任务独享
使用队列、信号量、事件组时,数据保存在这些结构体中,其他任务、ISR都可以访问这些数据。
使用任务通知时,数据存放入目标任务中,只有它可以访问这些数据。
在日常工作中,这个限制影响不大。因为很多场合是从多个数据源把数据发给某个任务,而不是把一个数据源的数据发给多个任务。
无法缓冲数据
使用队列时,假设队列深度为N,那么它可以保持N个数据。
使用任务通知时,任务结构体中只有一个任务通知值,只能保持一个数据。
无法广播给多个任务
使用事件组可以同时给多个任务发送事件。
使用任务通知,只能发个一个任务。
如果发送受阻,发送方无法进入阻塞状态等待
假设队列已经满了,使用 xQueueSendToBack() 给队列发送数据时,任务可以进入阻塞状态等待发送完成。
使用任务通知时,即使对方无法接收数据,发送方也无法阻塞等待,只能即刻返回错误。

深入源码看看API函数内部干了什么

函数的种类

任务通知有2套函数,简化版、专业版,列表如下:

简化版函数的使用比较简单,它实际上也是使用专业版函数实现的
专业版函数支持很多参数,可以实现很多功能
在这里插入图片描述
具体的API函数使用方法以及参数可以看看这个手册:FreeRTOS开发手册

函数都做了啥?

这些函数都无非和队列它们一样都是唤醒任务或者阻塞本身,任务通知就是有一点不一样,就是要修改任务里面的TCB里面的通知状态,仅此而已!关于任务的唤醒以及阻塞可以看看我之前写的文章:任务的调度机制
就可以把他们的作为概括为这样:
在这里插入图片描述挑出其中一个函数来分析:
在这里插入图片描述

软件定时器

软件定时器的作用

软件定时器就是"闹钟",你可以设置闹钟,
1、在30分钟后让你起床工作
2、每隔1小时让你例行检查机器运行情况

软件定时器也可以完成两类事情:
1、在"未来"某个时间点,运行函数
2、周期性地运行函数

日常生活中我们可以定无数个"闹钟",这无数的"闹钟"要基于一个真实的闹钟。
在FreeRTOS里,我们也可以设置无数个"软件定时器",它们都是基于系统滴答中断(Tick Interrupt)。

软件定时器内部到底做了什么实现了“闹钟”功能

前面所学的什么队列、信号量啊等等,处理任务通知,其他都需要创建,这个软件定时器也是需要创建的,那它的创建都创建了些什么呢?毫无疑问,还是那些结构体,以及=链表!那么它们的结构体里面的内容成员是什么呢?
在这里插入图片描述
在人类世界中,我们都是以时分秒为单位计算的,比如一个小时后去上班,等我五分钟,我上个厕所…等等。那么软件定时器是怎么样的呢?它们的单位是什么呢?其实它们的单位是Tick,学习任务调度的时候,任务调度也是由Tick Interrupt控制调度的,那么,对于它们来说就是,多少个Tick后我就来运行!还有就是我们人类世界是有一个表来计数时间的,那它们是通过什么来计数时间的呢?它们是在Tick中断里面进行计数的:在这里插入图片描述
那时间到了,我要去哪里找到那些任务到点了需要运行呢?这时候就需要链表上场表演了,创建的定时器的时候创建的各个结构体都会储存在一个链表里面,到时候我就会里面找,比对一下就知道了谁时间到了,周期性的还会更新里面的启动时间和到点时间,方便下次运行!
在这里插入图片描述

引入守护任务,守护任务做了啥?

在事件组中我们看到FreeRTOS的作者担心的问题,就是唤醒任务,你不知道要唤醒的任务的个数,具体可以看看我写的这个文章:事件组内部机制学习,害怕唤醒所需的时间过长,影响中断的性能,那么定时器也会有类似的担忧问题,讨论这个担忧的问题是什么之前,==我们来看看在哪里执行定时器回调函数呢?==第一印象就是在Tick中断中执行:

1、在Tick中断中判断定时器是否到时间了
2、如果时间到了,就调用软件定时器的回调函数
3、回调函数里面不得影响到别的任务,需要尽快执行:
不要调用会导致阻塞的API函数,比如 vTaskDelay()
可以调用 xQueueReceive() 之类的函数,但是超时时间要设为0:即刻返回,不可阻塞

但是,在FreeRTOS实时操作系统中,它想做到实时,就不可能允许在内核,在中断中执行不确定的大小,万一定时器函数非常的长(运行的时间非常长),就会导致Tick中断迟迟无法退出,影响任务的调度,进入影响整个系统!

所以在FreeRTOS中,不再Tick中断中执行软件定时器的回调函数。

那么在哪里调用定时器回调函数呢?它的做法和事件组的做法相同!都是利用队列唤醒一个任务来执行其他的工作的,软件定时器中的这个任务叫“守护任务”!以前被称为"Timer server",但是这个任务要做并不仅仅是定时器相关,所以改名为:RTOS Damemon Task。因为这个做法使用了队列,而不是在Tick中断中调用回调函数的,所以软件定时器的启动、停止函数的参数有一个超时时间也就不足为怪了!

BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );

当FreeRTOS的配置项 configUSE_TIMERS 被设置为1时,在启动调度器时,会自动创建RTOSDamemon Task。
守护任务的优先级为:configTIMER_TASK_PRIORITY;定时器命令队列的长度为configTIMER_QUEUE_LENGTH。
守护任务不是专为某个定时器服务的,它还要处理其他定时器

守护任务的调度

守护任务的调度,跟普通的任务并无差别。当守护任务是当前优先级最高的就绪态任务时,它就可以运行。它的工作有两类:
1、处理命令:从命令队列里取出命令、
2、处理执行定时器的回调函数
能否及时处理定时器的命令、能否及时执行定时器的回调函数,严重依赖于守护任务的优先级。下面使用2个例子来演示。

例子1:守护任务的优先性级较低
t1:Task1处于运行态,守护任务处于阻塞态
守护任务在这两种情况下会退出阻塞态切换为就绪态:命令队列中有数据、某个定时器超时了。至于守护任务能否马上执行,取决于它的优先级。
t2:Task1调用 xTimerStart()
要注意的是, xTimerStart() 只是把"start timer"的命令发给"定时器命令队列",使得守护任务退出阻塞态。
在本例中,Task1的优先级高于守护任务,所以守护任务无法抢占Task1。
t3:Task1执行完 xTimerStart()
但是定时器的启动工作由守护任务来实现,所以 xTimerStart() 返回并不表示定时器已经被启动了。
t4:Task1由于某些原因进入阻塞态,现在轮到守护任务运行。
守护任务从队列中取出"start timer"命令,启动定时器。
t5:守护任务处理完队列中所有的命令,再次进入阻塞态。
Idel任务时优先级最高的就绪态任务,它执行。
注意:假设定时器在后续某个时刻tX超时了,超时时间是"tX-t2",而非"tX-t4",从xTimerStart() 函数被调用时算起。

例子2:守护任务的优先性级较高
t1:Task1处于运行态,守护任务处于阻塞态。
守护任务在这两种情况下会退出阻塞态切换为就绪态:命令队列中有数据、某个定时器超时了。
至于守护任务能否马上执行,取决于它的优先级。
t2:Task1调用 xTimerStart()
要注意的是, xTimerStart() 只是把"start timer"的命令发给"定时器命令队列",使得守护任务退出阻塞态。
在本例中,守护任务的优先级高于Task1,所以守护任务抢占Task1,守护任务开始处理命令队列。
Task1在执行 xTimerStart() 的过程中被抢占,这时它无法完成此函数。
t3:守护任务处理完命令队列中所有的命令,再次进入阻塞态。
此时Task1是优先级最高的就绪态任务,它开始执行。
t4:Task1之前被守护任务抢占,对 xTimerStart() 的调用尚未返回。现在开始继续运行次函数、返回。
==t5:Task1由于某些原因进入阻塞态,进入阻塞态。==Idel任务时优先级最高的就绪态任务,它执行。
注意,定时器的超时时间是基于调用 xTimerStart() 的时刻tX,而不是基于守护任务处理命令的时刻tY。假设超时时间是10个Tick,超时时间是"tX+10",而非"tY+10"

简单深入源码学习软件定时器

#define xTimerstart(xTimer,xTicksTowait )   \  
xTimerGenericCommand(( xTimer ), tmrCONWMAND_START,( xTaskGetTickCount())NULL( xTicksTowait ) )

函数内部都做了什么?
在这里插入图片描述
那么毫无疑问肯定是守护函数在接收队列!那么守护函数里面具体做了什么呢?
在这里插入图片描述

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

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

相关文章

SprinBoot+Vue网上购物商城的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…

我们怎么把自动化测试落地到一个项目上呢?

现在的软件测试行业已经不是原先的点点点的功能测试,要想在软件测试这一行中扎根稳住,就需要你会的很多,不局限于功能测试,还要会自动化测试、接口测试、性能测试等。 今天就来说一下自动化测试,首先什么是自动化测试…

简单分享-获取.txt文件内数据 文件内数据逗号分隔 分隔符 C语言

简单分享-获取.txt文件内数据 文件内数据逗号分隔 分隔符 C语言 数据存储到文件中&#xff0c;把文件数据读取到数组&#xff0c;方便数据处理。 # include <stdio.h> # include <stdlib.h> # include <string.h>#define DATANUM 307200 //数组个数 int ma…

Linux之MySQL定时备份

#!/bin/bash #author: zking #MySQL定义备份并发送邮件 #定义变量 DATE$(date %F"_"%H:%M:%S) HOST127.0.0.1 DBdb1 USERNAMEroot PASSWORDun1xR00t MAILdonkeevip.qq.com BACKUP_DIR/data/db_backup SQL_FILE${DB}_sql_$DATE.sql#判断备份目录是否存在 if [ ! -d $B…

Visual Studio提示:无法安装CPpython.Exe.x64

如果你需要在Visual Studio中使用python环境&#xff0c;而且你本身已经有一个python环境&#xff0c;则只需要将你自己的python环境配置到Visual Studio中即可&#xff0c;可以无视如题报错&#xff0c;将不会产生实质性的问题或影响。 解决办法&#xff1a; 工具->获取工…

zabbix“专家坐诊”第255期问答

问题一 Q&#xff1a;大家好&#xff0c;问一下&#xff0c;zabbix做聚合图的时候&#xff0c;可以做到两根线在一个图里- 吗&#xff1f;还是说只能&#xff0c;单边计算聚合&#xff0c;然后再最后作图的时候&#xff0c;添加两条线上去 A&#xff1a;两个数据吗 Q&#xff…

安全政策与安全意识(上)

目录 1、信息安全保障 信息安全保障的三大支柱 2、网络犯罪 2.1 网络犯罪的概念 网络犯罪与计算机犯罪区别 2.2 网络犯罪的特点 2.3 犯罪形式 2.4 网络犯罪的原因(主观) 2.5 网络犯罪的原因(客观) 2.5预防网络犯罪的对策 2.6 计算机信息网络国际联网安全保护管理办法…

C语言知识体系思维导图

为了更清晰地描述C语言知识体系&#xff0c;笔者用一个结构化的思维导图来概括其主要组成部分。见下&#xff1a; 这个思维导图旨在提供一个全面而系统的视角&#xff0c;帮助学习者逐步构建扎实的C语言知识体系。随着学习的深入&#xff0c;可以根据个人兴趣和职业需求&#x…

缓存预热/雪崩/穿透/击穿

1. 缓存预热 预先将MySQL中的数据同步至Redis的过程 2. 缓存雪崩 Redis主机出现故障&#xff0c;或有大量的key同时过期大面积失效导致Redis不可用 Redis中key设置为永不过期&#xff0c;或者过期时间错开Redis缓存集群实现高可用多缓存结合预防雪崩服务降级 3. 缓存穿透 …

51单片机-AT24C02(IIC总线介绍及其时序编写步骤)-第一节(下一节实战)

IIC开始通信&#xff08;6大步&#xff09; 我以前的文章也有对基本常用的通信协议讲解&#xff0c;如SPI UART IIC RS232 RS485 CAN的讲解&#xff0c;可前往主页查询&#xff0c;&#xff08;2024.9.12,晚上20&#xff1a;53&#xff0c;将AT24C02存储芯片&#xff0c;掉电不…

Element UI按钮组件:构建响应式用户界面的秘诀

Element UI按钮组件&#xff1a;构建响应式用户界面的秘诀 一 . 创建按钮二 . 按钮的属性2.1 type 属性2.2 朴素按钮、圆角按钮2.3 size 属性2.4 圆形按钮2.5 加载状态2.6 禁用功能2.7 默认聚焦 三 . 按钮组 在现代网页设计中&#xff0c;按钮不仅是用户交互的核心元素&#xf…

即插即用篇 | YOLOv10 引入组装式Transformer模块AssembleFormer | arXiv 2024

本改进已同步到YOLO-Magic框架! 摘要—早期检测和准确诊断可以预测恶性疾病转化的风险,从而增加有效治疗的可能性。轻微的症状和小范围的感染区域是一种不祥的警告,是疾病早期诊断的重中之重。深度学习算法,如卷积神经网络(CNNs),已被用于分割自然或医学对象,显示出有希…

保姆级离线+windows环境+大模型前端UI安装(二)

看到很多文章采用docker在windows环境安装python或者是linux环境再装webui的&#xff0c;感觉比较麻烦&#xff0c;不够简洁&#xff0c;本文采用nodejs&#xff0c;来作为客户端引擎。 这篇只讲客户端安装&#xff0c;需要安装后端大模型及其运行的可以参考第一篇&#xff1a…

Vue入门学习笔记-表单

可以使用v-model 指令在表单控件元素上创建双向数据绑定。 引言&#xff1a; Vue采用了MVVM&#xff08;Model-View-ViewModel&#xff09;架构模式&#xff0c;通过指令可以快速实现数据和视图的双向绑定 修改视图层时&#xff0c;模型层也会改变&#xff1b;修改模型层&#…

【软考】程序设计语言基础

【软考】程序设计语言基础 一.程序设计语言基础概念 计算机要通过程序或指令来控制才能完成各种任务。程序设计语言&#xff08;计算机语言&#xff09;&#xff1a;人与机器交换信息的语言。 1.程序设计语言 计算机语言大致分为机器语言、汇编语言和高级语言三种。机器语言…

迁移学习:让你的深度学习模型更聪明的秘密武器

在深度学习领域&#xff0c;训练一个高效的模型通常需要大量的标注数据和计算资源。然而&#xff0c;获取这样的数据并不总是容易。幸运的是&#xff0c;迁移学习为我们提供了一种解决方案&#xff0c;它允许我们利用已有模型的知识&#xff0c;从而在新任务上获得更好的性能。…

被要求撤回Blackwell?一家初创企业称英伟达侵权自家技术,忍无可忍!英伟达和伙伴微软被齐齐告上法庭,赔偿或高达数十亿!

刚刚&#xff0c;一家初创公司居然把巨头英伟达和微软一起告了&#xff01; 名为Xockets的初创公司在诉讼中称&#xff0c;英伟达和微软公司窃取了其DPU技术&#xff0c;用以开发AI产品&#xff0c;并相互串通以压低其技术的价格&#xff0c;是名副其实的垄断行为&#xff01;…

C语言16--宏定义和关键字

预处理 在C语言程序源码中&#xff0c;凡是以井号&#xff08;#&#xff09;开头的语句被称为预处理语句&#xff0c;这些语句严格意义上并不属于C语言语法的范畴&#xff0c;它们在编译的阶段统一由所谓预处理器&#xff08;cc1&#xff09;来处理。所谓预处理&#xff0c;顾名…

有没有视频加字幕免费软件?值得收藏的10款字幕编辑软件推荐!

随着视频成为我们生活中不可或缺的一部分&#xff0c;它已然成为信息传播的重要方式。然而&#xff0c;仅有精彩的内容还不足以吸引全球观众&#xff0c;字幕的加入显得尤为重要。不仅能帮助不同语言的用户理解视频内容&#xff0c;还能提升视频的互动性。许多视频制作爱好者开…

Linux 防火墙:iptables (一)

文章目录 iptables 概述netfilter 与 iptables 的关系 四表五链规则表规则链数据包处理的优先顺序与规则链匹配顺序规则表的优先顺序规则链的匹配顺序规则链内的匹配顺序匹配流程示意图 安装与格式iptables 的安装iptables 防火墙的配置方法iptables 命令行配置方法常用的控制类…