嵌入式系统(Embedded system),是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”,根据英国电器工程师协会( U.K. Institution of Electrical Engineer)的定义,嵌入式系统为控制、监视或辅助设备、机器或用于工厂运作的设备。与个人计算机这样的通用计算机系统不同,嵌入式系统通常执行的是带有特定要求的预先定义的任务。由于嵌入式系统只针对一项特殊的任务,设计人员能够对它进行优化,减小尺寸降低成本。由于嵌入式系统通常进行大量生产。所以单个的成本节约,能够随着产量进行成百上千的放大。
由于个人数码助理(PDA,Personal Digital Assistant)及手持设备在硬件上设计的特性,即使在软件上的扩充性比其他设备来得好,但普遍被认为是嵌入式设备。但是这个定义也逐渐模糊。举例来说,Intel 公司的凌动(ATOM)微处理器原本是为了移动互联网设备(MID,Mobile Internet Device)这一类的嵌入式系统设计的,但是现在更多的被应用于上网本(Netbook),而上网本属于使用Windows或者Linux的个人计算机,因此嵌入式系统的定义又更模糊了。
嵌入式系统的核心是由一个或几个预先编程好以用来执行少数几项任务的微处理器或者单片机组成。与通用计算机能够运行用户选择的软件不同,嵌入式系统上的软件通常是暂时不变的;所以经常称为“固件”。
在计划刚开始的时候,阿波罗导航计算机被认为是阿波罗计划风险最大的部分。为了减小尺寸和重量而使用的当时最新的单片集成电路加大了阿波罗计划的风险。
第一款大批量生产的嵌入式系统是1961年发布的民兵I导弹上的D-17自动导航控制计算机。它是由独立的晶体管逻辑电路建造的,它带有一个作为主内存的硬盘。当民兵II导弹在1966年开始生产的时候,D-17由第一次使用大量集成电路的更新计算机所替代。仅仅这个项目就将与非门集成电路模块的价格从每个1000美元降到低了每个3美元,使集成电路的商用成为可能。
民兵导弹的嵌入式计算机有一个重要的设计特性:它能够在项目后期对制导算法重新编程以获得更高的导弹精度,并且能够使用计算机测试导弹,从而减少测试用电缆和接头的重量。
这些二十世纪六十年代的早期应用,使嵌入式系统得到长足发展,它的价格开始下降,同时处理能力和功能也获得了巨大的提高。英特尔4004是第一款微处理器,它在计算器和其他小型系统中找到了用武之地。但是,它仍然需要外部存储设备和外部支持芯片。1978年,国家工程制造商协会发布了可编程单片机的“标准”,包括几乎所有以计算机为基础的控制器,如单片机,数控设备,以及基于事件的控制器。
随着单片机和微处理器的价格下降,一些消费性产品用使用单片机的数字电路取代如分压计和可变电容这样的昂贵模拟组件成为可能。
到了二十世纪八十年代中期,许多以前是外部系统的组件被集成到了处理器芯片中,这种结构的微处理器得到了更广泛的应用。到了八十年代末期,微处理器已经出现在几乎所有的电子设备中。
集成化的微处理器使得嵌入式系统的应用扩展到传统计算机无法涉足的领域。对多用途和相对低成本的单片机进行编程,往往可成为各种不同功能的组件。虽 然要做到这一点,嵌入式系统比传统的解决方案要复杂,最复杂的是在单片机本身。但是嵌入式系统很少有额外的组件,大部分设计工作是软件部分。而非物质性的 软件不管是创建原型还是测试新修改相对于硬件来说,都要容易很多的,并且设计和建造一个新的电路不会修改嵌入式处理器。
手持系统通常都有一个屏幕和作为定位装置的控制按键。
大部分嵌入式系统通过“维护”或者“测试”接口来提供一个菜单,或者由一个RS-232(串行数据通信的接口标准)接口提供的命令行界面。这样就可以在很少的显示花费的基础上提供大量的控制手段。然而,这也会让大部分消费者无法安装必要的电缆。
这与桌面计算机市场有所不同,至2003年为止在那个领域只有少数几家竞争的架构,其中主要是英特尔/AMDx86和用于Apple Macintosh的Apple/Motorola/IBM PowerPC。在桌面计算机领域,随着对于Java接受程度的增长,软件对于特定运行环境的依赖越来越少。
PC/104标准是小型、小批量嵌入式和ruggedized系统设计的基础。这些系统通常使用DOS、Linux、NetBSD或者如QNX、Inferno这样的实时嵌入式操作系统。
大批量生产的嵌入式系统的通常配置是片上系统(en:System On Chip),它是一个专用集成电路,CPU是外购的知识产权并且添加到集成电路设计中。一个类似的常用机制是使用可编程门阵列,所有的逻辑包括CPU部分都可以编程实现。许多时髦的FPGA都是为这个目的设计的。
软件工具的来源有如下几种:
嵌入式系统设计人员也使用一些不为普通计算机程序员所熟悉的软件工具:
开发人员能够仍然使用断点、单步执行以及高级语言进行调试,在许多的调试工具上都有这种能力。另外开发人员在调试实时事件顺序的时候需要记录、使用简单的记录工具。
首先遇到这种问题的个人电脑和大型机程序员经常在设计优先级和可行方法的时候感到困惑。指导、代码审查和非个人风格(egoless)的编程是值得推荐的。
随着嵌入式系统变得越来越复杂,更高层次的工具和操作系统逐渐移植到可行的设备上。例如,蜂窝电话、个人数字助理和其他的消费用计算机需要一些从个人或者这些电子设备制造商之外的公司购买或者提供的一些重要软件。在这些系统中,需要如Linux、OSGi或者Java这样的开放编程环境,这样第三方软件提供上才能够在大规模的市场上销售软件。
大多数这样的开发环境都有一个运行在个人电脑上 的参考设计,这种软件的绝大部分都可以在传统的个人电脑上开发。然而,从开放环境移植到专用的电子设备和电子设备的驱动程序开发通常仍然是传统的嵌入式系 统软件工程师的工作。在有些情况下, the engineer works for the integrated circuit manufacturer, but there is still such a person somewhere.
许多设计人员发现LED在指示错误状态上非常有用,它们可以帮助进行故障处理。一个常用的机制是在复位的时候点亮电子设备所有的LED以表明供电和LED正常工作;然后在进行加电自检时由软件改变LED的状态;在此之后,软件用这些LED指示操作过程中的正常或者故障状态。这可以让技术人员、工程师和用户了解系统的状态。一个有趣的例外是电度表(electric power meters)和其他一些大街上的东西,闪烁的指示灯是为了吸引注意力或者表示损坏状态。
系统使用简单的API来完成允许和禁止中断设置。如果处理得当的话,它能够在嵌套子程序中处理嵌套调用,在最外面的中断允许嵌套中恢复前面的中断状态。这种方法是实现Exokernel的一个最简单的方法。
通常在循环中有一些子程序使用周期性的实时中断控制一组软件定时器,当一个定时器时间到的时候就会运行相应的子程序或者设置相应的标志。
任何可能发生的硬件事件都应该有软件定时器的支持,硬件事件大概每万亿次出现一次错误,对于现代的硬件来说大概是一年发生一次,对于以百万计大规模生产的设备来说,遗漏一个软件软件定时器在商业上可能是灾难性的。
有时测试软件运行一组基于软件的安全定时器,它们周期性地复位硬件中的软件看门狗。如果软件错过一个事件,安全定时器软件将会捕捉到它。如果安全定时器出错,看门狗硬件将会复位系统。
可以使用指向每个状态机函数的指针实现状态机,函数可以用C++、C或者汇编语言等实现。变化的状态将不同的函数放到指针中,每次循环运行时都会运行函数指针。
许多设计人员建议每个循环读一次输入输出设备、并且保存得到的结果,这样可以保证逻辑过程的在一致的参数上运行。
许多设计人员喜欢将状态机设计成每个状态仅仅检查一到两项内容,通常是检查硬件事件和软件定时器。
设计人员建议多级状态机应该让低层状态机早于高层状态机运行,这样高层就能够根据正确的信息运行。
如内部燃烧控制这样的复杂功能通常根据多维表格进行处理,代码通常进行查表处理而不进行复杂的计算,为了减小表格的大小以及成本软件可以在条目之间进行差值运算。
在最小的单片机中,尤其是只有128位组堆栈的8051中,控制环允许好的连接器使用静态分配的数据覆盖本地变量。在这种机制中,离子程序调用树末端越近的变量得到的存储器地址越高。当开始一个新的分支的时候,它的变量可以在以前分支遗弃的空间中进行重新分配。
简单控制循环的一个主要缺点是它无法保证响应特定硬件事件的时间。
细心的设计可以很容易地保证中断不会被长时间禁止,这样中断代码就可以在非常精确的时间运行。
控制环的另外一个主要缺陷是增加新的特性的时候会变得复杂。需要花费很长时间的算法必须小心地进行分解以使得每次只有一小部分在主循环中运行。
这种系统的优势是它的简单性,并且在很小的软件上,循环运行地很快几乎没有人关心它是不可预测的。
它的另外一个优势是这种系统保证运行软件的质量,无法将不好的运行结果归咎为其他的操作系统。
带有类似属性的架构都带有一个事件队列,有一个循环根据队列列表中的一个域确定删除时间和调用子程序。
这种架构的优点和缺点都非常类似于控制环,只是这种方法添加新的软件更加简单,只需要简单地编写新的任务或者将它添加到队列解释器中。
另外,代码第一次能够在非预期的时间访问自己的数据结构。定时器子程序必须要象中断子程序一样进行处理。
这样系统就突然变得很不一样了。任何一个任务的代码都有可能损害其他任务的数据 &emdash; 所以它们必须进行切缺的切分。对于共享数据的访问必须使用一些同步策略进行控制,如消息队列、信号灯或者非阻塞同步机制。
经常在这一步开发组织就会购买一套实时操作系统。如果一个组织缺少能够编写操作系统的人才或者操作系统将要在几个产品之上,这可能是一个明智的选择。这通常要将开发计划增加六到八周,and forever after programmers can blame delays on it.
微内核是实时操作系统的一个逻辑发展,通常的组织方式是操作系统内核分配内存并且将CPU在不同的线程之间进行切换。用户模式的进程实现如文件系统、用户接口等主要的功能。
微内核在二十世纪五十年代开始首次尝试,但是由于计算机在任务间切换以及在任务间交换数据速度非常缓慢,所以人们放弃了微内核而钟情于MULTICS和UNIX风格的大内核。总体上来说,微内核在任务切换以及任务间通信速度快的时候是比较成功的,在速度慢的时候是失败的。
外内核通过使用普通的子程序调用获得的通信效率很高,硬件以及系统中的软件都是程序员能用也能扩展的。资源内核(可能是库的一部分)分配CPU时 间、内存以及其他资源。如多任务、网络以及文件系统这样的大内核特性通过代码库来提供。库可以进行动态的连接、扩展或者共享。不同的应用甚至可以使用的不 同的库,但是所有的资源都来自于资源内核。
模拟环境的优点就是即使一个计算机出现故障,软件的不同例程能够迁移到正常工作的软件分区,表决的票数并不受影响。
通常虚拟软件运行在计算机的用户模式下,它捕捉、模拟硬件访问和不在用户模式下运行的指令。
由于个人数码助理(PDA,Personal Digital Assistant)及手持设备在硬件上设计的特性,即使在软件上的扩充性比其他设备来得好,但普遍被认为是嵌入式设备。但是这个定义也逐渐模糊。举例来说,Intel 公司的凌动(ATOM)微处理器原本是为了移动互联网设备(MID,Mobile Internet Device)这一类的嵌入式系统设计的,但是现在更多的被应用于上网本(Netbook),而上网本属于使用Windows或者Linux的个人计算机,因此嵌入式系统的定义又更模糊了。
嵌入式系统的核心是由一个或几个预先编程好以用来执行少数几项任务的微处理器或者单片机组成。与通用计算机能够运行用户选择的软件不同,嵌入式系统上的软件通常是暂时不变的;所以经常称为“固件”。
目录
嵌入式系统实例
- 自动柜员机(ATM)
- 航空电子,例如惯性导航系统、飞行控制硬件和软件以及其他飞机和导弹中的集成系统
- 移动电话和电信交换机
- 计算机网络设备,包括路由器、时间服务器和防火墙
- 办公设备,包括打印机、复印机、传真机、多功能打印机(MFPs)
- 磁盘驱动器(软盘驱动器和硬盘驱动器)
- 汽车发动机控制器和防锁死刹车系统
- 家庭自动化产品,如恒温器、冷气机、洒水装置和安全监视系统
- 手持计算器
- 家用电器,包括微波炉、洗衣机、电视机、DVD播放器和录制器
- 医疗设备,如X光机、核磁共振成像仪
- 测试设备,如数字存储示波器、逻辑分析仪、频谱分析仪
- 多功能手表
- 多媒体电器:因特网无线接收机、电视机顶盒、数字卫星接收器
- 个人数码助理(PDA),也就是带有个人信息管理和其他应用程序的小型手持计算机
- 带有其他能力移动电话,如带有蜂窝电话、个人数码助理(PDA)和Java的移动数字助理(MIDP)
- 用于工业自动化和监测的可编程逻辑控制器(PLCs)
- 固定游戏机和便携式游戏机
- 可穿戴计算机
历史
第一个被大家认可的现代嵌入式系统是麻省理工学院仪器研究室的查尔斯•斯塔克•德雷珀开发的阿波罗导航计算机。在两次月球飞行中他们在太空驾驶舱和月球登陆舱都是用了这种惯性导航系统。在计划刚开始的时候,阿波罗导航计算机被认为是阿波罗计划风险最大的部分。为了减小尺寸和重量而使用的当时最新的单片集成电路加大了阿波罗计划的风险。
第一款大批量生产的嵌入式系统是1961年发布的民兵I导弹上的D-17自动导航控制计算机。它是由独立的晶体管逻辑电路建造的,它带有一个作为主内存的硬盘。当民兵II导弹在1966年开始生产的时候,D-17由第一次使用大量集成电路的更新计算机所替代。仅仅这个项目就将与非门集成电路模块的价格从每个1000美元降到低了每个3美元,使集成电路的商用成为可能。
民兵导弹的嵌入式计算机有一个重要的设计特性:它能够在项目后期对制导算法重新编程以获得更高的导弹精度,并且能够使用计算机测试导弹,从而减少测试用电缆和接头的重量。
这些二十世纪六十年代的早期应用,使嵌入式系统得到长足发展,它的价格开始下降,同时处理能力和功能也获得了巨大的提高。英特尔4004是第一款微处理器,它在计算器和其他小型系统中找到了用武之地。但是,它仍然需要外部存储设备和外部支持芯片。1978年,国家工程制造商协会发布了可编程单片机的“标准”,包括几乎所有以计算机为基础的控制器,如单片机,数控设备,以及基于事件的控制器。
随着单片机和微处理器的价格下降,一些消费性产品用使用单片机的数字电路取代如分压计和可变电容这样的昂贵模拟组件成为可能。
到了二十世纪八十年代中期,许多以前是外部系统的组件被集成到了处理器芯片中,这种结构的微处理器得到了更广泛的应用。到了八十年代末期,微处理器已经出现在几乎所有的电子设备中。
集成化的微处理器使得嵌入式系统的应用扩展到传统计算机无法涉足的领域。对多用途和相对低成本的单片机进行编程,往往可成为各种不同功能的组件。虽 然要做到这一点,嵌入式系统比传统的解决方案要复杂,最复杂的是在单片机本身。但是嵌入式系统很少有额外的组件,大部分设计工作是软件部分。而非物质性的 软件不管是创建原型还是测试新修改相对于硬件来说,都要容易很多的,并且设计和建造一个新的电路不会修改嵌入式处理器。
特性
- 嵌入式系统在广义上说就是计算机系统, 它包括除了以通用为目的计算机之外的所有计算机。从便携式音乐播放器到航天飞机的实时控制子系统都能见到嵌入式系统的应用。与通用计算机系统可以满足多种 任务不同,嵌入式系统只能完成某些特定目的的任务。但有些也有实时性能的制约因素必须得到满足的原因,如安全性和可用性。除此之外其他功能可能要求较低或 没有要求,使系统的硬件得以简化,以降低成本。对于大批量生产的系统来说,降低成本通常是设计的首要考虑。嵌入式系统通常需要简化去除不需要的功能以降低 成本,设计师通常选择刚刚满足所需功能的硬件使目标最小化低成本的实现。
- 嵌入式系统并非总是独立的设备。许多嵌入式系统是以一个部件存在于一个较大的设备,它为设备提供更多的功能,使设备能完成更广泛的任务。例如,吉布森吉他机器人采用了嵌入式系统来调弦,但总的来说吉布森吉他机器人设计的目的绝不是调弦而是演奏音乐。同样的,车载电脑作为汽车的一个子系统,为它提供了导航,控制,车况反馈等功能。
- 部分为嵌入式系统编写的程序被称为固件,他们存储在只读存储器或闪存芯片。他们运行在资源有限的计算机硬件:小内存,没有键盘,甚至没有屏幕。
用户界面
嵌入式系统用户界面包括了从没有用户界面,专注于单一任务到现在的类似于现代桌面操作系统的复杂图形用户界面的各类界面。简单的嵌入式系统
简单的嵌入式设备往往由按钮,发光二极管(LEDs)和仅仅能显示小字符或数字的显示器,以及简单的菜单系统组成。较为复杂的嵌入式系统
较为复杂的嵌入式系统拥有的完整的图形屏幕、触摸感应或屏幕边缘按钮在最大限度地使用空间的同时,提供了足够的灵活性:指点控制是很自然的非常理想的操控方式,这样的方式可以改变屏幕的意义。手持系统通常都有一个屏幕和作为定位装置的控制按键。
大部分嵌入式系统通过“维护”或者“测试”接口来提供一个菜单,或者由一个RS-232(串行数据通信的接口标准)接口提供的命令行界面。这样就可以在很少的显示花费的基础上提供大量的控制手段。然而,这也会让大部分消费者无法安装必要的电缆。
CPU平台
在嵌入式系统设计中有许多不同的CPU架构,如ARM、MIPS、Coldfire/68k、PowerPC、X86、PIC、Intel 8051、Atmel AVR、Renesas H8、SH、V850、FR-V、M32R、DMCU等。这与桌面计算机市场有所不同,至2003年为止在那个领域只有少数几家竞争的架构,其中主要是英特尔/AMDx86和用于Apple Macintosh的Apple/Motorola/IBM PowerPC。在桌面计算机领域,随着对于Java接受程度的增长,软件对于特定运行环境的依赖越来越少。
PC/104标准是小型、小批量嵌入式和ruggedized系统设计的基础。这些系统通常使用DOS、Linux、NetBSD或者如QNX、Inferno这样的实时嵌入式操作系统。
大批量生产的嵌入式系统的通常配置是片上系统(en:System On Chip),它是一个专用集成电路,CPU是外购的知识产权并且添加到集成电路设计中。一个类似的常用机制是使用可编程门阵列,所有的逻辑包括CPU部分都可以编程实现。许多时髦的FPGA都是为这个目的设计的。
工具
同典型的计算机程序员一样,嵌入式系统设计人员也使用编译器、连结器和调试器开发嵌入式系统软件。然而,他们也使用一些大多数程序员不熟悉的工具。软件工具的来源有如下几种:
嵌入式系统设计人员也使用一些不为普通计算机程序员所熟悉的软件工具:
- 一个常用工具是“电路内部仿真器”(ICE,in-circuit emulator)或者是最新设计中的嵌入式调试器。这个调试工具是开发嵌入式程序的基本技巧。它代替微处理器或者嵌入微处理器内部,提供了在系统中快速 调用和调试试验代码的便捷工具。一个焊点通常就是一个插入系统的特殊电路,通常使用一台连结到这些焊点的个人计算机作为调试界面。
- 连结器通常是各种各样(exotic)。对于大多数商业编程来说,连接器几乎总是最后才想起的(afterthough) 部分,缺省设置也从来不变。与此相反,嵌入式连结器有完整、复杂的命令行语言是很普通的。经常有不同类型的内存,分别保存特殊的代码和数据。单独的数据结 构能够放在特殊的地址,这样软件能够很方便地访问映射到内存的控制寄存器。嵌入式连结器经常有用于减小代码大小和运行时间的外部(exotic)优化工具。例如,他们可能移动子程序的位置以使用较小的调用和跳转指令。它们经常带有管理data overlays和band switch技术的特性,这些技术是在嵌入式软件经常使用的扩展廉价CPU的方法。
- 另外一个常用的工具是一个在程序中添加代码和或者CRC的工具程序(经常是自己写的),使用这个工具嵌入式系统能够在执行程序之前先进行程序数据检查。
- 为数字信号处理开发软件的嵌入式程序员经常使用MathCad或者Mathematica这样的数学工具进行数学仿真。
- 一些较少使用的工具有将数据文件转换成代码的工具,使用这种工具就可以在程序中包含任意类型的数据。
- 少数一些项目为了特殊的可靠性或者数字信号处理要求使用同步编程语言。
- 对于C语言,ISO/IEC TR 18037:2005定义了
- 指定的地址空间
- 指定的存储类
- 基本输入输出的硬件寻址
调试
调试通常使用内部电路仿真器或者其他一些能够在单片机微码(microcode)内部产生中断的调试器。微码中断让调试器能够在只有CPU工作的硬件中进行操作,基于CPU的调试器能够从CPU的角度来测试和调试计算机的电路。PDP-11开创了这种特性的先河。开发人员能够仍然使用断点、单步执行以及高级语言进行调试,在许多的调试工具上都有这种能力。另外开发人员在调试实时事件顺序的时候需要记录、使用简单的记录工具。
首先遇到这种问题的个人电脑和大型机程序员经常在设计优先级和可行方法的时候感到困惑。指导、代码审查和非个人风格(egoless)的编程是值得推荐的。
随着嵌入式系统变得越来越复杂,更高层次的工具和操作系统逐渐移植到可行的设备上。例如,蜂窝电话、个人数字助理和其他的消费用计算机需要一些从个人或者这些电子设备制造商之外的公司购买或者提供的一些重要软件。在这些系统中,需要如Linux、OSGi或者Java这样的开放编程环境,这样第三方软件提供上才能够在大规模的市场上销售软件。
大多数这样的开发环境都有一个运行在个人电脑上 的参考设计,这种软件的绝大部分都可以在传统的个人电脑上开发。然而,从开放环境移植到专用的电子设备和电子设备的驱动程序开发通常仍然是传统的嵌入式系 统软件工程师的工作。在有些情况下, the engineer works for the integrated circuit manufacturer, but there is still such a person somewhere.
操作系统
嵌入式系统经常没有操作系统、专用的嵌入式操作系统(经常是实时操作系统)或者指定程序员移植到这些新系统。启动
嵌入式系统带有启动代码,通常它禁止中断、设置电子设备参数、测试计算机(RAM、CPU和软件),然后开始应用程序运行。许多嵌入式系统从短暂的掉电状态恢复,经常重起而不进行最近的自检。在十分之一秒内重起是常见的现象。许多设计人员发现LED在指示错误状态上非常有用,它们可以帮助进行故障处理。一个常用的机制是在复位的时候点亮电子设备所有的LED以表明供电和LED正常工作;然后在进行加电自检时由软件改变LED的状态;在此之后,软件用这些LED指示操作过程中的正常或者故障状态。这可以让技术人员、工程师和用户了解系统的状态。一个有趣的例外是电度表(electric power meters)和其他一些大街上的东西,闪烁的指示灯是为了吸引注意力或者表示损坏状态。
内部自检
许多嵌入式系统都有一定程度或者一定数量的内部加电自检,自检有几种类型:- 计算机检查:检查CPU、RAM和程序存储器。通常一加电就开始这些检查,在一些安全性非常重要的系统中,通常周期性地在安全时间间隔内进行自检,或者经过一段时间就进行自检。
- 外围设备检查:仿真输入和读入数据或者测量输出数据。有大量的通信、模拟和控制系统都有这些非常廉价的检查。
- 电源检查:通常测试每个供电电路,也可能检查电池或者主电源输入。通常供电部分的负载都很重,并且少有余量,所以这项检查很有意义。
- 通信检查:验证从相连单元接收到的简单消息,例如在互联网上使用ICMP消息“ping”。
- 电缆检查:将线连结到待检查的电缆上指示针进行检查。如电话这样的同步通信系统经常使用“同步”测试。电缆检查成本很低,当单元部分有插头的时候这项检查尤其重要。
- 装备检查:一个系统在安装时经常需要进行调整,这项检查就向安装人员做出状态指示。
- 消耗检查:检查系统所消耗的东西、在预量太低时发出警告。最常见的例子是汽车的油量表,最复杂的例子可能是维持化学反应物详细状态的自动医学分析系统。
- 运行检查:检查用户关心的系统运行状态。显然,在系统运行时必须进行这项检查,这方面的检查包括飞机上的导航仪器、汽车的速度表和磁盘的指示灯等。
- 安全检查:在'安全时限'内进行检查确保系统仍然可靠。安全时限通常小于能够产生损害的最小时间。
可靠性体系
根据人们需求的不同,可靠性也有不同的定义,有意思的事,可靠性的类型却相对较少,相似可靠性类型的系统,使用相似类型的内在检查和恢复方法:- 系统非常不安全或者无法修理。这包括太空系统、水下电缆、导航灯塔、钻孔系统,非常奇怪的是还包括汽车和大规模生产产品。总的来说,嵌入式系统检 测各个子系统、在线切换到冗余部分或者工作在“limp 模式”提供部分的功能。大规模生产的消费产品如汽车、个人电脑或者打印机也属于这个类别,这是因为与购买的费用相比维修费用高昂、维修人员又路途遥远。
- 系统不能安全地停止运行。这包括飞机导航、反应控制系统、重要的化学工厂安全控制、铁路信号、单发动机飞机的发动机,如上所述,但是“limp 模式”较难容忍,通常需要操作员选择备份系统。
- 系统停机时将会造成大量的金钱损失。这些包括电话交换机、工厂控制、桥梁和电梯控制、资金转移、市场开发、自动销售和服务等,这些系统通常有一些运转/不运转测试,它们通常带有在线冗余或者使用替换系统和人工过程的 limp 模式。
- 系统不安全的时候不能操作。同上面的情况类似,系统的运行将会造成大量的金钱损失。医疗设备、带有发动机这样的热备份的飞行器、化学工厂控制、自动股票交易、游戏系统等。测试可能是五花八门,但是出错时能够做的就是停止整个系统。
嵌入式软件架构的类型
常用的嵌入式软件架构有几种不同的基本类型。控制循环
在这种设计中,软件有一个简单的循环,这个循环调用各个子程序,每个子程序管理硬件或者软件的某一部分。中断通常用来设置标记或者更新软件其他部分能够读取的暂存器。系统使用简单的API来完成允许和禁止中断设置。如果处理得当的话,它能够在嵌套子程序中处理嵌套调用,在最外面的中断允许嵌套中恢复前面的中断状态。这种方法是实现Exokernel的一个最简单的方法。
通常在循环中有一些子程序使用周期性的实时中断控制一组软件定时器,当一个定时器时间到的时候就会运行相应的子程序或者设置相应的标志。
任何可能发生的硬件事件都应该有软件定时器的支持,硬件事件大概每万亿次出现一次错误,对于现代的硬件来说大概是一年发生一次,对于以百万计大规模生产的设备来说,遗漏一个软件软件定时器在商业上可能是灾难性的。
有时测试软件运行一组基于软件的安全定时器,它们周期性地复位硬件中的软件看门狗。如果软件错过一个事件,安全定时器软件将会捕捉到它。如果安全定时器出错,看门狗硬件将会复位系统。
可以使用指向每个状态机函数的指针实现状态机,函数可以用C++、C或者汇编语言等实现。变化的状态将不同的函数放到指针中,每次循环运行时都会运行函数指针。
许多设计人员建议每个循环读一次输入输出设备、并且保存得到的结果,这样可以保证逻辑过程的在一致的参数上运行。
许多设计人员喜欢将状态机设计成每个状态仅仅检查一到两项内容,通常是检查硬件事件和软件定时器。
设计人员建议多级状态机应该让低层状态机早于高层状态机运行,这样高层就能够根据正确的信息运行。
如内部燃烧控制这样的复杂功能通常根据多维表格进行处理,代码通常进行查表处理而不进行复杂的计算,为了减小表格的大小以及成本软件可以在条目之间进行差值运算。
在最小的单片机中,尤其是只有128位组堆栈的8051中,控制环允许好的连接器使用静态分配的数据覆盖本地变量。在这种机制中,离子程序调用树末端越近的变量得到的存储器地址越高。当开始一个新的分支的时候,它的变量可以在以前分支遗弃的空间中进行重新分配。
简单控制循环的一个主要缺点是它无法保证响应特定硬件事件的时间。
细心的设计可以很容易地保证中断不会被长时间禁止,这样中断代码就可以在非常精确的时间运行。
控制环的另外一个主要缺陷是增加新的特性的时候会变得复杂。需要花费很长时间的算法必须小心地进行分解以使得每次只有一小部分在主循环中运行。
这种系统的优势是它的简单性,并且在很小的软件上,循环运行地很快几乎没有人关心它是不可预测的。
它的另外一个优势是这种系统保证运行软件的质量,无法将不好的运行结果归咎为其他的操作系统。
非抢先式任务
非抢先式任务系统非常类似于上面的系统,只是这个循环是隐藏在API中的。我们定义一系列的任务,每个任务获得自己的子程序栈;然后,当一个任务空闲的时候,它调用一个空闲子程序(通常调用“暂停”、“等候”、“交出(yield)”等等)。带有类似属性的架构都带有一个事件队列,有一个循环根据队列列表中的一个域确定删除时间和调用子程序。
这种架构的优点和缺点都非常类似于控制环,只是这种方法添加新的软件更加简单,只需要简单地编写新的任务或者将它添加到队列解释器中。
抢先式定时器
使用上面的任何一种系统,但是添加一个按照定时器中断运行子程序的定时器系统,这样就给系统添加了崭新的能力,这样定时器子程序第一次能在一个有保证的时间内运行。另外,代码第一次能够在非预期的时间访问自己的数据结构。定时器子程序必须要象中断子程序一样进行处理。
抢先式任务
使用上面的非抢先式任务系统,从一个抢先式定时器或者其他中断运行。这样系统就突然变得很不一样了。任何一个任务的代码都有可能损害其他任务的数据 &emdash; 所以它们必须进行切缺的切分。对于共享数据的访问必须使用一些同步策略进行控制,如消息队列、信号灯或者非阻塞同步机制。
经常在这一步开发组织就会购买一套实时操作系统。如果一个组织缺少能够编写操作系统的人才或者操作系统将要在几个产品之上,这可能是一个明智的选择。这通常要将开发计划增加六到八周,and forever after programmers can blame delays on it.
微内核与外内核
这种方法试图将系统组织得比宏内核更易于配置,而同时提供类似的特点。微内核是实时操作系统的一个逻辑发展,通常的组织方式是操作系统内核分配内存并且将CPU在不同的线程之间进行切换。用户模式的进程实现如文件系统、用户接口等主要的功能。
微内核在二十世纪五十年代开始首次尝试,但是由于计算机在任务间切换以及在任务间交换数据速度非常缓慢,所以人们放弃了微内核而钟情于MULTICS和UNIX风格的大内核。总体上来说,微内核在任务切换以及任务间通信速度快的时候是比较成功的,在速度慢的时候是失败的。
外内核通过使用普通的子程序调用获得的通信效率很高,硬件以及系统中的软件都是程序员能用也能扩展的。资源内核(可能是库的一部分)分配CPU时 间、内存以及其他资源。如多任务、网络以及文件系统这样的大内核特性通过代码库来提供。库可以进行动态的连接、扩展或者共享。不同的应用甚至可以使用的不 同的库,但是所有的资源都来自于资源内核。
虚拟机
一些航空电子系统使用几个商用计算机。这样更进一步,每个计算机都在模拟它们自身的几个副本,重要的程序同时在几个计算机上运行并且进行投票控制(vote)。模拟环境的优点就是即使一个计算机出现故障,软件的不同例程能够迁移到正常工作的软件分区,表决的票数并不受影响。
通常虚拟软件运行在计算机的用户模式下,它捕捉、模拟硬件访问和不在用户模式下运行的指令。
检查点计算
另外一种常用的机制是两个计算机计算 for a bit,然后将它们的计算结果报到那个点上。如果一个计算机的计算是 nut,它就会被关闭。办公用(宏内核)操作系统
这种系统通常在没有系统经费的嵌入式项目中流行,但是从这篇文章的多个作者来看,这通常是不正确的,它们的逻辑是:- 操作系统是经过特殊封装的重用代码库。如果这些代码有用,设计人员就会节省时间和金钱,否则它们就是无用的。
- 商务系统的操作系统没有嵌入式硬件的接口。例如,如果要用Linux写一个马达控制器或者电话交换机,绝大部分的实际控制操作都是IOCTL调用,同时,正常的读、写和查询界面都是无用的。所以操作系统对于实际的开发妨碍很大。
- 大多数的嵌入式系统不处理办公事务,所以办公操作系统的大部分代码都被浪费了。例如,绝大多数的嵌入式系统从来都不使用文件系统或者屏幕,所以文件系统和图形用户界面部分就是浪费的,这些不用的代码只会影响系统的可靠性。
- 办公用操作系统保护硬件不让用户程序操作,这就严重地妨碍了嵌入式开发工作。
- 操作系统必须移植到嵌入式系统上,也就是说,硬件驱动程序无论如何都必须重写,这也是操作系统最难的部分,所以使用这样的操作系统几乎没有功效。
- 操作系统真正有用、可移植的特性是小段代码。例如,一个基本的TCP/IP接 口大约有3000行代码,另外的一个例子是大约同样大小的简单文件系统。如果设计需要这些代码,能够使用少于嵌入式系统开发10%的经费就能完成,不需要 支付版权费用,只需要简单地重写就可以了。如果系统这些代码有足够的通用性,嵌入式系统杂志封面的后面通常有公司销售没有版权费的C语言实现代码。
- 有现成的移植到普通嵌入式芯片的实现代码。
- 它们允许重用公开获得的设备驱动程序、网页服务器、防火墙或者其他代码。
- 开发系统能够从许多特性组合开始,在发布的时候可以剔除不需要的功能,从而节约所消耗的内存。
- 许多任务程师认为在用户模式运行应用程序更为可靠、更容易调试,所以开发过程更容易、代码更易于移植。
- 许多嵌入式系统没有控制系统那样对于实时性的严格要求,对于许多应用来说如嵌入式Linux这样的系统的响应速度就已经足够了。
- 要求更快的响应速度,而不是可靠性的特性,通常放到了硬件上。
- 许多实时操作系统都针对每件产品收取费用,当产品是消费品时,这项费用是巨大的。
Exotic custom 操作系统
一些系统需要安全、及时、可靠或者高效的特性,上面的架构却无法达到,构建这样的系统有一些广为人知的技巧:- 雇佣一个真正的系统程序员。他们的花费很小,但是能够节约数年的调试以及相关的收入损失。
- RMA (rate monotonic analysis),可以用来评估一组任务能否在特定的硬件系统下运行,在最简单的形式下,设计人员保证最快完成的任务有最高的优先级,平均来说 CPU 至少有 30% 的空闲时间。
- 和谐的任务能够高效地优化CPU。基本上来说,设计人员保证每件工作都是从heartbeat timer开始工作的。在实时操作系统上很难这样做,因为它们在等候输入输出设备的时候通常就会切换任务。
- 刚好有两个优先级(通常是运行和禁止中断)的系统不能出现高优先级任务等候低优先级任务释放信号灯或者其他资源的优先级倒置问题,
- 有监视器(monitor)的系统不能出现死锁。监视器锁住一段代码禁止中断和其他抢先任务。如果这个监视器只用于一小段快速运行的代码,系统可能工作正常。如果能够证明监视器 API 在所有情况下都能够完整运行,例如仅仅禁止中断,那么就不会产生系统挂起的情况。
Comments
Post a Comment
https://gengwg.blogspot.com/