如果说嵌入式系统的面向对象分析与设计涉及到抽象、思考和经验的话,那么嵌入式系统的实现则涉及更多的实施细节。无论使用咋样前言的技术方法,最终都需要把整个系统包括软件的、机械的和电子的部分聚合成一个满足应用需求的整体。
嵌入式系统最终是要在特定的硬件上运行。在系统分析阶段,只考虑系统要完成哪些功能而不考虑系统的具体实现,因此分析的结果自然是建立在嵌入式系统软硬件基础上的。而在设计阶段就要进行软硬件的具体分工,并且在软件方面的任何结构和行为设计都要考虑到硬件的具体实现能力。在硬件设计时,首先是要考虑实现系统功能的实际需要,然后再考虑如体积、尺寸、功耗等性能问题。
嵌入式系统设计的主要挑战或许就在于如何使相互竞争的设计指标同时达到最佳化。从过去到现在,大多数工程师或擅长软件设计,或擅长硬件设计,但还较少两者都擅长,软件子系统和硬件子系统往往要分别进行设计,直到整个设计流程的末期再进行系统继承。这种早期永久性的软硬件分离显然难以做到设计指标的最优化。
在理论上,如果在设计过程的任何阶段都能选择用硬件或软件来实现功能,就可以提供更好的最佳化系统。目前,可编程硬件技术(如PLD、FPGA、SOPC)的成熟是的软硬件设计流程统一的观点得到支持。现在,综合工具以及把硬件设计者的基本任务转变成顺序程序,当然他们任然需要了解硬件使如何有这些程序综合而来的。这样,硬件和软件的起点都是顺序程序,强化了系统功能可以用硬件、软件或二者的某种组合来实现的观点。因此可以说:对于某个特定的功能而言,选择硬件还是软件实现只是在不同设计指标之间进行取舍,这些指标包括性能、功率、灵活性、体积大小、一次性开发成本、每单位产品成本等,这种设计实现嵌入式系统的观点就称为软硬件协同设计。
就目前的硬件技术发展和国内的实际情况,完全采用可编程硬件技术设计和实现嵌入式系统还不现实。目前采用前两周方案设计实现嵌入式系统更为常见。即使使采用前两种方案,也同样存在软硬件协同设计的问题,只是硬件的取舍不如第三种方案灵活而已。
下面的讨论主要针对前两种方案实现系统的情况。
在采用面向对象嵌入式系统开发时,分析模型使独立于实现的。分析模型只针对系统领域概念和系统功能,模型中只表示出需要实现功能所应具备的逻辑结构。在设计阶段要根据分析模型首先划分硬件实现的功能和软件实现的功能,及确定硬件体系结构和软件体系结构,以及软硬件之间的接口。
目前,由于存在着各类学习开发装置(如学习板、开发板、开发平台等),并且这类开发平台具有较好的可扩展性,完全可以在开发平台上完成软件系统的开发,最后确定系统所需要的硬件。
当嵌入式系统的硬件子系统确立以后,其硬件实现通常是独立进行的。如果使用开发平台开发嵌入式软件,软件实现和硬件实现两者可以独立进行。
处理器的选择通常取决于技术和非技术两方面因素。从技术角度看,必须选择在功率、大小和成本约束下,能达到所需处理速度的微处理器‘非技术方面因素有开发环境、对处理器的熟悉程度、授权等等。
嵌入式外围级接口电路是指在一个嵌入式系统硬件构成中,除了核心控制部件(即嵌入式微处理器)以外的各种存储器、输入/输出接口、人机接口的显示/键盘、串行通信接口等等。
存储器是嵌入式系统中存储数据和程序的功能部件。
静态存储其驱动电路简单且速度块,而动态存储器由于需要定时刷新而是的驱动电路变得相对复杂,但这类存储器单位面积上存储容量大。他们在嵌入式系统中主要用来存储运行时的对象,如活动的任务程序、数据结构、变量等。
非易失线程存储器主要用来存放程序或静态数据,在这类存储器中存放的内容可以直接在其所在的地址空间中运行,也可以运行前装入到RAM中,而在RAM中运行其代码。这类存储器主要存放系统初始配置程序、系统启动程序bootloader、固化运行的任务程序和各类查找表等。
非易失非线性存储器通常也称为外存,这主要是由于存在这类存储器中的数据不同直接通过微处理器运行。这类存储器在嵌入式系统中主要来存储需要运行时加载的程序、运行时需要加载和处理的数据、系统运行时得到的大量数据等。
目前在通用计算器中所有的通信接口在嵌入式系统领域中都有广泛的应用,其中包括同步串口、RS-232C接口、通用串行总线USB接口、红外先IrDA接口、串行外围设备接口SPI、I2C控制总线接口、I2S音频总线接口、CAN总线接口、无线蓝牙接口、以太网接口、IEEE1394和JTAG接口等。
一般系统开发调试期间,通过在主机运行的调试器上输入控制命令,再通过UART或JTAG接口连接到目标机上的调试代理来完成系统的各项调试功能。以太网以及称为嵌入式系统较为常见的网络接口。USBj接口和IEEE1394接口普遍用来作为数据线数字设备同嵌入式计算机数据传输的接口,如数码照相机、数码摄像机等。再无线数据传输中,常见的由IEEE802.11系列无线网络传输接口、蓝牙接口以及红外接口等。
简单的输入设备可能只有一个开关或按钮,而复杂的输入设备可以是专用键盘、扫描仪等。简单的输出设备可能只有一只或几只发光二极管,而复杂的输出设备可能是一个长款数米的超大屏幕。
嵌入式系统的输入/输出设备的选择要根据实际需要,再面向对象的开发中,可以把输入设备和输出设备进行分类并定义成统一的描述接口,再分析和设计中按组件或不见得方式使用,而在实现时再替代从最终也需要的设备。
由于目前的嵌入式系统功能越来越复杂,所处理的数据量也非常庞大,因此这种系统就需要有很大的存储容量。
个人计算机存储卡国际协会PCMCIA是为了开发出低功耗、小体积、高扩展性的一个卡片型工业存储标准扩展所设立的协会,它负责对广泛使用的存储卡和输入/输出卡的外形规范、电气特性、信号定义进行管理。根据这些规范和定义而生产出来的外形如信用卡大小的产品叫做PCMICA卡,也称为PC-Card。按照卡的介质分为Flash、SRAM、I/O卡和硬盘卡。
电源设计也是嵌入式系统硬件设计的一个重要环节。从系统的保险性方面考虑,电源设计的缺陷是产生系统干扰的绝大部分原因;从功耗方面考虑,电源是各类手持系统的主要设计指标;从重要和体积上考虑,电源可能是系统重要的主要来源。因此,目前有关嵌入式系统电源提供方式、电源电压、各类省电模式等已成为电源设计的重要设计指标。
嵌入式系统尤其是手持式系统力求外观小型化,质量轻以及电源使用寿命长,例如手机或PDA。在便携式嵌入式系统的应用中,功耗和电源装置等辅助设备是必须要考虑的。
当确立了系统中要使用的外围电路及输入/输出接口电路和外部设备以后,就要通过硬件原理图把所有部件连接起来。在部件连接的过程中需要注意相互连接的部件的电气特性一定要正确。例如,图7.2中部件A的输出逻辑电平位0~3V,高电平输出电流位0.4mA,如B的输入高电平需要保证在4V以上(如CMOS器件),或保证输入高电平电流在5mA,(如发光二极管),这是虽然两端逻辑关系正确,但电气关系不匹配,这时就要在两者这件加入一个驱动元器件,或改变电路逻辑才有可能使系统正常工作。
有时即使逻辑和电气关系都正确,在通信连接中时序和协议关系不对也是不能达到连接目的的。在硬件连接层面,考虑的是最基本二时序和协议关系,如同步还是异步,输出波特率与输入波特率是否有共同的窗口等,而对于更高一层的链路关系,则是有基本软件链路协议保证的。
电路原理图绘制工具通常采用专用电路辅组设计软件(如protel或tangl等)。原理图的建立一般要保护哦设置原理图设计环境、放置元件、原理图布线,编译与调整元件属性、检查原理图、生成网络表和打印输出原理图几个步骤。
当系统硬件原理图设计完成以后,最终还要把所选定的电路元器件以其物理存在方式固定在印刷电路板PCB上。
电路原理图到PCB图的转化过程可以有人工布线和自动布线两种方式。
一般电路辅组开发工具都具备仿真功能。较好的工具甚至还可以对电路进行瞬态分析、噪声分析等动态特征的分析验证。
电路板图设计好后,一般要交由专业电路板制造商完成电路板的制作工作。当制作好的电路板拿回以后,就可以按照最初的设计往电路板上组装元器件。元器件的焊接,尤其是对密间距表面安装部件的焊接,可以通过专业焊接工具或到专业从事焊接的商业组织进行。对于试验阶段制品或间距较大的元器件也可以自行焊接,但一般焊接技术要求较高,初学者使很难达到要求的。
在调试的初级阶段一般要进行单个元器件的行为功能确认。一般要经过加电观察,通过简单的测试程序发送需要的测试向量,并通过适当的手段(示波器、逻辑分析仪、各类显示或声音输出等)观察输出。
硬件系统调试时应最先调试输出或显示部分。因为当一个系统输出不能正常工作时,系统就真的是一个“黑匣子”了。
电路板测试一般要针对具体电路逻辑编制测试程序。在编制测试程序时要注意到硬件运行的所有情况,一般来说测试程序所能运行的硬件电路功能要大于系统运行时所实际使用的功能。另外测试部件的工作性能指标返回也通常大于实际使用的范围,如某一UART部件测试的工作频率范围可能时0.3~115.2kbps,而实际使用中仅使用19.2kbps一个点。
硬件电路板测试程序时系统硬件驱动程序的基础。
从操作系统的视角看待对系统硬件功能的操作,就称邻接操作系统并能驱动硬件的程序为硬件设备驱动程序。要实现微处理器与外设的通信,应用程序要通过操作系统将具体的I/O任务下达给外设,外设要将其完成任务情况报告给调用该驱动的操作系统,再由操作报告给应用程序。
设备驱动程序的确立,使得为应用程序提供统一使用的外设界面而不必考虑外设输入/输出的实现细节成为可能,因而构成了层次式系统结构。对于中小型操作系统(如uc/os),通常采用开放式分层体系结构,即应用程序和操作系统可以不受限制地访问硬件设备甚至是直接操作I/O地址。
嵌入式系统中硬件设备驱动程序的所属是模糊的,他们既可以属于操作系统,如在具有大型操作系统的应用中,也可以不属于操作系统,如在小型操作系统甚至没有操作系统的应用中。通常可以把介于硬件和操作系统之间的这一部分称为硬件抽象层HAL。
 由于嵌入式系统中所使用的硬件通常都只针对特定应用而选择的,因此极少存在标准驱动程序的情况。
固件是底层的嵌入式软件,它提供硬件和应用程序/操作系统层软件之间的接口。固件存储在ROM里,嵌入式硬件系统一上点就立即执行。在完成系统初始化以后,固件可以继续保持活动状态,以提供某些基本的系统操作支持。固件的一个基本作用是提供一个启动程序,启动程序是一个用来引导操作系统或应用程序到硬件目标平台上的小应用程序,他在操作系统或应用程序执行后便立即退出。
嵌入式系统的软件在逻辑上是层次的。在对待设备驱动的问题上可以有封闭式分层设备驱动和开放式分层设备驱动两种。
封闭式分层设备驱动通常把设备驱动程序看成是内核的一部分。但由于设备种类繁多,相应地,设备驱动程序的代码也就会数量庞大。而且开发人员也比较杂乱。因此,SVR4提出了设备-驱动程序接口/设备驱动程序-讷河解耦DDI/DKI规范。
开放式分层设备驱动,它主要是不把硬件驱动程序看成是操作系统的一部分。操作系统仅提供内核任务调度和必要的系统服务(如信号量、任务见通信等),在操作系统需要硬件设备支持时,仅提供函数编写规范或要求(如us/os-ii要求函数具有可重入性)。这时把硬件设备驱动程序统一安排在HAL层中,而HAL层实际上是作为独立于操作系统层而独立存在的。
由于嵌入式操作系统不能像通用操作系统那样在标准的资源上安装,因此在实际用用他们到一个具体的目标系统上式需要进行移植。所谓移植,就是要针对特定的微处理器开发一些底层的,尤其是与微处理器内部及短期操作相关的部分代码。按照面向对象的观点,实时操作系统仅是嵌入式系统软件的一个组件,而其他的附加功能部件则是一些可选的组件。如图7.3所示。
这里仅以uC/OS-II一直到ARM微处理器为例来说明实时操作系统在特定应用系统中的应用原理。
大部分代码使用C语言编写的,但在把它具体应用到某种微处理器为核心的目标机上时,仍然需要用C语言和汇编语言编写一些与处理器相关的代码。这首先时因为uC/OS-II的事先并不知道所使用的微处理器内部寄存器的位数和数量,并且C语言不具备直接操作CPU寄存器的能力。因此它没有办法把这些寄存器压入堆栈或从堆栈取出再还原给他们,而这些也恰恰是操作系统进行任务调度和终端管理的必须的操作。
OS_CPU.H文件中。需要做的事情如下
应该编写一个简单的多任务应用程序,按照uC/OS-II的main()函数结构要求建立这些简单的任务。当简单的多任务程序运行成功时,才能证明移植工作的完成。以后的编码主要时应用程序的编码和确立如何使用uC/OS-II中的相关函数建立多任务之间的通信或同步关系。
在进入实际开发程序之前,要先建立交叉开发环境。
按照发布的形式,交叉开发环境主要分为开放和商用两种。开放式如gcc,商用如Arm Developer Suite.
按照使用方式,主要分为使用Makefile和集成开发环境IDE两种。
对开发环境有了必要的了解后,就可以根据要开发的目标配置开发环境并建立项目。
当嵌入式系统升级时,要考虑到跨平台问题,因为升级到目标系统的微处理器经常会与原来的系统不同。这属于软件复用,这时面向对象技术的基本优点之一。关于增加可移植性的方法,如尽量使用高级语言,把需要改变的部分集中到一起,采用面向对象技术等。
一个具有一定规模的嵌入式项目程序往往时多模块的源程序。另外,每个模块的开发语言也是不同的,开发时要注意模块之间的接口定义和相互调用连接关系。
&emsp:启动代码、硬件初始化代码通常要用汇编语言编写。因为这样可以发挥汇编语言短小精悍的优势,可以提高代码的执行效率。
编译器的重要工作时将用高级语言编写的源代码翻译成在特定类型微处理器上的可执行代码。编译器通常只针对一个源程序文件进行语法检查和翻译。因此在一个模块中调用其他模块的函数,使用其他模块的数据结构和全局变量之前都必须声明。
通常目标代码是不能执行的,不过可以通过目标代码体哦那个有用信息转化成可执行代码。现在的目标代码通常有两类:COFF与ELF.有了标准的目标文件格式,不同的开发商提供的开发工具就可以实现相互连接和操作。
汇编器的任务是将符号级的汇编语言翻译成称为目标代码的指令位级表示。汇编完成汇编语言到二进制代码的转换。汇编过程通常要经过两次扫描过程。在第一次扫描中,使用程序位置计数器(PLC)检查每一条指令的位置,扫描整个模块程序并标记每个标号的PLC的值。在第二次扫描中,把所有汇编代码中的相对地址加入到指令的相对偏移量位域。
链接器通常包括定位器。链接器是用来将不同的模块连接成目标文件;定位器允许将代码和数据放置在目标处理器的指定内存空间。
链接程序分为两个阶段:第一阶段,决定每一个目标文件开始的绝对弟子,目标文件装载的顺序由用户给定,给出文件装载顺序和每一个目标文件的长度后,容易计算出每个文件的其实地址;第二阶段,装载程序把所有目标文件符号表合并为i单独的一个大表,然后把相对地址变为绝对地址。
定位时,要根据目标系统中实际存在的存储器地址,根据输入的目标文件顺序以段为单位将他们一个接一个地拼接起来。除了按目标地址拼装以外,在定位过程中还完成了两个任务:一是生成最终的符号表;二是对代码段中的某些位域进行修改,所有需要修改的地方都有编译器生成的重定位表给出。
下载就是把链接得到的二进制文件装载到目标系统指定的内存中的过程。
在主机上开发并编译完成的可执行目标代码,经过主机与目标机之间的某种(串行接口、网络接口、USB接口、JTAG接口等)下载方式下载到嵌入式系统中,或者固化在嵌入式系统只读存储器中。
首先,如何在主机上控制目标机上的程序运行。这个问题可以通过目标机上运行调试代理的方式解决。调试代理负责与主机上的调试程序通信,解释调试命令并控制目标程序的运行(继续运行、单步运行、断点设置等)。
其次,如何模拟目标系统的输入/输出。
在PC机或工作站上,大量软件调试都可以编译并模拟执行代码来完成。但在某些情况下系统最终不可避免地要求直接在嵌入式目标硬件上运行代码。
在大多数评测主板上,串行端口是最重要的调试工具之一。
另一个调试工具是断点。在程序到达断点时,调试器会自动进入到监控状态。在监控状态,用户可以观察或修改CPU急促请你、程序变量值、存储器单元值甚至输入/输出寄存器。
&emsp:目前嵌入式系统断点由硬件断点和软件断点两种形式。硬件断点是指在微处理器内部配置硬件比较器(如ARM EmbeddedICD的嵌入式跟踪宏单元).软件断电时通过代码替换来完成的。
可以利用LED在代码进入特定程序显示错误状体,或显示空闲时的活动等等。
当软件工具不足以调试系统时,硬件辅助可以帮助查看系统运行时到底发生了什么。
典型的逻辑分析仪能够以两种模式获取数据:状态模式和定时模式。在定时模式中,采用使用一个内部时钟,这个时钟足够快地在每个被测系统时钟阶段抽取几个样本。状态模式则理工被测系统时钟控制采样,所以它每个时钟周期采样一个信号。
在嵌入式系统开发中,经常会遇到软件已经开发完成,但硬件还没有准备好的情况。虽然木便有了开发平台、开发板等,完全脱离硬件而在开发主机上的软件调试时极为有用的。如ARM的ARMulator。大部分CPU模拟器不能报告执行一段代码所使用的机器周期数,也不对总线和I/O设备的活动模拟。通常CPU模拟器能够模拟目标系统CPU的核心代码计算,也提供较强的可视性调试界面。
保证设计正确并不够,还必须保证系统被无误地制造出来。制造测试的目的时确保咋系统生产时的错误不会被带入到产品中来。即使设计时完美的,在系统每个副本的制造中也由潜在性的错误而使之被剔出流水线。设计出一个完美的系统之后再去解决在生产者咋样测试他们,这通常不会是一个好主意。当制造复杂系统时,有必要在设计中考虑制造测试。
制造一个被快速、测试地测试过的系统,通常需要仔细的设计,以确保系统能用许多显示制造错误结果的方式进行检查。
在一个产品测试中给定需要测试的所有可能的故障情况,就能生产一系列测试来检查每个故障对应的那些故障结果。
当逻辑电路的输出仅取决于当时的输入时,称这类电路为组合逻辑电路。
当逻辑电路的输出不仅依赖于当时的输入而且也依赖于过去的历史时,这类电路为时序逻辑电路。
降低顺序测试的复杂性的一个方法是使用扫描链。在扫描模式,它像一个允许寄存器的目前状态移出并且新状态被移入的移位寄存器。
边界扫描时芯片的标准接口,它被称为JTAG.JTAG标准为加入到芯片引脚的扫描链描述了配置和控制顺序。
&emsp:边界扫描用于检测微处理器基本部分时非常有用的。一旦微处理器的基本部分能够正常工作,就可以通过它运行各类诊断测试程序来检查系统的外围电路。