μC/OS-III 里面的环形表

文章目录

    • 1、时钟节拍任务
    • 2、定时器列表

μC/OS-III 里面两个地方用到了环形表,时钟节拍任务,定时器列表,通过排序后,效率是非常高的。
以下内容整理自 嵌入式实时操作系统uC/OS-Ⅲ

1、时钟节拍任务

全空的时钟节拍列表

2023/12/21 18:04:16

(1) 该时钟节拍列表由一个数据表(见 os_cfg_app.c 中的 OSCfg_TickWheel[]) 和一个计数器(OSTickCtr)构成。

(2) OSCfg_TickWheel[] 数据表包含的表项(entry)数目是由 os_cfg_app.h 文件中的 OS_CFG_TICK_WHEEL_SIZE 设定的,可在编译时进行配置。表项的具体数目要根据处理器中可用的 RAM 存储量和应用程序中的最大任务数来配置。一般可以把 OS_CFG_TICK_WHEEL_SIZE 的值设置为任务数目的1/4左右。建议不要使 OS_CFG_TICK_WHEEL_SIZE 的数值与时钟节拍的频率成倍数关系。如果时钟节拍频率是1000 Hz并且在用户的应用中有50个任务,那么用户应当避免把 OS_CFG_TICK_WHEEL_SIZE 的数值设置为10或20,而应当改为使用11或23。实际上,最好使用素数来设置 OS_CFG_TICK_WHEEL_SIZE。虽然在编译时很难预计运行时将会发生的事情,但理论上可以使在每个表项上等待的任务的数目均匀分布。

(3) 该数据表中的每个表项包含3个成员:

  • .NbrEntriesMax 表示在该表项上等待的任务的最大数目。应用程序可以通过调用函数 OSStatReset() 来重置 .NbrEntriesMax 的值。

  • .NbrEntries 表示在该表项上等待的任务的数目。

  • .FirstPtr 是一个指针变量,在表头上并属于该表,指向在该表项上的等待任务构成的双向链表(通过各任务的 TCB 结构体)。

每当任务 OS_TickTask() 接收到时钟节拍中断发送的信号时,它会将 OSTickCtr 加1。

当应用程序中的某个任务调用 OSTimeDlyXXX() 函数或者使用非零的超时值调用 OSXXXPend() 函数时,该任务会被自动插入到时钟节拍列表中。
在这里插入图片描述
MatchValue = 10 + 13
OSCfg_TickWheel[] spoke number = (10 + 13) * 2

MatchValue = 23
OSCfg_TickWheel[] spoke number = 11

第二个任务会插入到与第一个任务相同的表项中,如图 F5-11 所示。在同一个表项上等待的多个任务按照升序排列,因此,剩余等待时间最少的任务会放在时钟节拍列表的最前面。

在时钟节拍任务执行时(见 os_tick.c 文件中的 OSTickTask()OSTickListUpdate()),它首先会递增 OSTickCtr 的数值,然后判断应该处理哪个表项。如果位于该表项上的时钟节拍列表中有任务存在(即 .FirstPtr 非空),则时钟节拍任务会检查相关任务的 .TickCtrMatch 数值是否与 OSTickCtr 数值相同,如果相同,就会把相应的 OS_TCB 从时钟节拍列表中删除。如果该任务只是等待延时结束,则将会被放入任务就绪表中(后面会描述)。如果该任务在等待某个事件,则不仅需要把它从时钟节拍列表中删除,还需要把它从该事件的任务等待表中删除。在搜索时钟节拍列表时,一旦发现 OSTickCtr 的数值与任务的 .TickCtrMatch 数值不相等,就会立即结束该搜索操作。这是因为延时最先结束的任务总是放在表的最前面。

在这里插入图片描述
如果前面的任务延时还没有结束,那么后面的任务延时时间显然也没有到,也就没有必要再进一步搜索了。
注意,OS TickTask()在更新时钟节拍列表时所做的大部分工作都是在临界段代码中完成的。不过,由于时钟节拍列表是按照顺序排列的,因此,可以把临界区控制得相当短

时钟节拍中断服务程序仅需唤醒时钟节拍任务,可大大缩短中断处理时间。时钟节拍任务使用了一个由N个表项(即辐条)构成的环形数据表(即时钟节拍轮),N的数值由用户配置。所有延时的任务按照延时结束时刻分配到各个表项上,每次节拍中断发生时,只有其中一个表项上的任务可能延时结束。在各个表项上,任务按照延时结束的先后顺序排序。因此,时钟节拍任务每次被节拍中断唤醒后,只处理一个表项,从该表项中的第一个任务开始判断任务延时是否结束,延时结束则继续判断下一个任务,否则停止判断并返回,从而大大节省时间节拍处理时间。

2、定时器列表

在这里插入图片描述
F12-8(1) 定时器列表结构中含有一个表 (OSCfg_TmrWheel[],在 os_cfg_app.c 中声明) 和一个计数器 (OSTmrTickCtr,在 os.h 中声明)。

F12-8(2) 这个表可以容纳的条目数的最大值由参数 OS_CFG_TMR_WHEEL_SIZE 决定,可以在编译时设定(见 os_cfg_app.h)。实际的条目数取决于处理器可用的 RAM 大小和应用程序中的最大定时器数量。建议将 OS_CFG_TMR_WHEEL_SIZE 设为定时器数量的 1/4 左右。不建议将 OS_CFG_TMR_WHEEL_SIZE 设为定时器任务率的偶数倍。例如,如果定时器任务率是10Hz,请避免将 OS_CFG_TMR_WHEEL_SIZE 设为10或100(可以使用11或101)。最好使用素数。尽管在编译时很难预测运行时的情况,但在理想情况下,每个表项中定时器的数量应该是均匀分布的。

F12-8(3) 表中的每个条目包括三个字段:.NbrEntriesMaxNbrEntries.FirstPtr

  • .NbrEntries 表示链接到这个条目的定时器数量。
  • .NbrEntriesMax 用来跟踪表中的最大条目数。
  • .FirstPtr 包括一个指向当前位置上定时器双向链表的指针(通过 OS_TMR)。

每次时钟节拍中断服务程序 (ISR) 发送信号给定时器任务时,OSTmrTickCtr 增加1。

要将定时器插入定时器列表中,需要调用函数 OSTmrStart()。当然,定时器必须在使用之前先创建。

在这里插入图片描述
μC/OS-II将计算匹配值和序号,如下所示:

  • MatchValue = 12 + 10
  • OSCfg_TmrWheel[]中的序号 = 22


MatchValue = 22
OSCfg_TmrWheel[]中的序号 = 4

如图 F12-10 所示,第二个定时器插入到同一个条目指向的链表中,并且系统将根据定时器的剩余时间排序,将剩余时间较少的定时器排在链表头,而剩余时间最长的定时器排在链表尾。

在这里插入图片描述
当定时器任务执行时(见 os_tmr.cOS_TmrTask()),OSTmrTickCtr 开始加 1 并指向下一个辐条格子。如果此条中含有定时器(即 .FirstPtr 非空),那么第一个 S_TMR.Match 都会被检查是否与 OSTmrTickCtr 匹配。如果找到匹配的 OS_TMR,则将其从列表中移除,并且检查下一个,然后 OS_TmrTask() 将调用定时器回调函数(假设定时器创建时已定义)。反之,若 OSTmrTickCtr 不匹配定时器的 .Match 值,则查找过程立即结束。原因是链表已经排序,不需要再继续向后查找。

注意,OS_TmrTask() 执行时调度器是上了锁的。由于链表已经排序,并且查找过程在找不到匹配值后立即结束,因此临界代码段比较短。

备注:由于 OS_TMR 链表按照定时器的剩余时间从小到大排序,所以它们的 .Match 值也是按照相同顺序排列的。如果 OSTmrTickCtr 小于链表中某个定时器的 .Match 值,那么后面的定时器也一定都不匹配,可以停止查找并等待下一次比较。正是这样的轮设计和排序链表,使得系统大大减少了遍历每个定时器所需的时间。

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

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

相关文章

养老院自助饮水机(字符设备驱动)

目录 1、项目背景 2、驱动程序 2.1 三层架构 2.2 驱动三要素 2.3 字符设备驱动 2.3.1 驱动模块 2.3.2 应用层 3、设计实现 3.1 项目设计 3.2 项目实现 3.2.1 驱动模块代码 3.2.2 用户层代码 4、功能特性 5、技术分析 6. 总结与未来展望 1、项目背景 养老院的老人…

虾皮广告怎么做:如何在虾皮平台上进行广告投放

在虾皮(Shopee)平台上进行广告投放可以帮助您提高产品的曝光度和销量。通过有针对性的广告,您可以在虾皮平台上吸引更多的潜在买家,提高产品的可见度并增加销售机会。本文将为您介绍在虾皮平台上创建和管理广告的一些建议&#xf…

JAVA版的鸿鹄云商B2B2C:多商家入驻直播商城系统特性解析 商城免 费搭建

鸿鹄云商 b2b2c产品概述 【b2b2c平台】,以传统电商行业为基石,鸿鹄云商支持“商家入驻平台自营”多运营模式,积极打造“全新市场,全新 模式”企业级b2b2c电商平台,致力干助力各行/互联网创业腾飞并获取更多的收益。从消…

K8s攻击案例:Privileged特权容器导致节点沦陷

01、概述 特权容器(Privileged Container)是一种比较特殊的容器,在K8s中运行特权容器,需要将 Privileged 设为 true ,容器可以执行几乎所有可以直接在主机上执行的操作。 基于此,利用容器的特权配置可以获取…

BearPi Std 板从入门到放弃 - 引气入体篇(11)(SPI驱动 TFT LCD(ST7789))

简介 SPI 驱动 ST7789V2 进行字符显示, 并且使用中文库显示中文信息。主芯片: STM32L431RCT6LED : PC13 \ 推挽输出即可 \ 高电平点亮串口: Usart1 / LPUARTSPI(与LCD数据传输) : SPI2LCD_RESET(复位引脚): PC7 \ 推挽输出即可 LCD_POWER(…

一分钟学会“沉浸式翻译”插件的安装与使用

一、安装 安装地址:https://immersivetranslate.com/ 选择对应的浏览器进入安装即可 二、简单的翻译使用方法 第一次安装需要先刷新界面才可以达到翻译效果 核心需要修改的地方在以下三个: 第一处:设置翻译服务,免费版的可以直接…

光条中心线提取-Steger算法 [OpenCV]

在线结构光视觉传感器中,由线激光器发射出的线结构光,在本质上为一个连续且具有一定厚度的空间光平面,而在目标表面上所形成的具有一定宽度的光条特征,即为该光平面与目标表面相交而成的交线。在该空间光平面的厚度方向上&#xf…

【Midjourney】Midjourney根据prompt提示词生成人物图片

目录 🍇🍇Midjourney是什么? 🍉🍉Midjourney怎么用? 🔔🔔Midjourney提示词格式 Midjourney生成任务示例 例1——航空客舱与乘客 prompt prompt翻译 生成效果 大图展示 细节大…

光伏企业如何能够提高光伏电站的建设效率?

随着全球对可再生能源需求的日益增长,光伏行业的发展势头强劲。然而,光伏电站建设过程中往往存在效率低下的问题,这不仅影响了电站的运营成本,也制约了整个行业的发展速度。因此,如何提高光伏电站的建设效率&#xff0…

Zookeeper集群搭建,四字命令监控,Leader选举原理以及数据如何同步

Java学习面试指南:https://javaxiaobear.cn 1、集群角色 Leader: 领导者。 事务请求(写操作)的唯一调度者和处理者,保证集群事务处理的顺序性;集群内部各个服务器的调度者。对于create、setData、delete…

java日记:getMethod的用法介绍和实例

先上理论 通过类实例化对象的getMethods() 方法可以获得该类所包括的全部方法, 返回值是Method[]。 通过类实例化对象的getMethod()方法可以获得该类所包括的指定方法, 返回值是Method,每个Method对象对应一个方法,获得Method对象后,可以调用…

电影《名侦探柯南:黑铁的鱼影》观后感

上周看了电影《名侦探柯南:黑铁的鱼影》,整体故事的话,就是柯南他们团队一起去岛屿去上参观,“正好”碰上了“海上信标案件”,在柯南的电影里,用“正好”多少有些反讽的意味,因为柯南好像走到哪,都正好碰到…