1、第2章 嵌入式系统的开发过程,一 嵌入式软件开发的特点,嵌入式系统与通用计算机在以下几个方面的差别比较明显: (1)人机交互界面。嵌入式系统和通用计算机之间的最大区别在与人机交互界面。嵌入式系统可能根本就不存在键盘、显示器等设备,它所完成的事情也可能只是监视网络情况或者传感器的变化情况,并按照事先规定好的过程及时完成相应的处理任务。 (2)有限的功能。嵌入式系统的功能在设计时已经定制好,在开发完成投入使用之后就不再变化,系统将反复执行这些预定好的任务,而不象通用计算机那样随时可以运行新任务。当然,使用嵌入式操作系统的嵌入式系统可以添加新的任务,删除旧的任务;但这样的变化对嵌入式系统而言是关键性
2、的变化,有可能会对整个系统产生影响。 (3)时间关键性和稳定性。嵌入式系统可能要求实时响应,具有严格的时序性。同时,嵌入式系统还要求有非常可靠的稳定性。 其工作环境可能非常恶劣,如高温、高压、低温、潮湿等。这就要求在设计时考虑目标系统的工作环境,合理选择硬件和保护措施。软件稳定也是一个重要特征。软件系统需要经过无数次反复测试,达到预先规定的要求才能真正投入使用。,嵌入式软件开发与传统软件开发有许多共同特点,但它又有它自身的特点: (1)需要交叉开发环境。嵌入式应用软件开发要使用交叉开发环境。交叉开发环境是指实现编译、链接和调试应用程序代码的环境。与应用程序环境不同,它分布在有通信链接的宿主机和
3、目标机环境之中。宿主机(Host)是一台通用计算机,一般是PC机。它通过串口或网络连接与目标机通信。目标机(Target)常在嵌入式软件开发期间使用,用来区别与嵌入式系统通信的宿主机。目标机应用软件需要绑定操作系统一起运行。交叉软件包括交叉编译器、交叉调试器和模拟软件等。交叉编译器允许应用程序开发者在俗主机上生成能在目标机上运行的代码。交叉调试器和模拟调试软件用于完成俗主机与目标机应用程序代码的调试。,(2)引入任务设计方法。嵌入式应用系统以任务为基本单元。在系统设计阶段,用多个并发的任务代替通用软件的多个模块,并定义了应用软件任务间的接口。嵌入式系统的设计通常采用DARTS(Design a
4、nd Analysis of Real-Time Systems)设计方法进行任务的设计。DARTS给出了系统任务划分的方法和定义任务间接口的机制。 (3)需要固化程序。通用软件的开发在测试完成以后就可以直接投入运行。其目标环境一般是PC机,在总体结构上与开发环境差别不大。而嵌入式应用程序开发环境是PC机,但运行的目标环境却千差万别,可以是PDA,也可以是仪器设备。而且应用软件在目标环境下必须存储在非易失性存储器中,保证用户用完关机后确保得到保证下次的使用。所以应用软件在开发完成以后,应生成固化版本,烧写到目标环境的Flash中运行。 (4)软件开发难度大。绝大多数的嵌入式应用有实时性的要求,
5、特别在硬实时系统中,实时性至关重要。这些实时性在开发的应用软件中得到保证,这就要求设计者在软件的需求分析中充分考虑系统的实时性。这些实时性的体现一部分来源于实时操作系统的实时性,另一部分依赖于应用软件的本身的设计和代码的质量。同时,嵌入式应用软件对稳定性、可靠性、抗干扰性等性能的要求都比通用软件的要求更为严格和苛刻。因此,嵌入式软件开发的难度加大。,嵌入式开发还需要提供强大的硬件开发工具和软件包支持,需要开发者从速度、功能和成本综合考虑,由此看来有以下几点: a、硬件功能强。更强大的嵌入式处理器(如32为RISC芯片或信号处理器DSP)增强了处理能力,加强了对多媒体、图形等的处理。同时增加功能
6、接口,如USB等。 b、工具完备。见P37。 c、通信接口。要求硬件上提供各种网络通信接口。新一代的嵌入式处理器已经开始内嵌网络接口,除了支持TCP/IP协议,有的还支持IEEE1394、USB、Bluetooth或IrDA通信接口中的一种或几种;软件方面系统内核支持网络模块,甚至可以把设备做成嵌入式Web服务器或嵌入式浏览器。 d、精简系统内核以降低功耗和成本。未来的嵌入式产品是软硬件紧密结合的设备,为了降低功耗和成本,需要设计者尽量精简系统内核,利用最低的资源实现最适当的功能。 e、提供友好的多媒体人机界面。嵌入式设备与用户交互,最重要的因素就是它能提供非常友好的用户界面。手写文字输入、彩
7、色图形和图象都会使用户获得操作自如的感受。,2.2 嵌入式软件的开发流程,嵌入式软件的开发流程与通用软件的开发流程大同小异,但开发所使用的设计方法有一定的差异。整个开发流程可分为需求分析阶段、设计阶段、生成代码阶段和固化阶段。开发的每个阶段都体现着嵌入式开发的特点。 1 需求分析阶段嵌入式系统的特点决定了在开发初期的需求分析过程中就要搞清需要完成的任务。在需求分析阶段需要分析客户的需求,并将需求分类整理-包括功能需求、操作界面需求和应用环境需求等。嵌入式系统应用需求中最为突出的是注重应用的实效性,竞争中Time-to-Market最短的企业最容易赢得市场。嵌入式开发的需求分析阶段与一般软件开发
8、的需求分析阶段差异不大,包括以下3个方面。a、对问题的识别和分析。见P38。b、制定规格说明文档。经过对问题的识别,产生了系统各方面的需求。通过对规格的说明,文档得以清晰、准确的描述。这些说明文档包括需求规格说明书和初级的用户手册等。c、需求评审。需求评审作为系统进入下一阶段前最后的需求分析复查手段,在需求分析的最后阶段对各项需求进行评估,以保证软件需求的质量。,2 设计阶段需求分析完成后,需求分析员提交规格说明文档,进入系统设计阶段。系统的设计阶段包括系统设计、任务设计和任务的详细设计。通用软件开发的设计常采用将系统分为各个功能子模块,在进一步细分为函数,采用自顶向下的设计方法。而嵌入式应用
9、软件是通过并发的任务来运作的,应用软件开发的系统设计将系统划分为多个并发执行的任务,各个任务允许并发执行,通过相互间通信建立联系。传统的设计方法不适应这种并发的设计模式,因而在嵌入式软件开发中引入DARTS的设计方法。 DARTS设计方法是结构化分析/结构化设计的扩展。它给出划分任务的方法,并提供定义任务间接口的机制。DARTS设计方法的设计步骤如下:a、数据流分析在DARTS设计方法中,系统设计人员在系统需求基础上,以数据流图作为分析工具,从系统的功能需求开始分析系统的数据流,以确定主要的功能。扩展系统的数据流图,分解系统到足够的深度,以识别主要子系统和各个子系统的主要部分。,b、划分任务
10、系统设计人员把可并行、相对独立的功能单元抽象成一个系统任务。实时软件系统中并行任务的分解主要考虑系统内部功能的异步性。根据数据流图中的变换,分析出哪些变换是可以并行的,哪些变换是顺序执行的。系统设计人员可以考虑一个变换对应一个任务,或者一个任务包括多个变换。其判定的原则取决于以下因素:I/O依赖性:如果变换依赖于I/O,应选择一个变换对应一个任务。时间关键性的功能:具有时间关键性的功能应分离出来,成为一个独立的任务,并且赋予这些任务较高的优先级,以满足系统对时间的要求。计算量大的功能:计算量大的功能在运行时势必会占用CPU很多时间,应当让他们单独成为一个任务。功能内聚:系统中各紧密相关的功能,
11、不适合划分为独立的任务,应该把这些逻辑上或数据上紧密相关的功能合成一个任务,使各个功能共享资源或相同事件的驱动。将紧密相关的功能合成一个任务不仅可以减少任务间通信的开销,而且也降低了系统设计的难度。时间内聚:将系统中在同一时间内能够完成的各个功能合成一个任务,以便在同一时间统一运行。周期执行的功能:将在相同周期内执行的各个功能组成一个任务,使运行频率越高的任务赋予越高的优先级。,c、定义任务间的接口任务划分完成以后,下一步就要定义各个任务的接口。在数据流图中接口以数据流和数据存储区的形式存在,抽象化数据流和数据存储区成为任务的接口。在DARTS设计方法中,有两类任务接口模块:任务通信模块和任务
12、同步模块,分别处理任务间的通信和任务间的同步。有了划分好的任务以及定义好的任务间的接口后,接下来就可以开始任务的详细设计,任务详细设计的主要工作是确定每个任务的结构。画出每个任务的数据流图,使用结构化设计方法,从数据流图导出任务的模块结构图,并定义各模块的接口。之后,进行每个模块的详细设计,给出每个模块的程序流程图。,3 生成代码阶段生成代码阶段需要完成的工作包括代码编程、交叉编译和链接、交叉调试和测试等。a、代码编程编程工作是每个模块的详细设计文档基础上进行的。规范化的详细设计文档能缩短编程时间。由于嵌入式系统是一个受资源限制的系统,故而直接在嵌入式系统硬件上进行编程显然是不合理的。在嵌入式
13、系统开发过程中,一般采用的方法是先在PC上编程;然后通过交叉编译、链接,将程序做成目标平台上可以运行的二进制代码格式;最后将程序下载到目标平台上的特定位置,在目标板上启动运行这段二进制代码。,b、交叉编译和链接嵌入式软件开发编译完成后,要进行编译和链接以生成可执行代码。但是,在开发过程中,设计人员普遍使用Intel公司的x86系列CPU的计算机进行开发;而目标环境的处理芯片确是多种多样的,如ARM、DSP、PowerPC、DragonBall系列等。这就要求开发机的编译器能支持交叉编译。嵌入式C编译器是有别于一般计算机中的C语言编译器的.嵌入式系统中使用的C语言编译器需要专门进行代码化,以产生
14、更加优质、高校的代码。优秀的嵌入式C编译器产生代码长度及运行时间仅比以汇编语言编写的同样功能程序长5%-20%。这微弱的差别完全可以有现代处理器的高速度、存储器容量大以及产品提前占领市场的优势来加以弥补;编译产生代码质量的差异,是衡量嵌入式C编译器工具优劣的重要指标。,c、交叉调试 调试是开发过程中必不可少的环节。嵌入式开发软件的交叉编译不同于通用软件的调试方法。在通用软件开发中,调试器与被调试的程序往往运行在同一机器上,作为操作系统上的两个进程,通过操作系统提供的调试接口控制被调试进程。嵌入式软件开发需要交叉开发环境,调试采用的是包含目标机和宿主机的交叉调试方法。调试器还是运行在宿主机的通用
15、操作系统上,而被调试的程序则运行在基于特定硬件平台的嵌入式操作系统上。调试器与被调试程序间可以进行通信,调试器可以控制、访问被调试程序,读取被调试程序的当前状态和改变被调试程序的运行状态。交叉调试器用于对嵌入式软件进行调试和测试。嵌入式系统的交叉调试器在宿主机上运行,并且通过串口或网络连接到目标机上。,嵌入式软件的编写和开发调试主要流程为:代码编写-交叉编译-交叉链接-重定位和下载-调试,如图所示。,交叉调试具有以下特点: *调试器和被调试的程序运行在不同的机器上。调试器运行在PC或工作站上,而被调试程序运行在各式的专用目标机上。 *调试器通过各种通信方式与目标机建立联系,如串口、并口、网络、
16、JTAG或者专用的通信方式。 *在目标机上一般具有某种调试代理,这种代理能与调试器一起配合完成对目标机上运行的程序的调试。这种代理可以是某种能支持调试的硬件,也可以是某种软件。*目标机可以是一种仿真机。通过在宿主机上运行目标机的仿真软件来仿真一台目标机,使整个调试工作只在一台计算机上进行。,整个嵌入式系统软件的开发一般在集成开发环境下完成。嵌入式系统的开发工作几乎使跨平台交叉开发,多数代码直接控制硬件设备,硬件依赖性强,对时序的要求十分苛刻,很多情况下 的运行状态都具有不可再现性。 嵌入式集成开发环境关键技术包括项目建立和管理工具、源代码级调试技术、系统状态分析技术、代码性能优化技术、运行态故
17、障监测技术、图形化浏览工具、代码编辑辅助工具以及版本控制工具等。嵌入式集成开发环境包括可裁减的实时操作系统,宿主机上的编译、调试、查看等工具,以及利用串口、网络ICE等宿主机与目标机的连接工具。 (4)测试嵌入式系统开发的测试与通用软件的测试相似,分成单元测试和系统集成测试。,4固化阶段 嵌入式应用软件调试完成以后,编译器要对源代码重新编译一次,以产生固化到目标环境的可执行代码,在烧写到目标环境的Flash中。固化的可执行代码与用于调试的可执行代码有一些不同。固化用的代码在目标文件中把调试用的信息都屏蔽掉了。固化后没有监控器执行硬件的启动和初始化。启动模块和固化代码都定位到目标环境的Flash
18、中,有别于调试过程中都在目标机的RAM中运行。 可执行代码烧写到目标环境中固化后,还要进行运行测试,以保证程序的准确无误。固化测试完成后,整个嵌入式应用软件的开发就基本完成了,剩下的就是对产品的维护和更新了。,5嵌入式软件开发的要点,嵌入式软件高度依赖目标应用的软硬件环境,软件的部分任务功能函数由汇编语言完成,具有高度的不可移植性。但这并不是说嵌入式软件的开发不需要关注可移植性。提高应用软件的可移植性方法如下: 1 尽量使用高级语言开发,少用汇编语言。 2 局域化不可移植部分,要提高代码的可移植性,可以把不可移植的代码和汇编代码通过宏定义和函数的形式,分类集中在某几个特定的文件中。程序中对不可
19、移植代码的使用转换成函数和宏定义的使用,在以后的的移植过程中,既有利于迅速地对要修改地代码进行定位,又可以方便地进行修改,最后检查这个代码中修改的函数和宏对前后代码是否有影响,从而大大提高移植的效率。3 提高软件的可重用性。,2.3 嵌入式系统的调试,调试方式有很多种,应根据实际的开发要求和实际的条件进行选择。 1.源程序模拟器方式源程序模拟器是在PC机上,通过软件手段模拟执行为某种嵌入式处理器编写的源程序的测试工具。模拟器软件独立于处理器硬件,一般与编译器集成在同一个环境中,是一种有效的源程序检验和测试工具。但是,模拟器的功能毕竟是以一种处理器模拟另一种处理器的运行,在指令执行时间、中断响应
20、、定时器等方面很有可能与实际处理器有相当大的差别。另外,它无法仿真嵌入式系统在应用系统中的实际执行情况。 ARM公司的开发工具有ARMulator模拟器,可以模拟开发各种ARM嵌入式处理器。它具有指令、周期和定时等三级模拟功能。 *指令级:可以给出系统状态的精确行为。 *周期级:可以给出每一周期处理器的精确行为。 *定时级:可以给出在一周期内出现信号的准确时间。,2.监控器方式,监控器调试需要目标机和宿主机协调。首先,在宿主机和目标机之间建立物理上的连接。在宿主机上运行调试器 ,目标机运行监控程序和被调试程序。监控程序是一段运行于目标机上的可执行程序,主要负责监控目标机上被调试程序的运行情况。
21、它与宿主机端调试器一起完成对应用程序的调试。监控程序包含基本功能的启动代码,并完成必要的硬件初始化,初始化自己的程序空间,等待宿主机的命令。被调试程序通过监控程序下载到目标机,就可以开始进行调试。程序在调试过程中查出错误后,通过调试器进行错误的定位;然后在宿主机上进行源码的修改,重新编译生成后下载到目标机,再进行下一轮的调试。,监控器方式操作简单易行,功能强大,不需要专门的调试硬件,适用面广,能提高调试的效率,缩短产品的开发周期,降低开发成本,应用广泛。监控器调试主要用于调试运行在目标机操作系统上的应用程序,不适宜用来调试目标操作系统。ARM公司的Angel是常驻在目标机Flash中的监控程序
22、。通过RS-232串行口与PC机相连。Angel功能如下: *具有Debug功调试能。 *支持Angel调试协议ADP(Angel Debug Protocol)。 *支持目标机中的应用程序使用标准C函数库。 *具有多任务调度和处理器模式管理功能。 *具有中断功能。Angel不但具有多任务调度功能,还具有对存储器管理单元MMU进行调试和管理的功能。实际上,Angel具有了部分操作系统的功能。,3.仿真器模式,仿真器调试方式使用处理器内嵌的调试模块接管中断及异常处理。用户通过设置CPU内部的寄存器来指定哪些中断或异常发生后处理器直接进入调试状态 。仿真器调试方式是在微处理器的内部嵌入额外的控制模
23、块。当特定的触发条件满足时,系统将进入某种特殊状态。在这种状态下,被调试的程序暂时停止运行,宿主机的调试器通过微处理器外部特设的通信口访问各种寄存器、存储器资源,并执行相应的调试指令。仿真器调试方式避免了监控器方式的许多不足。它在调试过程中不需要对目标操作系统进行修改,没有引入监控器,使系统能够调试目标操作系统的启动过程。而且通过微处理器内嵌的处理模块,在微处理器内部提供调试支持,不占用目标平台的通信端口,大大方便了系统开发人员。但是,为了识别各种各样的目标环境以及它们可能出现的异常和出错,必须针对不同开发板使用的微处理器编写相适应的各类Flash、RAM的初始化程序。这大大增加了程序员的软件
24、工作量。,一般高档微处理器都带JTAG接口,如Intel公司的XScale、Samsung公司的S3C4510B等。现在,很多DSP芯片都带JTAG接口,如TI公司TMS3205XX系列。通过JTAG接口,既可对目标系统进行测试,也可对目标系统的存储单元(如Flash)进行编程。嵌入式系统的调试有很多种方法,也被分成不同的层次。调试方法有软件调试和硬件调试,前者使用软件调试器调试嵌入式系统软件,后者使用仿真调试器协助调试过程。就操作系统调试的层次而言,有时需要调试嵌入式操作系统的内核,有时需要调试嵌入式操作系统的应用程序。由于嵌入式系统特殊的开发环境,不可避免的是调试时必然需要目标运行平台和调
25、试器两方面的支持。调试过程的结构如图2-3所示。P46。,1硬件调试,使用硬件调试器,可以获得比软件功能强大得多的调试性能。硬件调试器的原理一般是通过仿真硬件的真正执行过程,让开发者在调试过程中可以时刻获得执行情况。硬件调试器主要有ICE(在线仿真器)和ICD(在线调试器)两种。ICE是一种完全仿造调试目标CPU设计的仪器。该仿真器可以真正地运行所有的CPU动作,并且可以在其使用的内存中设置非常多的硬件中断点,可以实时查看所有需要的数据,从而给调试过程带来很多的便利。老式的ICE一般只有串口和并口,新式ICE还提供USB或以太网接口。但ICE的价格非常昂贵。使用ICD和目标板的调试端口连接,发
26、送调试命令和接受调试信息,就可以完成必要的调试功能。一般地,在ARM公司提供的开发板上使用JTAG接口,在Motorola公司提供的开发板上使用BDM口。使用合适的工具可以利用这些调试口。例如ARM开发板,可以将JTAG调试器接在开发板的JTAG口上,通过JTAG口与ARM CPU进行通信。然后使用软件工具与JTAG调试器相连接,做到与ICE调试类似的调试效果。,2. 软件调试,1(1) 操作系统内核的调试 操作系统内核比较难以调试,因为操作系统内核中不方便增加一个调试器程序。如果需要调试器程序,也只能使用远程调试,通过串口与操作系统中内置的“调试桩”,完成调试工作。(2) 应用程序的调试的调
27、试应用程序的调试可以使用本地调试器和远程调试器两种方法。相对操作系统的调试而言,这两种方法都比较简单。可以将需要的调试器移植到该系统中,直接在目标板上运行调试器调试程序。也可以远程调试,只需要将一个调试服务器移植到目标系统中就可以了。由于很多嵌入式系统受资源的限制,而调试器一般需要占用太多的资源,所以使用远程调试的选择占了大多数。,2.4 板级支持包,由于嵌入式系统中可以采用微处理器/微控制器的多样性,嵌入式操作系统的可移植性显得更为重要。所以有些嵌入式操作系统的内核明确分成两层,其上层一般称为“内核”,而低层则称为“硬件抽象层”或“硬件适配层”,都缩写成HAL。HAL往往独立于内核,由CPU
28、的厂商提供,与BIOS很相似。也有的厂商(如VxWorks的提供者WindRiver公司)把硬件抽象层称为BSP,即板级支持包(Board Support Package)。严格来说,这两个词是有差别的,HAL更偏向于CPU芯片,而BSP更偏向于板子一级,但是实际使用中并不严格加以区分。板级支持包是操作系统与目标应用硬件环境的中间接口,它是软件包中具有平台依赖性的那一部分。板级支持包将实时操作系统与目标应用环境的硬件连接在一起,它不可避免地使用了硬件设备的特性,具有很强的硬件相关性。板级支持包的实现中包含了大量的与处理器和设备驱动相关的代码和数据结构。,板级支持包完成的功能大体有以下两个方面:
29、 *在系统启动时,对硬件进行初始化。比如对设备的中断、CPU的寄存器和内存区域的分配等进行操作。这个工作是比较系统化的,要根据CPU的启动、系统的嵌入式操作系统的初始化以及系统的工作流程等方面要求来决定这一部分BSP应完成什么功能。 *为驱动程序提供访问硬件的手段。驱动程序经常要访问设备的寄存器,对设备的寄存器进行操作。如果整个系统是统一编址,开发人员可以直接在驱动程序中用C语言的函数就可以访问。但是,如果整个系统是单独编址,那么C语言就不可以直接访问设备中的寄存器,只有用汇编语言编写的函数才能进行对外围设备寄存器的访问。BSP就是为上层的驱动程序提供访问硬件设备寄存器的函数包。 在对硬件进行初始化是,BSP要完成大量的工作. 开发一个性能稳定可靠、可移植性好、可配置性好、规划化的板级支持包将大大提高嵌入式操作系统各方面的性能。在目标环境改变的情况下,嵌入式操作系统的桥级支持包只需要在原有的基础上做小小的改动,就可以适应新的目标硬件环境。这无疑将显著地减少开发的成本和开发周期,提高嵌入式操作系统的市场竞争力。,