基于raw os的事件触发系统
Raw
os的事件触发系统有以下特点:
1 基于UML的状态机理念设计,实现了有限状态机(fsm)以及层次状态机(HSM)。
2 实现了活动对象(ACTIVE OBJECT)的特性,一个活动对象包含了一个消息队列以及一个状态机。活动对象是具有优先级的,这样任务的实时性能够得到保证。消息队列的设计能够保证即时信号不丢失。
3活动对象(ACTIVE OBJECT)一共有64个优先级,对于小系统而言足够了。
4 整个系统消耗RAM只有几个字节,rom 消耗小于1K。而且64个活动对象共享一个栈空间。
5 消息系统支持紧急事件发送。一般的时候事件发到消息队列尾部,紧急事件可以发到头部。
6 支持活动对象超时机制,即在活动对象内部允许向某个活动对象启动一个软件定时器,超时了可以自动向指定的活动对象发送超时信号。
7 系统最大关中断时间为顺序15句C语言,在keil mdk 编译器(-O2)下总共有48句顺序汇编。假设一个机器时钟周期运行一句汇编,如果使用12M系统的8051, 系统最大关中断时间约为4us, 在72M的m3系统上为0.6us。这样的实时性对于中断反应来说是可以接受的。
8 系统任务的最大延迟时间为某个活动对象的状态机执行的最长的路径。所以设计短时间执行的状态机成为实时性关键。通常情况下状态机可以分解,写出短路径的状态机不是件难事。
9 整个事件触发系统为非抢占系统,也就是说不用担心各活动对象状态机之间的资源共享问题。唯一需要注意的是中断那边和状态机之间的资源冲突,因为有了消息机制,强制中断通过消息系统发送事件,一定程度上避免了临界区的问题。
10 基于状态机的编程对于解决某些复杂逻辑往往能出奇制胜。状态机也是目前科学界的根本基础。
11 基于状态机编程是目前最节省功耗的编程方式,裸机编程通常需要在超循环里面刻意的等待一个事件,一般为轮询。但是状态机只要没有事件就可以进入低功耗睡眠,其功耗之低是裸机编程无法匹敌的。对于rtos来说繁复的任务切换消耗了cpu大量的资源,其cpu利用率远低于状态机方式编程。
12 基于状态机的编程是一种非常机械的行为,通常画出状态机转换图,基本代码也就出来了,所见即所得,并不像某些人认为那样,状态机是很难编程的。
以下比较Raw os的事件触发系统和裸机编程的优势:
1 裸机通过大量的switch 和if一定程度上也可以实现状态机,但是软件规模大了,整个代码东跳西跳,随机性太大,基本代码无从维护。基于raw os 的事件触发机制避免了随意的switch和if, 整个框架井然有序,非常的机械性,代码是很容易维护的。适合大规模软件作战。
2裸机编程的任务最大的延迟是整个超循环轮询一圈,这样的机制是非常的糟糕,加入新的模块后,时间上更加无法估计,这是一种灾害编程。只能通过大量的异步中断去做实时性的东西,但是大量的代码在中断里面执行,会阻塞比它低优先级的中断,很容易造成其它中断得不到响应,进而数据丢失。基于raw os的事件触发机制所承受的任务最大延迟永远是活动对象的状态机执行最长的路径,不会随着模块的增加造成任务的最大延迟发生任何变化。实时性得到了保障。
3 裸机编程唯一的优势是简洁明了,适合初学者快速上手。基本C语言会用的可以快速投入产出,学习周期短。但是这个简单是有代价的,一旦系统一复杂那就是很难控制了。基于raw os 的事件触发机制非常容易上手,而且更能简洁的解决复杂逻辑性问题。
4 裸机编程实现低功耗是一件难事,很多情况下只是会轮询等待事件的发生,从而进入不到低功耗模式,但是基于raw os 的事件触发机制有事件发生才会运行,没事件发生一直处于睡眠状态,对于功耗的降低是不可言语的。
5资源使用问题,也许有人会说裸机省却了很多资源,其它rtos无法进入底资源的单片机运行,所以我们只能裸奔。对于传统的rtos来说,不幸这个是事实。对于8051这种长期不灭的怪物来说,甚至没有硬件的栈,资源也极其短缺,rtos的基础是每一个任务需要一个栈,栈的大小一般为512字节以上。8051 的确承受不起。但是基于raw os 的事件触发机制所有的活动对象共享一个栈,避免了资源的消耗,系统占的ram只有几个字节。申明一个活动对象也只要36个字节,相对裸机编程资源上并不会浪费多少。
以下比较raw os的事件触发系统和rtos编程的优势:
1 第一还是资源,尤其是ram, 目前的单片机紧缺的是ram通常不太缺rom。rtos每一个任务需要一个栈,但是raw os的事件触发系统所有的活动对象只需要一个栈,这个不是其它蜂鸟rtos所能比拟的。
2 第二实时性问题,很多rtos内核api是关中断的,比如ucos 2 的内核最大关中断时间在m3上可以超过20多us。对于中断相应这块很不利。rtos内核api是即使实现了最大关中断为0的特性,但是任务的延迟还是存在的。内核api必然要关抢占,一关抢占,任务的最大延迟时间就上升了。只要基于raw os的事件触发系统最长的状态机路径小于rtos的最大任务延迟,其实时性必然超越rtos。很多情况下这个是能做到的,因为rtos的最大任务延迟时间很长,有几十个us到上百个us。所以基于raw os的事件触发系统是很有机会击败很多rtos的实时性的无论是中断延迟,还是任务延迟。
3 在某种特殊情况下,比如在不支持浮点数的cpu运算,运算浮点数运算,必然会造成状态机时间运行增大,这种情况下基本很难分解状态机。怎么办?如果系统的实时性要求不是那么高的话,使用浮点数运算也没问题,如果系统需要很高的实时性,那就请你不要使用浮点数运算了。什么?你一定需要浮点数运算又需要实时性?如果资源允许的话请你上raw os, raw os的事件触发系统做为raw os 的一个子模块,紧紧的和raw os连接在了一起。在raw os的事件触发系统上做的所有工作在raw os上全部无条件支持。也许事件触发系统配合raw os进行无差别的编程,是目前最优的方案。
4 功耗问题,rtos因为个任务间的切换,造成了cpu的资源过度的浪费,其cpu利用率比起事件触发编程底的多,而且功耗也更大。raw os 的事件触发编程应该是目前最省功耗的编程方式了。
下面来介绍下raw os加上raw os 的事件触发编程的优势:
1 实时性,实时性永远是最重要的第一个话题,在一些高度安全的领域,系统无法响应外面的输入的话,将会产生灾难性的后果。目前主流商业rtos理论上的调度依据都是根据rms调度来的。Rms 理论简而言之任务越少,系统实时性越有保障,任务越多实时性越不能保障。假设系统的空闲任务运行raw os 的事件触发编程机制,就可以把更多的任务hold住,idle任务一共可以hold住64个活动对象,简而言之是是64个状态机。但是idle任务对于整个系统而言只是一个任务,idle内部分解任务再多也不会改变这一点。只有实时性更为紧迫的任务可以不放在idle任务里。这样设计的话会急剧减少任务数量的开支,任务实时性更有保障。
2功耗问题,因为更多的任务在idle里面完成,减少了任务的数量也就减少了任务的切换,功耗降低了不少。
3 关于资源,因为idle 任务里面运行的是事件触发机制,所有任务共享一个栈。资源会降低很多很多,最明显的减少了任务栈的开销。比如在64K ram 里运行ucos 2 会非常吃紧,但是引入了这个机制后,64K还是很丰富的晚餐。
关于和qp nano 实时系统的比较的问题:
1 qp
nano 一共实现了8个优先级的active object,往往在实践上不够用。raw os 的事件触发编程一共实现了64个优先级的active object,实践上足够了。
2 qp nano 的活动对象(active
object)超时计算效率低下,raw os 的事件触发编程提高了超时计算效率。
3 qp
nano 不支持紧急消息的发送,事实上对于有些很重要的事件消息,这个机制是必须的。
4 raw
os的状态机算法一定程度上参考了qp的,但是代码的可读性比起原版qp高得多。
Qp的qk 机制,实现了抢占的功能,但是这一块是有缺陷的。具体的现在不讨论这个问题,但是raw os 很好的弥补了这一块抢占的功能。
综上所述Raw os 加上raw os 的事件驱动机制的在实时性以及资源利用,cpu的利用率以及功耗上是无与伦比的。
raw
os 的事件驱动机制代码在以下位置:
http://www.raw-os.org/module.html
以上代码是基于stm32(cortex-m3)的移植,各家m3板子都是通用的,没有板子的也可以直接软件在线仿真。代码实现了一个模拟炸弹。炸弹解码是按键盘:uudua
希望大家喜欢。谢谢阅读此文章。
|