17.1 基于模型的设计
基于模型设计是一种流程,较之传统软件开发流程而言,使开发者能够更快捷、更高效地进行开发。适用范围包括汽车电子信号处理、控制系统、通信行业和半导体行业。
V字模型开发流程整体描述:
模型本身就是一个可执行的规划书,开发者修改优化模型就是对设计的修缮,修缮之时立刻可以进行设计的验证,无需到编码实现之后通过测试再进行系统验证。
使用基于模型设计流程开发软件有以下优势:
- 在整个项目开发过程中使用统一的设计环境;
- 可以直接将需求与设计链接起来,易于对比变更点,降低设计遗漏的可能性;
- 将测试集成到设计中以持续验证并纠正错误;
- 通过多域仿真优化算法;
- 自动产生嵌入式软件代码;
- 开发标准模块库便于重用;
- 自动生成文档;
- 支持针对硬件目标的设计重用。
17.1.1 需求文档
Requirements for a fast filter
1. Two input
One for signal input and the other for filter coefficient.
2. One output
The output for signals filterd by the filter.
3. Title
There should be a title in the model.
4. Alogrithm
The calculation equation should be display in the model.
17.1.2 根据需求进行设计
17.1.3 需求与设计的挂接
通常需求文档使用Word或者Doors管理,MATLAB为了能将设计规划书与模型关联起来,通过rmi setup注册Active-X controls后Simulink Model菜单栏增加了需求追踪功能,通过这个功能追加Simulink链接到需求设计规划书的Word文档中,在每一项需求设计条目后都会出现Simulink的小图标,能够从需求文档链接到模型;可通过链接检查需求变更是否及时反映到所设计的模型中,以保持设计文档和模型的一致性。
17.1.4 模型的仿真
17.1.5 模型的性能分析及修正
使用模型生成代码,特别是产品级代码生成时,所用模型必须按照特定规则进行审查。在工业自动化生产、汽车电子开发过程中,随着模型复杂度的提高,人工检查模型属性、配置及对于MAAB标准的遵守度逐渐成为负担,使用Simulink工具栏中的Model Advisor工具可以自动进行标准及模型参数配置和属性的检查,并产生检查报告。
检查的内容有:
- 是否会导致系统仿真出错;
- 是否会导致生成的代码无效;
- 生成的代码是否符合安全标准。
17.1.6 模型效率分析与优化
使用Profile Report了解模型每个环节的时间消耗和各种子方法的调用次数。
17.1.7 模型的代码生成
Simulink的Simulink Coder工具箱提供了将模型转换为可优化的嵌入式C代码的功能,将模型的信号源和信号接收部分模块替换为输入/输出端口,系统文件使用ert.tlc,负责统筹调用代码生成的整个过程,将模块转换为相应的C代码,只不过这时的C代码并非专门面向某种嵌入式芯片的,而是未经过优化的通用性嵌入式代码,可读性不强。
17.1.8 模型生成代码的优化
Simulink的Embedded Coder工具箱提供了两方面的优化,一是通过对信号线的存储类型进行设置改变代码生成时的变量生成方式,二是通过结构化的思想将算法模型构成一个原子子系统,并将代码生成在指定文件的指定函数内,便于移植或重用。
17.1.9 代码的有效性验证
Processor In the Loop Simulation(PILS,处理器在环仿真)提供了验证算法有效性的方法。
17.1.10 其他验证方法
17.2 Simulink代码生成流程及技巧
在Simulink环境中,嵌入式代码是由Embedded Coder、Simulink Coder为主导,MATLAB Coder辅助器进行生成代码优化。主要应用目标为嵌入式MCU,片上快速原型开发板,以及应用于民生电子、工业领域的MCU微处理器等。
17.2.1 代码生成时的模型配置方法
example.slx
Configuration Parameter中集中管理着模型的代码生成方法、格式等约束条件。为了生成嵌入式代码,至少需要配置3部分:解算器Solver、系统目标文件(如ert.tlc)、硬件实现规定Hardware Implementation。
solver
解算器必须采用固定点类型,没有连续状态时可选discrete,步长默认为auto,在简单通用嵌入式代码生成过程中此参数没有实际作用。
当模型中使用参数变量,如Gain的增益值,在生成代码是,如果希望使用该参数的值直接展开到代码中,就需要设置参数内联选项,在Code Generation→Optimization中有Default parameter behavior选项。
可调:
P_example_T example_P = { 5.0 /* Variable: k * Referenced by: '/Gain' */ }; void example_step(void) { example_Y.Out1 = (example_P.k * example_U.In1 + example_U.In2) * example_U.In3; }
内联:(此时缺少model_data.c文件)
void example_step(void) { example_Y.Out1 = (5.0 * example_U.In1 + example_U.In2) * example_U.In3; }
当选择Inlined后,代码生成时模型的参数将以常数方式直接生成到代码逻辑中,不再以一个参数变量的形式生成。当模型中的参数需要作为实时可以调节的参数生成到代码中时,选择Tunable,参数将作为变量生成。如果不需要实时调节参数,可以选择节省存储空间的方式Inlined。
MATLAB2014a中该选项以勾选框的形式给出。
Hardware Implementation
Hardware Implementation选项是规定目标硬件规格的选项。在这个选项卡中可以配置芯片的厂商和类型,设置芯片的字长、字节顺序等。
另一个关键的设置选项是控制整个代码生成过程的系统目标文件System Target File,ert.tlc文件是Embedded Coder提供的能够生成专门用于嵌入式系统C代码的系统目标文件。在Code Generation页面中的Browser按钮可以选择系统目标文件。
Code Generation对比:
另外2018a拥有搜索功能:
Report
在Report子标签中有关于生成代码报告的页面,通过勾选框可以选择是否在模型编译结束后自动打开。
在Advanced parameters中可以选择是否在代码报告中追加模型与代码的双向追踪,并选择追踪的内容
勾选Metrics中的Static code metrics时,将会在代码生成报告中包含静态代码的参数指标。
Comments
在comments子标签中包含对生成代码中注释内容的配置。
Include comments选项的勾选决定是否在生成代码中添加Simulink自带的注释。注释中带有可以从代码跳转到对应模块的超链接,方便读者追溯模块与代码的对应关系,建议勾选。
Symbol
symbol子标签页面用于设置ert.tlc一族系统目标文件控制下的代码生成不变定义规则。这些符号包括数据变量和数据类型定义、常亮宏、子系统方法、模块的额输出变量、局部临时变量及命令的最长字符数等。
控制代码生成的标示符:
标示符 | 作用说明 |
$R | 表示根模型的名字,将C语言不支持的字符替换为下划线 |
$N | 表示Simulink对象:模块、信号或信号对象、参数、状态等的名字 |
$M | 为了避免命名冲突,必要时追加后缀以示区分 |
$A | 表示数据类型 |
$H | 表示系统层级标示符,对于根层次模块root_,对于子系统模块sN_,N是Simulink分配的系统编号 |
$F | 表示函数名,如表示更新函数时使用_Update |
$C | 校验和标示符,用于防止命名冲突 |
$I | 表示输入/输出标示符,输入端口使用u表示,输出端口则用y表示 |
通过上表中各种标示符的不同组合,即可规定生成代码中各部分的名称的生成规则。推荐使用默认设置。
Custom Code
Custom Code子标签主要用于添加用户自定义的或者编译模型时必需的源文件、头文件、文件夹或者库文件等。
Debug
原Debug子标签页面,新版Code Generation→Advanced parameters中,可以对编译过程和TLC过程的相关选项进行设置。
Verbose build的勾选可以将编译过程信息显示在Command Window中。Retain .rtw file则能够保留编译模型生成的rtw文件。rtw文件是代码生成过程中从Simulink模型得到的中间文件,它记录了模型相关的所有需要被TLC文件使用的信息。下面关于TLC的几组参数能够启动TLC文件的profile功能和调试功能,使得开发者能够对TLC语言文件进行断点调试、单步调试等动作,以及了解TLC语句的覆盖度等情况。
Interface
Software E、environment组的参数中提供CPL(Code replacement library)的选择,CPL中定义一个表,根据表格将Simulink模块与所对应的目标语言的数学函数及操作函数库挂接,以便从模型生成代码。Support参数组中每个选择框代表一种嵌入式编码器对代码生成的支持功能,其中一些功能需要Simulink提供的头文件来支持才能编译为目标文件的,这些头文件一部分存储在MATLABroot\simulink\include文件夹中,一部分是在模型生成代码的过程中自动生成的(rt_开头的文件)。
选择框条目 | 所需头文件 |
floating-point numbers | rtw_solver.h |
non-finite numbers | rt_nonfinite.h |
complex numbers | - |
absolute time | - |
continuous time | rt_continuous.h |
variable-size signals | - |
Code interface与Data Exchange参数组用来配置生成代码的接口及数据记录的方式,如无特殊要求建议使用默认配置。
Verification
Verification子标签页面主要是关于代码验证方式SIL与PIL的配置,是否使能代码中函数执行时间记录、代码覆盖度记录,以及是否创建用于SIL与PIL的模型等。
Code Style
Code Style子标签页面提供了一些关于代码风格的选择框选项,如if else分支的完整性确保,if else与switch case语句的选用,生成括号的频度,是否保留函数声明中extern关键字等。
Template
Template子标签页面内为嵌入式编码器提供了一族默认的代码生成模板。
ert_code_template.cgt中使用TLC变量方式规定了文件生成的顺序及添加模型信息注释的位置。模型生成的源文件、头文件及全局数据存储和外部方法声明文件的生成可以使用统一模板。
File customization Template则提供给用户自定义代码生成过程的文件输入,用户根据应用场景需要可以调用读入/写入目标硬件的TLC文件、自定义函数或注释,甚至根据模型的单速率/多速率不同分别调用不同的主函数模板等。
ert_code_template.cgt中主要规定了代码段的顺序。
Generate an example main program提供是否生成一个示例主函数的选项。这个示例主函数名为ert_main.c,包含一个main()函数和一个调度器代码。主函数调用模型初始化函数model_initialize()初始化模型需要的数据,以及复位异常状态标志;调度器代码仅提供一个模型每个采样时间点应该执行的函数模板rt_Onestep(),此函数应该绑定到目标硬件的定时器中断上作为其中断服务函数(ISR),执行周期应该与模型基频(即固定点解算器的步长)一致,内部应该调用模型单步函数model_step()。另外,rt_Onestep()内部应该对其调用进行溢出检测。
Code Placement
Code Placement子标签页面提供的选项将影响生成代码的组织方式和数据存储方式及头文件包含的分隔符选择等。
File packaging format表示文件的组织方式。
File packaging format | 生成的文件列表 | 省去的文件列表 |
Modular | model.c subsystem files(optional) model.h model_types.h model_private.h model_data.c(conditional) |
- |
Compact(with separate data file) | model.c model.h model_data.c(conditional) |
model_types.h model_private.h |
Compact | model.c model.h |
model_types.h model_private.h model_data.c |
省去的只是文件个数,其内容被合并到了其他文件中。
省去的文件 | 内容转移目标 |
model_data.c | model.c |
model_private.h | model.c和model.h |
model_types.h | model.h |
Data Type Replacement
该子标签页提供一个选择框,勾选之后出现3列数据类型列表。
前两列按照数据类型的对应关系给出了每种数据类型在Simulink和嵌入式编码器生成代码中的类型名,第3列工用户设置,填入自定义的类型名之后 ,生成代码时将使用自定义的类型名替换Code Generation Name。用户填入的自定义类型名不仅是一个别名字符串,还必须在Base Workspace中定义其作为Simulink.AliasType类型对象才可以。第3列不必全部填满。
Memory section
Memory section(新版Code Generation→Advanced parameters中)可以设置函数、常数、输入/输出、数据和参数的存储段。存储段的设置主要面向模型等级函数和顶层模型的内部数据。
完成配置后按下Ctrl+B或者在Command Window中输入rtwbuild(gcs),即启动模型编译。
>> rtwbuild(gcs) ### Starting build procedure for model: example ### Generating code and artifacts to 'Model specific' folder structure ### Generating code into build folder: C:\Users\lenovo\Desktop\example_ert_rtw ### Invoking Target Language Compiler on example.rtw ### Using System Target File: D:\matlab2018a\rtw\c\ert\ert.tlc ### Loading TLC function libraries ...... ### Initial pass through model to cache user defined code . ### Caching model source code ....................... ### Writing header file example_types.h ### Writing header file example.h . ### Writing header file rtwtypes.h ### Writing source file example.c ### Writing header file example_private.h ### Writing source file example_data.c ### Writing source file ert_main.c ### TLC code generation complete. .### Creating HTML report file example_codegen_rpt.html ### Using toolchain: LCC-win64 v2.4.1 | gmake (64-bit Windows) ### Creating 'C:\Users\lenovo\Desktop\example_ert_rtw\example.mk' ... ### Successful completion of code generation for model: example
若勾选了生成报告的选项,则编译完成会自动弹出Code Generation Report。
若配置无误,编译成功,在与模型名相同的.c文件中会包含model_step()函数,此处为example_step(),这里的代码表示模型所搭建的逻辑。
17.2.2 代码生成的流程
模型生成代码的顺序之前已经提及,首先通过 rtwbuild命令将模型编译为rtw文件,Simulink Coder中的目标语言编译器(Target Language Compiler)将rtw文件转换为一系列的源文件,在这个过程中TLC所使用的文件包括3类:系统目标文件(ert.tlc、grt.tlc等)、模块的目标文件(如与S函数配套的TLC文件)和支持代码生成的TLC函数库等文件。
模型的源代码全部生成之后,可以使用Simulink提供的模板自动生成makefile来编译链接得到目标文件,也可以将生生成的源代码加入到目标芯片所使用的编译集成环境IDE的工程项目中去,使用IDE编译链接,最终通过仿真器下载到目标硬件中进行实机运行。
6个更细致的阶段:Entry、Before TLC、After TLC、Before Make、After Make和Exit。在保持顺序执行的前提下,每个阶段都可以由用户追加一些自定义行为,进行模型内部约束关系的检查,或者是链接外部第三方开发工具等。
在Entry阶段,可以对自定义目标进行预配置参数配置和检验等操作;Before TLC是代码生成之前的阶段,可以将需要用到的编译信息存储到一个结构体中管理,或者将编译需要的头文件、源文件和库文件等进行路径定位和添加;After TLC是代码生成之后的阶段,可以将生成代码文件夹需要的文件拷贝到目标芯片的集成编译环境工程文件夹内以备使用;在Before Make阶段可以对代码进行分析、验证和模型或模块的用户设置检测等;After Make则可以通过MATLAB控制集成编译环境自动生成工程文件,更新其中生成的代码列表,并自动编译链接及下载到目标硬件中;Exit阶段则可以将整个过程是否顺利执行的信息进行显示或临时变量清除等操作。
rtw文件
rtw文件作为模型编译器的输入文件和编译过程的中间产物,记录了模型创建信息和编译信息、名字与版本号、配置参数集、输入输出、参数等所有信息。在原Debug子标签页面,新版Code Generation→Advanced parameters中,可以选择保留。
rtw文件的构成元素是record,称为记录,格式如下:
recordName{itemName itemValue}
rtw文件的这一条条记录是按照层次进行划分的,最上层是CompiledModel,具有全局的访问范围,向内注册呢个分别是System、block,每条记录都由一个统领关键字和一对{ }构成,{ }内部成为统领关键字的域,访问域中成员与结构体访问的方法一致。如:
CompiledModel.Subsystem[0].Block[0].Parameter.Value;
追加信息使用addtorecord命令,如:
% addtorecord CompiledModel Author{Name "Custom"}
TLC文件
tlc文件即TLC编译器所编译的目标文件。
- 系统目标文件:规定生成代码的全局结构,以匹配所支持的目标芯片群及目标语言。
- 模块目标文件:规定Simulink模块生成代码时的代码实现,一般与模块的S函数同名,存储在同一文件夹下,并从S函数中获取参数信息以生成代码。
在TLC运行阶段,首先运行的就是系统目标文件,如ert.tlc,系统目标文件是TLC运行的起点,其他TLC文件会被其调用,整个执行过程按照TLC命令行逐一执行。TLC文件执行过程中,会读取、增加或修改rtw文件中的记录信息。
17.2.3 代码生成方法与技巧
Simulink模代码生成的结构