发布网友
共1个回答
热心网友
常用的嵌入式软件架构有几种不同的基本类型。 在这种设计中,软件有一个简单的循环,这个循环调用各个子程序,每个子程序管理硬件或者软件的某一部分。中断通常用来设置标记或者更新软件其他部分能够读取的暂存器。
系统使用简单的API来完成允许和禁止中断设置。如果处理得当的话,它能够在嵌套子程序中处理嵌套调用,在最外面的中断允许嵌套中恢复前面的中断状态。这种方法是实现Exokernel的一个最简单的方法。
通常在循环中有一些子程序使用周期性的实时中断控制一组软件定时器,当一个定时器时间到的时候就会运行相应的子程序或者设置相应的标志。
任何可能发生的硬件事件都应该有软件定时器的支持,硬件事件大概每万亿次出现一次错误,对于现代的硬件来说大概是一年发生一次,对于以百万计大规模生产的设备来说,遗漏一个软件软件定时器在商业上可能是灾难性的。
有时测试软件运行一组基于软件的安全定时器,它们周期性地复位硬件中的软件看门狗。如果软件错过一个事件,安全定时器软件将会捕捉到它。如果安全定时器出错,看门狗硬件将会复位系统。
可以使用指向每个状态机函数的指针实现状态机,函数可以用C++、C或者汇编语言等实现。变化的状态将不同的函数放到指针中,每次循环运行时都会运行函数指针。
许多设计人员建议每个循环读一次输入输出设备、并且保存得到的结果,这样可以保证逻辑过程的在一致的参数上运行。
许多设计人员喜欢将状态机设计成每个状态仅仅检查一到两项内容,通常是检查硬件事件和软件定时器。
设计人员建议多级状态机应该让低层状态机早于高层状态机运行,这样高层就能够根据正确的信息运行。
如内部燃烧控制这样的复杂功能通常根据*表格进行处理,代码通常进行查表处理而不进行复杂的计算,为了减小表格的大小以及成本软件可以在条目之间进行差值运算。
在最小的单片机中,尤其是只有128位组堆栈的8051中,控制环允许好的连接器使用静态分配的数据覆盖本地变量。在这种机制中,离子程序调用树末端越近的变量得到的存储器地址越高。当开始一个新的分支的时候,它的变量可以在以前分支遗弃的空间中进行重新分配。
简单控制循环的一个主要缺点是它无法保证响应特定硬件事件的时间。
细心的设计可以很容易地保证中断不会被长时间禁止,这样中断代码就可以在非常精确的时间运行。
控制环的另外一个主要缺陷是增加新的特性的时候会变得复杂。需要花费很长时间的算法必须小心地进行分解以使得每次只有一小部分在主循环中运行。
这种系统的优势是它的简单性,并且在很小的软件上,循环运行地很快几乎没有人关心它是不可预测的。
它的另外一个优势是这种系统保证运行软件的质量,无法将不好的运行结果归咎为其他的操作系统。 非抢先式任务系统非常类似于上面的系统,只是这个循环是隐藏在API中的。我们定义一系列的任务,每个任务获得自己的子程序栈;然后,当一个任务空闲的时候,它调用一个空闲子程序(通常调用“暂停”、“等候”、“交出(yield)”等等)。
带有类似属性的架构都带有一个事件队列,有一个循环根据队列列表中的一个域确定删除时间和调用子程序。
这种架构的优点和缺点都非常类似于控制环,只是这种方法添加新的软件更加简单,只需要简单地编写新的任务或者将它添加到队列解释器中。 使用上面的任何一种系统,但是添加一个按照定时器中断运行子程序的定时器系统,这样就给系统添加了崭新的能力,这样定时器子程序第一次能在一个有保证的时间内运行。
另外,代码第一次能够在非预期的时间访问自己的数据结构。定时器子程序必须要象中断子程序一样进行处理。 使用上面的非抢先式任务系统,从一个抢先式定时器或者其他中断运行。
这样系统就突然变得很不一样了。任何一个任务的代码都有可能损害其他任务的数据 &emdash; 所以它们必须进行切缺的切分。对于共享数据的访问必须使用一些同步策略进行控制,如消息队列、信号灯或者非阻塞同步机制。
经常在这一步开发组织就会购买一套实时操作系统。如果一个组织缺少能够编写操作系统的人才或者操作系统将要在几个产品之上,这可能是一个明智的选择。这通常要将开发计划增加六到八周,and forever after programmers can blame delays on it. 这种方法试图将系统组织得比宏内核更易于配置,而同时提供类似的特点。
微内核是实时操作系统的一个逻辑发展,通常的组织方式是操作系统内核分配内存并且将CPU在不同的线程之间进行切换。用户模式的进程实现如文件系统、用户接口等主要的功能。
微内核在二十世纪五十年代开始首次尝试,但是由于计算机在任务间切换以及在任务间交换数据速度非常缓慢,所以人们放弃了微内核而钟情于MULTICS和UNIX风格的大内核。总体上来说,微内核在任务切换以及任务间通信速度快的时候是比较成功的,在速度慢的时候是失败的。
外内核通过使用普通的子程序调用获得的通信效率很高,硬件以及系统中的软件都是程序员能用也能扩展的。资源内核(可能是库的一部分)分配CPU时间、内存以及其他资源。如多任务、网络以及文件系统这样的大内核特性通过代码库来提供。库可以进行动态的连接、扩展或者共享。不同的应用甚至可以使用的不同的库,但是所有的资源都来自于资源内核。 一些航空电子系统使用几个商用计算机。这样更进一步,每个计算机都在模拟它们自身的几个副本,重要的程序同时在几个计算机上运行并且进行投票控制(vote)。
模拟环境的优点就是即使一个计算机出现故障,软件的不同例程能够迁移到正常工作的软件分区,表决的票数并不受影响。
通常虚拟软件运行在计算机的用户模式下,它捕捉、模拟硬件访问和不在用户模式下运行的指令。 这种系统通常在没有系统经费的嵌入式项目中流行,但是从这篇文章的多个作者来看,这通常是不正确的,它们的逻辑是:
操作系统是经过特殊封装的重用代码库。如果这些代码有用,设计人员就会节省时间和金钱,否则它们就是无用的。
商务系统的操作系统没有嵌入式硬件的接口。例如,如果要用Linux写一个马达控制器或者电话交换机,绝大部分的实际控制操作都是IOCTL调用,同时,正常的读、写和查询界面都是无用的。所以操作系统对于实际的开发妨碍很大。
大多数的嵌入式系统不处理办公事务,所以办公操作系统的大部分代码都被浪费了。例如,绝大多数的嵌入式系统从来都不使用文件系统或者屏幕,所以文件系统和图形用户界面部分就是浪费的,这些不用的代码只会影响系统的可靠性。
办公用操作系统保护硬件不让用户程序操作,这就严重地妨碍了嵌入式开发工作。
操作系统必须移植到嵌入式系统上,也就是说,硬件驱动程序无论如何都必须重写,这也是操作系统最难的部分,所以使用这样的操作系统几乎没有功效。
操作系统真正有用、可移植的特性是小段代码。例如,一个基本的TCP/IP接口大约有3000行代码,另外的一个例子是大约同样大小的简单文件系统。如果设计需要这些代码,能够使用少于嵌入式系统开发10%的经费就能完成,不需要支付版权费用,只需要简单地重写就可以了。如果系统这些代码有足够的通用性,嵌入式系统杂志封面的后面通常有公司销售没有版权费的C语言实现代码。
然而许多任务程师并不认同这一点,嵌入式Linux越来越受到人们的欢迎,尤其是在无线路由器和全球定位系统这样的功能强大的嵌入式系统中。其中有下面一些原因:
有现成的移植到普通嵌入式芯片的实现代码。
它们允许重用公开获得的设备驱动程序、网页服务器、防火墙或者其他代码。
开发系统能够从许多特性组合开始,在发布的时候可以剔除不需要的功能,从而节约所消耗的内存。
许多任务程师认为在用户模式运行应用程序更为可靠、更容易调试,所以开发过程更容易、代码更易于移植。
许多嵌入式系统没有控制系统那样对于实时性的严格要求,对于许多应用来说如嵌入式Linux这样的系统的响应速度就已经足够了。
要求更快的响应速度,而不是可靠性的特性,通常放到了硬件上。
许多实时操作系统都针对每件产品收取费用,当产品是消费品时,这项费用是巨大的。 一些系统需要安全、及时、可靠或者高效的特性,上面的架构却无法达到,构建这样的系统有一些广为人知的技巧:
1.雇佣一个真正的系统程序员。他们的花费很小,但是能够节约数年的调试以及相关的收入损失。
2.RMA (rate monotonic analysis),可以用来评估一组任务能否在特定的硬件系统下运行,在最简单的形式下,设计人员保证最快完成的任务有最高的优先级,平均来说 CPU 至少有 30% 的空闲时间。
3.和谐的任务能够高效地优化CPU。基本上来说,设计人员保证每件工作都是从heartbeat timer开始工作的。在实时操作系统上很难这样做,因为它们在等候输入输出设备的时候通常就会切换任务。
4.刚好有两个优先级(通常是运行和禁止中断)的系统不能出现高优先级任务等候低优先级任务释放信号灯或者其他资源的优先级倒置问题,
5.有监视器(monitor)的系统不能出现死锁。监视器锁住一段代码禁止中断和其他抢先任务。如果这个监视器只用于一小段快速运行的代码,系统可能工作正常。如果能够证明监视器 API 在所有情况下都能够完整运行,例如仅仅禁止中断,那么就不会产生系统挂起的情况。
这就意味着使用两个优先级和监视器的系统是安全、可靠的,因为它们没有死锁和优先级倒置的问题。如果监视器能够执行到结束,那么就永远不会挂起。如果使用和谐的任务,可能还会相当高效。然而,RMA 无法描述这些系统,优先级最好也不要到处都有,其中包括操作系统和硬件。