|
知识路径: > 嵌入式系统软件基础知识 > 嵌入式系统程序设计 > 嵌入式软件开发过程 > 嵌入式软件设计 >
|
相关知识点:31个
|
|
|
|
由于嵌入式系统的特殊性,嵌入式软件除正常功能要求外,在实时性、安全性、可靠性、可扩展性、可定制性、标准符合性等方面都有要求。下面简要介绍实时性、可扩展性、可定制性等方面的设计技术。
|
|
|
|
嵌入式应用通常都有实时性的要求,即系统部分功能需要满足时间的限制。根据系统对时间的要求不同,可分为软实时要求和硬实时要求。对于软实时要求的系统,希望系统运行越快越好,不局限于特定任务在多长时间完成。对于硬实时系统,则有明确的任务执行时限的要求,如果系统运行不能满足该要求,则必须采取处理措施。
|
|
|
通常情况下,嵌入式系统对于硬实时和软实时都有要求,是两者的结合。在进行软件实时性设计时,需要考虑如下几个方面因素:
|
|
|
(1)通过合理划分实时单元和分时单元,提高系统的实时性能。例如,对于信号处理系统,对于信号的翻译、解释、转移、传递和应答是实时单元,通常要放到实时任务中处理。而对于运行过程中信息输出或故障信息记录,可以是分时单元,可以利用操作系统数据通信机制传递信息,或直接采用共享内存方式传递数据,由分时任务或系统后台任务进行数据处理。
|
|
|
(2)合理划分系统中的实时任务,提高系统运行效率、实时性和吞吐量。任务是实时系统运行的调度单元,具体管理系统中的各类资源,可以使用或等待CPU、存储空间或I/O设备等。任务彼此之间按照系统的调度策略执行,对于没有操作系统的系统,需自行编写调度算法。通常,任务与函数形式差异不大,但有确定的任务入口点、私有数据区、以及主体结构,表现为循环体或明确的中止状态(任务没有返回值)。任务划分粗细程度,对系统影响较大,划分过细则会引起任务频繁切换,如果划分不彻底,又会造成原本可并行的操作只能串行开展。为了达到效率和吞吐量之间的平衡与折衷,应遵循一定的任务分解规则(假设下述任务的发生都依赖于唯一的触发条件,如果两个任务能够满足下面的条件之一,则可以将其合理地分开):
|
|
|
.时间:两个任务所依赖的周期条件具有不同的频率和时间段。
|
|
|
.异步性:两个任务所依赖的条件没有相互的时间关系。
|
|
|
.优先级:两个任务所依赖的条件需要有不同的优先级。
|
|
|
.清晰性/可维护性:两个任务可以在功能上或逻辑上相互分开。
|
|
|
同时,在设计过程中尽量减少模块(任务)之间的数据通信,特别是控制耦合(即一个任务可控制另一个任务的执行流程或功能),如果必须出现,应采取相应措施(如,任务间通信)实现彼此之间的同步或互斥,以避免可能引起的临界资源冲突,防止死锁现象出现。
|
|
|
(3)在程序设计上采取措施,提高程序执行效率。比较常用的优化手段有:系统关中断/关调度范围尽可能最小化,采用简短的中断服务程序,循环体工作量最小化,将频繁使用的变量设置为寄存器变量,采用经典高效的算法(如查找、排序)等。
|
|
|
|
出于系统的升级、维护和重用的考虑,对软件的可扩展性提出了要求,需要在设计过程中规划好系统的架构,并采用模块设计方法实现。例如,在面向航空领域应用的特定系统,其系统功能由软硬件共同实现,如何区分软硬件功能分配以及两者之间的界限非常重要,同时应用中涉及大量驱动软件、功能组件,就需要对这些部分进行模块化设计。
|
|
|
|
混合编程模式是指同时利用汇编语言和高级语言进行嵌入式软件设计。这主要是利用汇编语言对硬件操作的方便性和汇编语言的高效执行特点来编写与硬件紧密相关,或实时要求严格的代码;而利用高级语言接近人的思维、处理逻辑关系功能强大的优势编写逻辑功能函数。
|
|
|
通常,高级语言实现的代码比汇编语言实现相应功能的代码具有更好的移植性。在系统设计时,要从系统整体的性能和效率考虑,合理分配高级语言和汇编语言的实现比例,不过分强调某一方面而忽略另一方面。
|
|
|
|
嵌入式领域软件开发时,常常需要开发大量的硬件设备驱动软件,包括各类处理器的驱动、各类外部设备的驱动软件。由于驱动软件需要与硬件进行深度结合,并且部分是采用汇编语言实现,如果没有合理硬件驱动管理机制的支持,很难做到软件在不同硬件平台上的迁移与扩展。
|
|
|
类似于Windows系统的硬件设备驱动,在嵌入式系统的软件开发中引入了硬件驱动层,对系统运行的各类设备驱动进行封装。上层的系统软件通过标准的接口进行访问,实现系统软件与硬件的隔离,降低系统软件的开发难度,缩短了开发时间。硬件驱动层包括CPU片内资源的硬件驱动和板子上外围设备硬件的驱动,如下图所示。
|
|
|
|
|
CPU的硬件驱动通常包括寄存器、时钟、中断、异常、存储管理单元等。在系统引导过程中,要配置好各种寄存器,进行时钟、中断、异常、存储管理等部件初始化,后续系统软件则通过子程序的方式调用相关硬件驱动。
|
|
|
其他外部设备驱动通常包括串口、网口、鼠标、键盘、存储器等。在系统开发时,需要为目标机所有的外部设备逐一编写驱动程序,以供其他应用软件进行调用。例如键盘,硬件会记录每次按下的键码,放入输入键码队列中,编制的驱动程序即从键码队列中取出按下的键,根据键值的不同执行不同的操作。通过编制硬件驱动层,并通过标准的接口向上提供访问,使得上层软件的编写就与硬件无关了,只要软件之间逻辑关系正确,就不需要改动。即便是驱动程序需要移植到其他硬件上,只要硬件设计基本相同,也可以直接重用硬件驱动程序,使得整个软件方便地移植。
|
|
|
|
模块化设计方法适用于通用软件和嵌入式软件的设计,是提高系统可扩展性和软件复用性的通用方法。模块化设计包括四个方面:模块、数据、体系和程序设计。
|
|
|
模块设计降低了系统的复杂性、使得系统易于修改、且支持了各部分的并行开发。针对模块的操作特性,则是通过时间历史、激活机制和控制模式进行体现。在程序结构内部,模块可分类:
|
|
|
(1)顺序模块,由应用程序进行引用和执行,运行过程中不能被打断。
|
|
|
(2)增量模块,运行过程中可被其他应用程序打断,而后再从断点重新开始。
|
|
|
(3)并行模块,在多处理器环境下可以与其他模块同时执行。
|
|
|
由于单个模块的功能已被划分出来,开发起来相对较为容易,更多要从独立性的角度关注模块之间的界限。功能的独立性可以使用内聚性和耦合性这两个特性要素进行衡量:内聚性衡量模块功能强度的相关性,耦合性衡量模块间的相互依赖的相关性。
|
|
|
数据设计至关重要,并被有些人认为是最重要的设计行为。数据设计主要取决于数据结构的设计和程序复杂性的设计,通常采用如下办法保证数据设计的质量:
|
|
|
(1)用于功能和行为分析的系统分析原理也适用于数据。
|
|
|
(2)模块涉及的数据结构及基于数据结构的操作应被确定。
|
|
|
(3)创建数据词典并用来详细说明数据和程序的设计。
|
|
|
(4)较低层次的数据设计策略延迟至设计过程的后期。
|
|
|
(5)数据结构的信息应只被需要使用此结构内数据成员的模块知道。
|
|
|
|
(7)设计和编程语言应支持抽象数据类型的规范和实现。
|
|
|
体系设计的主要目标是定义适合模块化开发的程序结构,并描述出模块之间的控制相关性。体系设计应融合程序结构与数据结构,并对数据在程序中流动的界限进行定义。体系设计要关注系统的整体设计而不是单独组件。进行体系设计有许多不同的方法,但这些方法无一例外都是从软件的全局性出发,逐步接近设计的原点。
|
|
|
过程设计通常是在数据、程序结构及算法被确定后(通常是类似英语的自然语言),再进行程序过程设计。
|
|
|
|
系统的可定制性通常包括可剪裁性和可配置性两个方面。
|
|
|
|
系统的开发者需要完成系统的全集,而系统的使用者由于资源限制或使用需求只要求获得系统的子集,对于不需要的部分要进行剪裁。系统的剪裁性取决于模块之间的耦合度,耦合度越小的系统,剪裁力度越大。对于嵌入式系统,通常可以剪裁到只包含如下内容:
|
|
|
|
|
|
例如,一般的嵌入式系统设计中,通常是按照功能对代码进行了细致地划分,抽象出一部分公共函数作为实现其他功能的基础,不可被剪裁,其他功能代码之间由于比较独立,具有良好的可剪裁性。但是,由于操作系统本身的管理功能要求,类似任务管理和定时功能这些从技术上看可以剪裁的模块,必须保留在内核之中。
|
|
|
|
用户对于已经选择的模块,需要通过配置进一步调整系统的功能和规模。通常在系统设计时要定义一组参数来实现对软件规模的配置,也可以通过系统调用中的参数对系统功能进行配置。
|
|
|