当前位置: 首页 > article >正文

400行程序写一个实时操作系统(十八):时间触发型RTOS的设计

前言

前面已经说过了,Sparrow采用的是时间触发系统的设计,本章将会讲解时钟触发相关的算法。

重新回顾一下时间触发系统的定义:

时间触发系统的任务调度基于定时器中断,适用于周期性任务和确定性要求高的场景,如控制系统。它的内部有一个时钟,每隔一定时间间隔就会触发一次时间中断,每次时钟中断时,调度器决定是否需要切换任务。

systick时钟

systick时钟是为RTOS而设计的的一个中断时钟,它使得RTOS在不同架构之间的移植性难度大大减小。在这里插入图片描述

在前面的文章中,笔者曾经调试过Sparrow来了解RTOS内部的中断使用,当时得出的结论是:SysTick中断会在一定时间间隔响应,然后触发PendSV中断产生上下文切换:

在这里插入图片描述

systick中断用法如下:
在这里插入图片描述

如何使用时钟

定时上下文切换

参考上面的程序,我们可以先设置SysTick时钟,让它在一定时间间隔响应,然后在SysTick中断中加入PendSV中断的触发函数,这样就能达到定时上下文切换的目的。

除此之外,SysTick本身就是一个定时器,RTOS中需要定时的地方太多了,我们必须高效利用它的定时功能。

延时阻塞态

利用延时的时间

在Sparrow中,任务有就绪态、阻塞态、挂起态三种状态,任何任务只能有一种状态。延时就是一种阻塞态,表示它在等待某个事情的发生。

让我们想一想,在非RTOS的环境中,我们的延时一般都是空等,但是在RTOS环境中,任务被分解为线程的形式,每个线程尽量与其他线程并行执行,那么,我们是不是可以在其他线程延时等待时,把它移除就绪表,然后把时间让给其他线程执行呢?等时间一到,再把它加入就绪表。

这当然是可行的。

如何设计算法?

延时则加入延时表
定期检查延时结束时间_时间到就加入就绪表
时钟计时提供时间基准
就绪表
任务一
任务二
延时表
任务A_延时结束时间
任务B_延时结束时间

如图所示,我们需要一张延时表,当每个任务延时时,这个任务会被踢出就绪表,延时表会记录它延时到期的时间,每一次SysTIck中断时,时间基数就会加1,然后我们可以先比较延时表中的任务是否到时间,如果到时间,那么就从延时表删除,加入就绪表,如果没到,就继续等。

如何解决溢出的问题?

我们知道计算机中一个数的大小是有上限的,比如uint_32,最大只能到2^32 - 1。如果发生了溢出那怎么办呢?

笔者提供两种思路:

1.设置更大的计数单位

2.使用两个表进行维护。

当然,Sparrow使用的是后一种。

设置更大的计数单位

请读者想一想,我们每天都是24小时轮转,但我们是怎么表示时间的呢?是通过年、月、日来进行记录,也就是说,SysTick的计数也可以这样干,每溢出一次,前面的计数单位就加一,这样就能记录事情发生的先后了。

但是假设时间非常漫长,那么单片机会不断的设置更大的计数单位,从秒、分、时、日、月,一直到年,每一个数字都需要内存来存储,这样的方法,缺点是内存并不固定。

使用两个表进行维护

正常情况下,任务的延时加上当前时间最多溢出一次,例如1 + 2^32 -1 会溢出一次,虽然1 + 2^32 - 1 + 2^32会溢出两次 ,但是这个时间段太长了,太离谱了,根本不可能被使用。既然最多溢出一次,那么,只要多一个表就可以解决溢出的问题。

记录没有溢出的延时表
记录的时间
记录的时间
记录溢出的延时表
记录的时间
记录的时间

当时间溢出发生时,由于此时记录没有溢出的延时表的任务肯定已经完成了延时,也就是说,这张表现在是空的。

此时只有溢出的延时表上的延时需要完成,当溢出再次发生时,我们又需要一张表难道我们要重新申请一块内存来存储表吗?

显然,完全不需要,因为没有溢出的延时表是空的,我们可以重复利用它。现在,之前溢出的延时表变成了未溢出的延时表,之前未溢出的延时表被重新利用,拿来记录现在溢出的延时任务!

使用两个表进行维护,这就是Sparrow的延时策略。

总结

先讲解了时间触发型RTOS的设计,然后讲解SysTick时钟,它通常作为RTOS的定时器。为了充分利用定时器,引入延时阻塞的概念,解决了裸机中常见的延时空等待的问题。


http://www.kler.cn/a/370797.html

相关文章:

  • Vue.js组件开发-如何处理跨域请求
  • LabVIEW实现油浸式变压器自主监测与实时报告
  • 【git】如何删除本地分支和远程分支?
  • 若依分页插件失效问题
  • 【力扣Hot 100】普通数组1
  • 【Linux】13.Linux进程概念(2)
  • 【跨越边界:嵌入式系统在物联网时代的重要性】
  • 需要了解这些关于漏洞的知识
  • Spring Boot框架在中小企业设备管理中的创新应用
  • 灵活如风:全面掌握动态新增 SQL Server 对象的实用指南
  • 【git】 git 删除了文件,如何找回
  • java中Scanner的nextLine和next方法
  • 地图讲故事之GIS遇到历史-中国十大古都篇
  • Linux 开机自动挂载硬盘
  • ThinkPHP+Mysql 灵活用工+灵活用工平台+灵活用工系统
  • 大数据新视界 -- 大数据大厂之大数据重塑影视娱乐产业的未来(4 - 4)
  • MySQL 数据库备份与恢复全攻略
  • 详解PHP正则表达式中的转义操作
  • SQL 与 MY SQL
  • Python实现基于WebSocket的stomp协议调试助手工具
  • 《MYSQL实战45讲》表数据删一半,为什么表文件大小不变?
  • 算法题解记录32+++最长连续序列(百题筑基)
  • 【专题】计算机网络之数据链路层
  • 【数据结构和算法】二、python中的常用数据结构(数组、链表、堆栈、递归、二叉树、哈夫曼树等数据结构的基本原理讲解与实战演练)
  • PyTorch中Transformer 模型介绍
  • 【Linux系统编程】线程深入运用