近来,有报道称包括Denso、Motorola和Toyota在内的不同行业的多家公司都在产品代码方面取得了成功。这项技术正日益成为软件下一波演进发展中的一个重要组成部分。虽然总体而言,它对软件工程化过程的影响已为业界所了解,但却并没有十分清楚地确立起来。对于早前类似演进发展(包括从机器代码发展到汇编代码,再发展到源代码)的参与者而言,这一点尤为明显。
图1:查看一个软件过程的普通方法是借助于V形图。
随着抽象与自动化程度的日益提高,新的过程、方法和工具接踵而来。瀑布式过程已让位于螺旋式方法和迭代方法。实时方法已经出现并正在取代静态流程设计。新的工具也出现了,如包含有调试器、优化编译器和自动测试工具的IDE(集成开发环境)。
不过,由于难以使用、缺乏了解或是工具支持不足的原因,并非每一种好的思想都能开花结果。有迹象表明,这些方法和工具对于主流产品应用并非总是实用。例如,用验证来确保软件正确性的正规方法是使用一种全世界只有极少数专家才真正懂得的语言编写的。此外,1980年代的实时用例工具可以辅助设计,但并未提供一条产生最终代码的简便途径。
图2:用控制系统方框图来表示反馈控制。
在早期应用阶段,产品代码生成的效果相当不错,这主要是由于其实用性。不过,其进一步的发展还需要依靠集成过程、方法和工具的支持。一种新的过程只有在具备了所需支持方法和工具的条件下才会成功。如果这些条件有所欠缺,那么对一个公司成熟的嵌入式系统进行重新设计的努力就不会是可行和实用的。
本文给出了主要面向产品代码生成的这样一个框架:
* 基于模型的设计
* 建模、仿真、快速原型、产品代码生成、模型测试和覆盖、在环测试
* 开发工具、验证与生效(V&V)工具、集成工具
模型的设计过程
图3:创建一个系统模型来表示所需的行为特性。
通过提供一个共同的图形规范和分析环境,基于模型的设计可以支持控制/DSP系统工程师和软件开发人员的需要。在这个过程中,模型被创建并用来规定系统数据、接口、反馈控制逻辑、离散/状态逻辑和实时行为。
基于模型的设计被应用在几乎每个需要嵌入式控制系统的行业之中。而在大型控制单元(ECU)等嵌入式应用的开发过程中,其应用更为广泛。DSP和通信应用也采用这种方法,但它们更强调建模和原型,而不是产品代码生成。
为了满足这些不同的应用,基于模型的设计过程必须解决线控驾驶系统等安全关键系统的需求。它还必须产生最终的、可执行的代码,而且必须特别紧凑、快速和能够追踪。这是由于在大批量生产的ECU中,必须使用低成本的定点微控制器部件和DSP。
基于模型的设计适合任何过程框架环境,包括那些在IEEE软件工程化标准中描述过的过程框架。
IEEE Std. 730适用于任何通用软件项目。为了很好地理解它的过程框架,有必要回顾一下它对“关键性”项目文档所列出的需求。
IEEE Std. 730需求包括:
* 软件需求规范(SRS)
图4:线控驾驶系统。
* 软件设计描述(SDD)
* 软件验证与生效计划(SVVP)
* 软件验证与生效报告(SVVR)
* 用户文档
* 软件配置管理计划(SCMP)
* 包括软件项目管理计划(SPMP)在内的其他文档
查看一个软件过程的普通方法是借助于图1所示的V形图。这个图对应着大部分工程化过程,不过在开发生命周期中,这个过程是迭代性的,有许多反复的步骤。图中的软件过程包括以下几个组成部分:
* 开发 (需求、设计、编码和集成)
图4B:对线控驾驶系统的建模与仿真。
* 验证和生效(V&V)
* 集成 (软件配置管理、需求可追踪性和文档)
基于模型的设计非常注重过程迭代、早期测试和开发过程中的重用,这使得它既独特而又功能强大。这一过程的内在实用性体现在V形图的底部,产品代码生成是来自设计的一种自动过渡。
在基于模型的设计中,方框图或状态图模型可以用作系统和软件需求、软件设计,或者在稍作假设变换之后,用作源代码。这个过程的另外一个独特之处是,它在最终编译之前要进行广泛的验证和生效操作。早期验证和生效的好处很明显:它将大大减少在最终系统集成和测试期间发现的bug数目,返工次数也会更少。
开发方法与工具
在软件工程化过程中,采用了基于模型的设计方法
图5:故障模式效应分析用来确保线控驾驶的救生操作。
开发方法包括:1. 行为建模;2. 详细软件设计;3. 分布式结构设计;4. 产品代码生成;5. 嵌入式目标集成。验证与生效方法包括:1. 仿真与分析;2. 快速原型;3. 模型测试与覆盖;4. 代码追踪与检查;5. 硬件在环(HIL,Hardware-In-the-Loop)测试。集成方法包括:1. 源控制接口;2. 需求管理接口;3. 报告生成。
下面给出了对各种开发方法的简洁描述,并提供有例子和工具支持信息。注意这里给出的所有工具都是商业上可以获得的。其后的部分讨论了开发行为,并包含有关键的验证与生效方法。最后,本文将通过集成组件来进行总结。
1. 行为建模
模型用来为单个子系统(如线控驾驶)的各个方面规定需求和设计。
一个典型的系统包括:
* 输入(如方向盘传感器)
* 控制器或DSP模型
* 设备模型(直流马达、齿条和小齿轮、车轮)
* 输出(方向的改变)
在图2和图3中,通过使用控制系统方框图来表示反馈控制、使用状态图来表示离散事件和条件逻辑,以及使用DSP模块来表示滤波器,可以创建一个系统模型来表示所需的行为特性。
2. 仿真与分析
图6:图3中电源管理设计的测试覆盖。
然后,通过使用基于时间或基于事件的仿真以及频域分析等方法,可以执行和分析模型,以确保其满足需求。例如,一个线控驾驶系统必须对传感器故障进行响应,并“将高频响应衰减到3db以下,同时指令传输速率不能低于1.5Mbps”。
图4A和B*中对线控驾驶系统的建模与仿真,可以确定这些需求是相互冲突的还是有效的。仿真是一个核心验证行为,它确保可以实现一个系统来满足这些需求。
3. 快速原型
要在产品的芯片上实现一个可以工作的解决方案,设备模型还不够精确,处理能力也不满足要求,因此建模本身并不能提供完整的解决方案。
快速原型对于克服这些缺陷非常有用,因为它用物理设备来代替设备模型。在线控驾驶的例子中,设备有可能是一辆汽车,这时就使用一辆实际的汽车。不过,因为系统并未建立起来,一个实时或嵌入式平台将负责运行控制器软件并与设备进行交互作用。
有两种形式的快速原型:功能性快速原型和目标性快速原型。功能性原型使用一台功能强大的实时计算机,如多处理器浮点PowerPC或DSP系统,目的在于确定系统对物理汽车的控制是否如对模型汽车的控制一样好。如果真的是这样,则设备模型的不精确性就显得无关紧要,并且控制策略也得到了验证。
图7:代码回放。
目标性快速原型在相同或相似的产品MCU或DSP,而不是高端PowerPC内核或其他专用高端快速原型硬件中执行软件。目的是将代码下载到实际产品目标之中,以便用物理设备进行快速测试。如果执行良好,则控制器不仅看似有效,而且可以在产品中加以实现。
软件设计行为包括定点数据规范、实时任务、数据输入、内建测试和诊断。通过基于模型的设计,用于算法规范和验证的同一模型被软件工程师加以改进和约束,作为产品代码生成过程的一部分。
4. 模型测试
与将模型部署到硬件上去编译和集成相比,在桌面计算机上测试模型具有更大的优势。基于源代码的测试已经存在许多年了,但是最近的方法允许进行模型测试和结构覆盖。使用的场景假定是开发人员对控制器施加满负荷压力,以便用仿真和覆盖来验证其设计完备性。另一种测试类型是故障模式效应分析(Failure Mode Effect Analysis),用来确保故障情况下线控驾驶的救生操作,参见图5*。
设计完备性不佳的例子是数值溢出和死码(dead code)。使用最小或最大数值的模型压力测试可以确保不发生溢出情况。使用仿真很容易进行这种测试,但死码就没有这么容易检测出来了,因为检测需要结构覆盖。死码与失效代码不同,其区别在于后者是开发人员已知,并且出于某种原因而使其失效的。实际情况中的死码意味着在确定规范期间遗漏了什么。
图8:器件驱动模块库。
模型覆盖用来评估一个测试件的累积结果,以确定哪些功能模块未被执行,或者哪些状态未被到达。源代码语言(如C和C++)中建立了某些类型的覆盖,但现在模型也可以进行覆盖了。这项工作要求C语言所不需要(或不可能有)的新理论和新工具,因为这些语言没有功能模块或状态这样的构造。
修改条件/决策覆盖(MC/DC)被FAA(美国联邦航空管理局)认为是满足安全关键系统所必需的最严格的覆盖水平。现在,这种覆盖在一种基于模型的设计框架和许多需要线控设计的场合中已经得到了实现。
5. 分布式结构设计
现代嵌入式系统包含一些分布式ECU,它们相互间通过一个象FlexRay这样的容错通信系统进行实时通信。宝马(BMW)最新的DSC(动态稳定性控制)包含ABS作为其15个子功能之一。通过从DECOMSYS向单个子系统增加主机、任务和信号等网络部件,嵌入式功能可以连接和映射到一个ECU结构之上。此外,它方便了OSEKtime/OS等时间触发操作系统的任务激活时间行为的仿真。集群、主机、任务和连接是在MATLAB/Simulink环境下进行设计和仿真的。最后,整个设计与DECOMSYS::DESIGNER产品实现了无缝集成,可以与FlexRay xCDEF设计数据仓库进行互动。
Vector公司和Cadence公司提供的分布式网络设计解决方案(分别为DaVinci和SysDesign)集成了Simulink/Stateflow的Real-Time Workshop/Real-Time Workshop Embedded Coder,由子系统产生代码,并将它们映射到结构上进行验证。
产品代码生成 模型经过验证并且生效之后,就该产生代码了。使用编译器时,这个过程是简单的。这里存在着各种不同的优化设置和用户配置选项。关键之处在于保持代码的高效、精确并与原有的代码或其他工具进行集成。另一个要点是保持代码相对框图的可追踪性,以便进行检查和验证。
1. 代码追踪和检查
图7显示了一个自动链接的HTML报告。当开发人员选择代码中的求和模块时,它将把该模块在框图中进行高亮显示。
2. 嵌入式目标集成
图6*中的应用使用了速率转换模块。不过,它与商用RTOS之间也存在着直接的联系,包括VxWorks 和各种OSEK产品。如图7*所示,还需要集成设备驱动程序。
3. 硬件在环测试
控制器建立起来之后,就可以在环路中使用实时设备模型来执行一系列开环和闭环测试了。有一种测试仅涉及处理器,称作“处理器在环”测试。另一种测试使用实际建立的ECU硬件,叫做“硬件在环”测试。在这两种测试中,都使用设备模型来对物理控制器进行测试。通过这一系列测试(或许与需求验证中所用的是同种测试),控制器必须看来对于消费者是可以接受的。
4. 集成组件
在开发过程中,大部分软件标准都要求需求追踪能力,这或许源于其他需求工具。此外,还需要软件配置管理(SCM)来对开发过程中的各种工件(artifact)进行存储、版本维护和查找。由报告生成工具产生的文档将确保管理者、消费者和供应商能够看到模型。SCM的接口如图8*所示。
本文小结
当整个软件工程化过程行为得到支持时,将会推动软件的进步。但是,仅仅进行局部的、支离破碎的改进是不足够。本文介绍了基于模型的设计和产品代码生成的一个完整的软件工程化框架,并且还给出了具体的方法和工具,意在表明它并非仅仅是一种理论,而是既实用又有效。
(转载)