4. 代码生成核心配置项
Embedded Coder 的代码生成结果并不是由模型单独决定的,而是由模型与一组配置参数共同决定。同一张模型,只要系统目标文件、硬件实现或代码风格不同,生成的 C 文件在函数签名、数据类型、文件划分和注释密度上都会明显不同。因此,工程化配置的第一步不是急着点“生成代码”,而是先把 Configuration Parameters 中与代码生成直接相关的几组参数固定下来,形成可复用的配置集(Configuration Set),再绑定到模型上。
本节围绕七类核心配置项展开:系统目标文件、语言标准、硬件实现、代码风格、注释、文件打包与报告选项。它们之间存在明确的依赖顺序,下图给出了配置项之间的依赖与作用关系。
系统目标文件:决定代码生成框架
系统目标文件(System target file,STF)是代码生成的总开关,它决定了使用哪一套 TLC 脚本框架来生成代码。工程中最常用的三个选择是:grt.tlc(通用实时目标,适合快速验证)、ert.tlc(嵌入式实时目标,适合量产嵌入式代码)、autosar.tlc(AUTOSAR 目标,用于符合 AUTOSAR 规范的 ECU 软件)。选择 ert.tlc 后,代码生成器会启用更紧凑的数据结构、更少的运行时开销,并支持单精度浮点、可重入函数等嵌入式常用特性。在 Configuration Parameters → Code Generation → System target file 中通过 Browse 选择,选择后界面会自动切换到 Embedded Coder 的配置视图。
语言标准:与工具链保持一致
语言标准在 Code Generation → Language 中设置,可选 C 或 C++,并进一步指定标准版本。对于 C 代码,常用 C99 (ISO),它支持 // 行注释、混合声明与语句、变长数组等特性,绝大多数嵌入式编译器(GCC、IAR、Keil、Tasking)都支持。若目标编译器只支持 C89,则必须选择 C89/C90 (ANSI),此时生成代码不会使用 // 注释和混合声明。选择 C++ 时通常配合 C++11 (ISO),用于需要类封装或模板的工程。语言标准一旦确定,应与实际编译器的 -std= 选项严格一致,否则会出现“生成代码能编译但行为异常”的隐蔽问题。
硬件实现:决定数据类型映射
硬件实现(Hardware Implementation)是很多初学者忽略但影响最大的配置项。它定义了目标处理器的字长、字节序、整数类型对应的 C 类型,以及是否支持浮点。在 Hardware Implementation → Device vendor 中选择厂商(如 ARM Compatible、Texas Instruments、Intel),再选择 Device type(如 ARM Cortex-M)。关键参数包括:char 是否为 8 位、short 是否为 16 位、int 是否为 32 位、long 是否为 32 位或 64 位、字节序为 Little-endian 还是 Big-endian。例如在 ARM Cortex-M 上,典型配置为:char=8、short=16、int=32、long=32、long long=64、float=32、double=64、Little-endian。这些设置直接决定 Simulink 中 int32、uint16 等数据类型映射到 C 代码中的哪个关键字,也决定定点运算的溢出行为。
代码风格:让生成代码符合团队规范
代码风格配置位于 Code Generation → Code Style,主要控制标识符命名、括号风格、缩进和换行。常用选项包括:Parentheses level(括号层级,可选 Nominal 或 Maximum)、Preserve operand order in expression(是否保持运算顺序)、Convert if-elseif-else to switch(是否将多分支转换为 switch)、Suppress unlimited length(是否限制行宽)。标识符命名规则在 Code Generation → Identifiers 中设置,可指定函数名、变量名、类型名的最大长度和大小写风格。例如团队规范要求函数名不超过 31 字符、使用 模块名_功能名 格式,就可以在 Maximum identifier length 中设为 31,并通过 Custom token 定制前缀。代码风格配置的价值在于:生成代码可以直接进入团队的静态检查流程,而不需要人工二次格式化。
注释:可追溯性的关键
注释配置在 Code Generation → Comments 中。Embedded Coder 支持在生成代码中插入模型版本、模块路径、模块参数、Simulink 版本等信息。常用选项包括:Simulink block comments(是否包含模块注释)、MATLAB source comments(是否包含 MATLAB 函数注释)、Generate comments for model(是否生成模型级注释)、Include comments(是否包含注释)。工程上建议至少开启模块路径注释和模型版本注释,这样当代码在 HIL 或台架测试中出现问题时,可以通过注释快速定位到对应的 Simulink 模块。注释密度过高会增大代码体积,过低则失去可追溯性,通常以“每个函数头 + 每个子系统入口”为粒度较为合适。
文件打包与报告选项
文件打包配置位于 Code Generation → Code Packaging,决定生成代码是单文件还是多文件。选择 Single file 时,所有函数和数据类型放在一个 .c 和 .h 中,适合小型模型;选择 Modular 时,每个模型或子系统生成独立的 .c/.h,适合大型工程和团队并行开发。报告选项位于 Code Generation → Report,可勾选 Generate code generation report、Generate static code metrics report、Generate traceability report。报告会以 HTML 形式输出,包含代码文件列表、函数调用关系、静态代码度量(如函数数量、代码行数、圈复杂度)和模型到代码的追溯矩阵。打包选项还支持 Generate makefile 和 Package code and artifacts,后者会生成一个 .zip 包,便于交付给编译集成团队。
Configuration Set,通过 setActiveConfigSet 或 Simulink.ConfigSet 脚本绑定到模型,避免每次手动重复设置。配置集可以导出为 .mat 或 .m 文件,纳入版本管理。配置示例:一个 ARM Cortex-M 工程的参数表
下面给出一个面向 ARM Cortex-M4、使用 GCC 编译器的工程配置示例,参数值属于教学示例,实际工程需根据编译器手册核对。
| 配置项 | 路径 | 示例值 |
|---|---|---|
| 系统目标文件 | Code Generation → System target file | ert.tlc |
| 语言 | Code Generation → Language | C,C99 (ISO) |
| 设备厂商 | Hardware Implementation → Device vendor | ARM Compatible |
| 设备类型 | Hardware Implementation → Device type | ARM Cortex-M |
| 字节序 | Hardware Implementation → Byte ordering | Little Endian |
| int 字长 | Hardware Implementation → Number of bits: int | 32 |
| 标识符最大长度 | Code Generation → Identifiers | 31 |
| 模块注释 | Code Generation → Comments | 开启 |
| 文件打包 | Code Generation → Code Packaging | Modular |
| 生成报告 | Code Generation → Report | 开启代码生成报告与追溯报告 |
配置完成后,点击 Generate Code,在 Code Generation Report 中检查生成的 .c/.h 文件是否符合预期:函数签名是否使用了正确的数据类型、注释是否包含模块路径、文件划分是否与模型层级一致。若发现数据类型与硬件不匹配,优先回到 Hardware Implementation 检查字长设置;若发现命名不符合规范,回到 Identifiers 调整命名规则。配置项之间是联动的,修改一处后应重新生成并复查报告,而不是只改参数不验证结果。