Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

自定义系统目标文件

本节提供关于系统目标文件结构的信息、自定义系统目标文件的规范以及帮助您生成框架性系统目标文件的基本教程。

使用系统目标文件控制代码生成

系统目标文件控制编译过程的代码生成阶段。系统目标文件还使您能够控制以什么样的表示方式将您的目标显示给最终用户。系统目标文件提供

  • 对编译过程至关重要的变量定义,例如 CodeFormat TLC 变量的值

  • 生成代码的顶层 TLC 程序的主要入口点

  • 要显示在系统目标文件浏览器中的目标信息

  • 用于定义目标特定的代码生成选项(以及与编译过程相关的其他参数)并在“配置参数”对话框中显示这些选项的机制

  • 从其他目标(例如嵌入式实时 (ERT) 目标)继承选项的机制

请注意,虽然系统目标文件是目标语言编译器 (TLC) 文件,但它包含嵌入式 MATLAB® 代码。在创建或修改系统目标文件之前,您应该掌握 TLC 和 MATLAB 语言的相关知识。目标语言编译器脚本与函数中介绍了 TLC 和 MATLAB 语言的特点和语法。

阅读本节内容时,您可能需要参考代码生成器提供的系统目标文件。这些文件大部分存储在 matlabroot/rtw/c 文件夹(打开)下的目标特定的文件夹中。其他系统目标文件存储在 matlabroot/toolbox/rtw/targets打开)下。

系统目标文件命名和位置约定

系统目标文件必须位于 MATLAB 路径上的文件夹中,这样才能使目标显示在系统目标文件浏览器中并在编译过程中得到调用。请遵循Folder and File Naming Conventions中提供的系统目标文件和相关目标文件的位置和命名约定。

系统目标文件的结构

概述

本节介绍系统目标文件的结构和内容。下面的列表显示了系统目标文件的一般结构。请注意,这不是系统目标文件的完整代码列表,只是从构成系统目标文件的每个部分中摘录的片段。

%%----------------------------
%% Header Comments Section
%%----------------------------
%% SYSTLC: Example Real-Time Target
%%    TMF: my_target.tmf MAKE: make_rtw
%% Initial comments contain directives for STF Browser.
%% Documentation, date, copyright, and other info may follow.
          ...
%selectfile NULL_FILE
         ...
%%----------------------------
%% TLC Configuration Variables Section
%%----------------------------
%% Assign code format, language, target type.
%%
%assign CodeFormat = "Embedded-C"
%assign TargetType = "RT"
%assign Language   = "C"
%%
%%----------------------------
%% TLC Program Entry Point
%%----------------------------
%% Call entry point function.
%include "codegenentry.tlc"
%%
%%----------------------------
%% (OPTIONAL) Generate Files for Build Process
%%----------------------------
%include "mytarget_genfiles.tlc"
%%----------------------------
%% RTW_OPTIONS Section
%%----------------------------
/%
  BEGIN_RTW_OPTIONS
  %% Define rtwoptions structure array. This array defines target-specific
  %% code generation variables, and controls how they are displayed.
  rtwoptions(1).prompt = 'example code generation options';
        ...
  rtwoptions(6).prompt = 'Show eliminated blocks';
  rtwoptions(6).type = 'Checkbox';
         ...
  %----------------------------------------%
  % Configure RTW code generation settings %
  %----------------------------------------%
         ...
  %%----------------------------
  %% rtwgensettings Structure
  %%----------------------------
  %% Define suffix text for naming build folder here.
  rtwgensettings.BuildDirSuffix = '_mytarget_rtw'
  %% Callback compatibility declaration
  rtwgensettings.Version = '1';

  %% (OPTIONAL) target inheritance declaration
  rtwgensettings.DerivedFrom = 'ert.tlc';
  %% (OPTIONAL) other rtwGenSettings fields...
         ...
  END_RTW_OPTIONS
%/
%%----------------------------
%% targetComponentClass - MATHWORKS INTERNAL USE ONLY
%% REMOVE NEXT SECTION FROM USER_DEFINED CUSTOM TARGETS
%%----------------------------
/%
  BEGIN_CONFIGSET_TARGET_COMPONENT
  targetComponentClass = 'Simulink.ERTTargetCC';
  END_CONFIGSET_TARGET_COMPONENT
%/

如果您基于现有系统目标文件创建自定义目标,则必须删除 targetComponentClass 部分(指令 BEGIN_CONFIGSET_TARGET_COMPONENTEND_CONFIGSET_TARGET_COMPONENT 之间的部分)。此部分预留给 MathWorks 内部开发的目标使用。

标头注释

文件开头的这几行采用 TLC 注释的格式。它们为系统目标文件浏览器和编译过程提供必要的信息。请注意,必须将浏览器注释放在文件头部,位于其他注释或 TLC 语句之前。

注释的存在使代码生成器能够检测到系统目标文件。打开系统目标文件浏览器时,代码生成器将扫描 MATLAB 路径中是否存在具有格式化标头注释的 TLC 文件。注释中包含以下指令:

  • SYSTLC:显示在浏览器中的描述符。

  • TMF:要在编译过程中使用的模板联编文件 (TMF) 的名称。选择目标后,此文件名将显示在“配置参数”对话框的代码生成窗格的Template makefile字段中。

  • MAKE:要在编译过程中使用的 make 命令。选择目标后,此命令将显示在“配置参数”对话框的代码生成窗格的 Make 命令字段中。

以下标头注释来自 matlabroot/rtw/c/ert/ert.tlc

%% SYSTLC: Embedded Coder TMF: ert_default_tmf MAKE: make_rtw
%% SYSTLC: Create Visual C/C++ Solution File for Embedded Coder
.
.
.

每个注释最多只能包含两行。

如果不指定系统目标文件中的 TMF 字段,该文件仍然有效。要更改 TemplateMakefile 参数的值,您可以改用由 rtwgensettings.SelectCallback 指定的回调函数。

您也可以使用 rtwgensettings.SelectCallback 指定的回调函数来更改外部模式参数 ExtModeExtModeTransportExtModeMexFileExtModeIntrfLevel 的值。

您可以在标头注释中指定多组指令。每一组指令在系统目标文件浏览器中显示为一种不同的目标配置。在上面的示例中,前两行代码指定 ERT 目标的默认配置。接下来两行指定创建和编译 Microsoft® Visual C++® 解决方案 (.sln) 文件的配置。下图显示了这些配置在系统目标文件浏览器中的显示方式。

有关自定义标头注释的示例,请参阅创建自定义目标配置

TLC 配置变量

系统目标文件中的这一节介绍与整个代码生成过程有关的为全局 TLC 变量赋值的内容。

对于嵌入式目标,大多数情况下只需使用 ERT 目标 (ert.tlc) 使用的全局 TLC 变量设置。特别重要的是,您的系统目标文件必须为 CodeFormat TLC 变量使用 'Embedded-C' 值,并在 TLC 文件的 RTW_OPTIONS 部分使用对应的 rtwgensettings.DerivedFrom = 'ert.tlc'。验证并确认已为以下变量赋值:

  • CodeFormat:CodeFormat TLC 变量选择生成的代码的功能。此变量的 'Embedded-C' 值由 ERT 目标使用。基于 ERT 的目标应指定 'Embedded-C' 作为 CodeFormat 的值。此选项的作用是实现生产代码、最小化内存使用量、静态内存分配以及为生成的代码提供简化接口。

    要了解 CodeFormat TLC 变量的其他值的相关信息,请参阅比较各产品的系统目标文件支持

  • Language:唯一有效的值是 C,它支持由配置参数 TargetLang 指定的 CC++ 代码生成。

  • TargetType:代码生成器定义预处理器符号 RTNRT,以区分仿真代码和实时代码。这两个符号在条件编译中使用。TargetType 变量确定定义的是 RT 还是 NRT

    大多数目标都设计用来生成实时代码。它们按如下方式为 TargetType 赋值。

    %assign TargetType = "RT"

    而有些目标(比如模型引用仿真目标、加速仿真目标、RSim 目标和 S-Function 目标)生成的代码则仅在非实时时间使用。这些目标按如下方式为 TargetType 赋值。

    %assign TargetType = "NRT"

TLC 程序入口点和相关的 %include 指令

代码生成过程通常以 codegenentry.tlc 开始。系统目标文件调用 codegenentry.tlc,如下所示。

%include "codegenentry.tlc"

注意

codegenentry.tlc 和底层 TLC 文件都假定已为 CodeFormatTargetTypeLanguage 赋值。请在包含 codegenentry.tlc 之前设置这些变量。

如果您需要实现目标特定的代码生成功能,应在您的系统目标文件中包含 TLC 文件 mytarget_genfiles.tlc。此文件提供了在调用 codegenentry.tlc 前后执行自定义 TLC 代码的机制。有关此机制的信息,请参阅:

自定义代码生成过程的另一种方法是直接调用底层函数(通常由 codegenentry.tlc 调用),并在代码生成过程的每个阶段包含您自己的 TLC 函数。采用这种方法应慎重。有关详细信息,请参阅TLC 文件

codegenentry.tlc 调用的底层函数包括:

  • genmap.tlc:将模块名称映射到对应的语言特定的模块目标文件。

  • commonsetup.tlc:设置全局变量。

  • commonentry.tlc:开始代码生成过程。

RTW_OPTIONS 部分

RTW_OPTIONS 部分须置于以下指令之间:

/%
  BEGIN_RTW_OPTIONS
.
.
.
  END_RTW_OPTIONS
%/

RTW_OPTIONS 的第一部分定义 rtwoptions 结构体数组。使用 rtwoptions 显示自定义目标选项中介绍了这种结构体。

RTW_OPTIONS 的第二部分定义 rtwgensettings 结构体,它定义代码生成过程的编译文件夹名称和其他设置。有关 rtwgensettings 的信息,请参阅 rtwgensettings 结构体

rtwgensettings 结构体

系统目标文件的最后一部分定义 rtwgensettings 结构体。此结构体存储写入 model.rtw 文件并由编译过程使用的信息。目标开发人员最常用到的 rtwgensettings 字段包括

  • rtwgensettings.Version:使用此属性启用 rtwoptions 回调,并在 rtwgensettings.SelectCallback 中使用回调 API。

    注意

    要使用回调,您必须rtwgensettings.Version 设置为非空值。例如:

    rtwgensettings.Version = '1';
    

    将上面的语句添加到系统目标文件的配置 RTW 代码生成设置部分。

  • rtwgensettings.DerivedFrom:此结构体字段定义要从中继承选项的系统目标文件。请参阅继承目标选项

  • rtwgensettings.SelectCallback:此结构体字段指定 SelectCallback 函数。您必须将 rtwgensettings.Version 设置为非空值,否则您的回调将被忽略。SelectCallback 与目标关联,而不是与目标的任何选项关联。通过设置系统目标文件配置参数选择目标时,将触发 SelectCallback 函数。

    SelectCallback 函数用于设置(或禁用)特定于目标的配置参数。

    以下代码安装 SelectCallback 函数:

    rtwgensettings.SelectCallback = 'my_select_callback_handler(hDlg,hSrc)';

    SelectCallback 函数的参量 (hDlg, hSrc) 是回调 API 函数使用的私有数据的句柄。

    注意

    如果您开发了自定义目标并希望它与模型引用兼容,则必须实现 SelectCallback 函数来声明模型引用兼容性。请参阅Support Model Referencing

  • rtwgensettings.ActivateCallback:此属性指定 ActivateCallback 函数。当模型的活动配置集发生更改时,将触发 ActivateCallback 函数。这可能会在加载模型的过程中发生,也可能会在用户更改活动配置集时发生。

    以下代码安装 ActivateCallback 函数:

    rtwgensettings.ActivateCallback = 'my_activate_callback_handler(hDlg,hSrc)';

    ActivateCallback 函数的参量 (hDlg,hSrc) 是回调 API 函数使用的私有数据的句柄。

  • rtwgensettings.PostApplyCallback:此属性指定 PostApplyCallback 函数。当用户在“配置参数”对话框中编辑选项后点击应用确定按钮时,将触发 PostApplyCallback 函数。当更改应用于配置集后,将调用 PostApplyCallback 函数。

    以下代码安装 PostApplyCallback 函数:

    rtwgensettings.PostApplyCallback = 'my_postapply_callback_handler(hDlg,hSrc)';

    PostApplyCallback 函数的参量 (hDlg, hSrc) 是回调 API 函数使用的私有数据的句柄。

  • rtwgensettings.BuildDirSuffix:为了标识由编译过程创建的编译文件夹,大多数系统目标文件都会定义一个文件夹名称后缀。为了形成编译文件夹名称,编译过程会将 rtwgensettings.BuildDirSuffix 字段中定义的后缀追加到模型名称的后面。您可以通过为 rtwgensettings.BuildDirSuffix 指定新字符串值来修改后缀。例如:

    rtwgensettings.BuildDirSuffix = '_mytarget_rtw'

    编译过程会创建一个名为 model_mytarget_rtw 的编译文件夹。有关详细信息,请参阅编译过程文件夹

    不要使用函数来指定新字符串值。例如:

    rtwgensettings.BuildDirSuffix = my_get_build_suffix(bdroot);

其他代码生成选项

Configure Generated Code with TLC介绍了其他 TLC 代码生成变量。目标的最终用户可以通过输入以下形式的 MATLAB 命令为这些变量赋值

set_param(modelName,'TLCOptions','-aVariable=val');

(有关详细信息,请参阅指定 TLC 以用于代码生成。)

但是,最好还是使用以下形式的语句在系统目标文件中为这些变量赋值:

%assign Variable = val

为了增强可读性,建议您在系统目标文件中配置 RTW 代码生成设置注释的下方添加这些赋值。

模型引用注意事项

有关系统目标文件以及为了支持代码生成器模型引用功能而需要进行的其他修改的重要信息,请参阅Support Model Referencing

定义和显示自定义目标选项

使用 rtwoptions 显示自定义目标选项

通过自定义系统目标文件中的 rtwoptions 结构体,可以控制“配置参数”对话框的代码生成窗格中显示的选项。

rtwoptions 结构体的字段定义要在“配置参数”对话框中显示的变量和关联的用户界面元素。使用 rtwoptions 结构体数组,您可以定义该对话框中显示的目标特定的选项,并将选项按类别进行组织。还可以编写回调函数,以指定如何处理这些选项。

代码生成窗格打开时,系统将扫描 rtwoptions 结构体数组,并显示列出的选项。每个选项由一个指定的用户界面元素(复选框、编辑字段、菜单或按钮)表示,此界面元素显示该选项的当前值。

用户界面元素可以处于启用或禁用(灰显)状态。如果选项处于启用状态,则用户可以更改选项值。如果某个选项被禁用,该选项将使用默认值,并且用户无法更改该选项值。

您也可以使用 rtwoptions 结构体数组来定义触发回调函数执行但不显示在代码生成窗格中的特殊的 NonUI 元素。请参阅 NonUI 元素

rtwoptions 结构体数组的元素被分成几个组。每个组都以 Category 类型的头元素开始。Category 头元素的 default 字段必须包含该类别中其余元素的计数。

Category 头元素的下方是要显示在代码生成窗格上的选项。每个类别中的头后面是一个或多个选项定义元素。

每个类别的目标选项都对应于“配置参数”对话框中代码生成下面列出的选项。

rtwoptions 结构体字段摘要表总结了 rtwoptions 结构体的字段。

示例 rtwoptions 结构体.  以下代码定义一个 rtwoptions 结构体数组。第一个(头)元素的默认字段设置为 4,指示头后面的元素数。

  rtwoptions(1).prompt        = 'userPreferred target options (I)';
  rtwoptions(1).type          = 'Category';
  rtwoptions(1).enable        = 'on';
  rtwoptions(1).default       = 4;   % number of items under this category
                                     % excluding this one.
  rtwoptions(1).popupstrings  = '';  % At the first item, user has to 
  rtwoptions(1).tlcvariable   = '';  % initialize all supported fields
  rtwoptions(1).tooltip       = '';
  rtwoptions(1).callback      = '';
  rtwoptions(1).makevariable  = '';

  rtwoptions(2).prompt        = 'Execution Mode';
  rtwoptions(2).type          = 'Popup';
  rtwoptions(2).default       = 'Real-Time';
  rtwoptions(2).popupstrings  = 'Real-Time|UserDefined';
  rtwoptions(2).tlcvariable   = 'tlcvariable1';
  rtwoptions(2).tooltip       = ['See this text as tooltip'];

  rtwoptions(3).prompt        = 'Log Execution Time';
  rtwoptions(3).type          = 'Checkbox';
  rtwoptions(3).default       = 'on';
  rtwoptions(3).tlcvariable   = 'RL32LogTETModifier';
  rtwoptions(3).tooltip       = ['']; % no tooltip

  rtwoptions(4).prompt        = 'Real-Time Interrupt Source';
  rtwoptions(4).type          = 'Popup';
  rtwoptions(4).default       = 'Timer';
  rtwoptions(4).popupstrings  = 'Timer|5|6|7|8|9|10|11|12|13|14|15';
  rtwoptions(4).tlcvariable   = 'tlcvariable3';
  rtwoptions(4).callback      = 'usertargetcallback(hDlg, hSrc, ''tlcvariable3'')';
  rtwoptions(4).tooltip       = [''];
  rtwoptions(4).tooltip       = ['See TLC file for how to use reserved '...
    ' keyword ''hDlg'', and ''hSrc''.'];
...
  rtwoptions(5).prompt        = 'Signal Logging Buffer Size in Doubles';
  rtwoptions(5).type          = 'Edit';
  rtwoptions(5).default       = '100000';
  rtwoptions(5).tlcvariable   = 'tlcvariable2';
  rtwoptions(5).tooltip       = [''];

第一个元素在“配置参数”对话框中的代码生成下添加了一个用户首选目标选项 (I) 窗格。该窗格显示了 rtwoptions(2)rtwoptions(3)rtwoptions(4)rtwoptions(5) 中定义的选项。

如果要定义很多选项,可在一个系统目标文件中定义多个 Category 组。

请注意,rtwoptions 结构体和回调是使用 MATLAB 代码编写的,虽然它们嵌入在 TLC 文件中。要验证 rtwoptions 结构体定义和代码的语法,可将命令复制并粘贴到 MATLAB 命令行窗口,在 MATLAB 提示符下执行这些命令。

要了解有关 usertarget.tlc 和附带的示例回调文件的详细信息,请参阅包含自定义 rtwoptions 的示例系统目标文件。要查看更多目标特定的 rtwoptions 定义示例,请参阅 matlabroot/rtw/c 文件夹下的 target.tlc 文件。

rtwoptions 结构体字段摘要中列出了 rtwoptions 结构体的字段。

rtwoptions 结构体字段摘要

字段名称描述

callback

有关回调用法的示例,请参阅包含自定义 rtwoptions 的示例系统目标文件

closecallback
(obsolete)

请勿使用 closecallback
应改用 rtwgensettings.PostApplyCallback(请参阅 rtwgensettings 结构体)。

closecallback 将被忽略。

有关回调用法的示例,请参阅包含自定义 rtwoptions 的示例系统目标文件

default

选项的默认值(如果 typePushbutton,则为空)。

enable

必须是 'on''off'。如果是 'on',选项显示为一个启用的项目;否则,显示为一个禁用的项目。

makevariable

与选项关联的模板联编文件标记(如果有)。在处理模板联编文件期间,makevariable 将被展开。请参阅Template Makefile Tokens

modelReferenceParameterCheck指定选项在引用模型和父模型中是否必须具有相同的值。如果未指定此字段或值为 'on',则选项值必须相同。如果指定此字段而值为 'off',则选项值可以不同。请参阅Controlling Configuration Option Value Agreement

NonUI

不显示在界面上,但会用来调用 close 或 open 回调的元素。请参阅 NonUI 元素

opencallback
(obsolete)

请勿使用 opencallback
应改用 rtwgensettings.SelectCallback(请参阅 rtwgensettings 结构体)。

有关回调用法的示例,请参阅包含自定义 rtwoptions 的示例系统目标文件

popupstrings

如果 typePopup,则 popupstrings 定义菜单中的项目。项目之间用 "|"(竖线)分隔。下面的示例定义 GRT 目标使用的 MAT 文件变量名称修饰符菜单中的项目。

'rt_|_rt|none'

prompt

选项的标签。

tlcvariable

与选项关联的 TLC 变量的名称。

tooltip

将鼠标指针悬停在项目上时显示的帮助文本。

type

元素的类型:CheckboxEditNonUIPopupPushbuttonCategory

NonUI 元素.  rtwoptions 数组中类型为 NonUI 的元素仅用于调用回调。NonUI 元素不会显示在“配置参数”对话框中。如果要在打开或关闭对话框时执行与用户界面元素无关联的回调,则可以使用 NonUI 元素。有关示例,请参阅下一节,包含自定义 rtwoptions 的示例系统目标文件

注意

类型为 NonUIEdit 的元素的默认值决定该元素的允许值的集合。

  • 如果默认值为 '0''1'

    • 对于类型 NonUI,元素存储布尔值。

    • 对于类型 Edit,元素存储 int32 类型的值。

  • 如果默认值包含除 '0''1' 以外的整数,则元素中存储 int32 类型的值。

  • 如果默认值不包含整数,则元素被理解为字符向量。

包含自定义 rtwoptions 的示例系统目标文件

本软件提供了一个工作系统目标文件(包含 MATLAB® 文件回调函数),以此为例说明如何使用 rtwoptions 结构体来显示和处理代码生成窗格上的自定义选项。这些示例与回调 API 兼容。

示例目标文件包括:

  • usertarget.tlc:示例系统目标文件。此文件说明如何定义自定义菜单、复选框和编辑字段,还说明如何使用回调。

  • usertargetcallback.m:由菜单调用的 MATLAB® 文件回调。

阅读本节内容时请参考示例文件。示例系统目标文件 usertarget.tlc:说明如何使用 rtwoptions 显示以下自定义目标选项:

  • 执行模式菜单。

  • 记录执行时间复选框。

  • 实时中断源菜单。此菜单执行外部文件 usertargetcallback.m 中定义的回调。与菜单关联的 TLC 变量传递给回调,回调将显示菜单的当前值。

  • 信号记录缓冲大小(双精度)编辑字段。

与“配置参数”对话框中的示例目标选项交互时,请研究一下示例代码。要与示例目标文件交互,请执行以下操作:

  1. 打开您选择的模型。

  2. 打开“配置参数”对话框并选择代码生成窗格。

  3. 点击浏览。将打开系统目标文件浏览器。选择 usertarget.tlc。然后点击确定

  4. 注意代码生成窗格包含一个自定义子选项卡:用户首选目标选项 (I)

  5. 当您与此类别中的选项交互以及打开和关闭“配置参数”对话框时,请观察 MATLAB 命令行窗口显示的消息。这些消息或来自系统目标文件中的代码,或来自从系统目标文件所调用的回调。

继承目标选项

ert.tlc 提供一组基本的 Embedded Coder® 代码生成选项。如果您的目标基于 ert.tlc,则您的系统目标文件通常应继承 ERT 中定义的选项。

可以使用 rtwgensettings 结构体中的 rtwgensettings.DerivedFrom 字段定义要从中继承选项的系统目标文件。您应按以下说明转换您的自定义目标,以使用此机制。

按以下示例所示设置 rtwgensettings.DerivedFrom 字段值:

rtwgensettings.DerivedFrom = 'stf.tlc';

其中 stf 是要从中继承选项的系统目标文件的名称。例如:

rtwgensettings.DerivedFrom = 'ert.tlc';

当“配置参数”对话框执行这行代码时,它会自动包含 stf.tlc 中的选项。如果 stf.tlc 是已转换为新布局的 MathWorks 内部系统目标文件,对话框将使用新布局显示继承的选项。

处理不支持的选项.  如果您的目标不能完全支持从 ert.tlc 继承的选项,您应该检测不支持的选项设置并显示警告或错误消息。在某些情况下,如果用户选择了您的目标不支持的选项,您可能需要中止编译过程。例如,如果您的目标不支持生成示例主程序选项,而此选项被选中,则不应允许编译过程继续下去。

即使您的目标可能无法全部支持继承的 ERT 选项,ERT 选项也要保留在“配置参数”对话框的代码生成窗格中。不要简单地从系统目标文件中的 rtwoptions 结构体中删除不支持的选项。当代码生成器执行优化时,这些选项必须存在于对话框中才能被扫描到。

例如,您可能想要阻止用户关闭单一输出/更新函数选项。那么,从对话框中删除此选项并将 TLC 变量 CombineOutputUpdateFcns 简单地指定为 on 似乎是合理的做法。但是,如果该选项不包含在对话框中,代码生成器会认为输出函数和更新函数需要合并。这样将生成效率较低的代码。

自定义系统目标文件的提示和技巧

简介

以下各节介绍自定义系统目标文件的各种技巧,包括:

  • 如何从系统目标文件中调用自定义 TLC 代码

  • 支持多个开发环境的方法

  • 更新系统目标文件时的注意事项

必需的和推荐的 %include 指令

如果您需要实现目标特定的代码生成功能,我们建议在您的系统目标文件中包含 TLC 文件 mytarget_genfiles.tlc

当您的系统目标文件设置必需的 TLC 环境后,您必须包含 codegenentry.tlc 才能启动标准代码生成过程。

mytarget_genfiles.tlc 提供了一种在主代码生成入口点之后执行自定义 TLC 代码的机制。请参阅使用 mytarget_genfiles.tlc

使用 mytarget_genfiles.tlc.  mytarget_genfiles.tlc(可选)是一个很有用的中心文件,您可从中调用目标特定的 TLC 文件来生成其他文件,作为目标编译过程的一部分。例如,您的目标可能会为开发环境创建子联编文件或工程文件,或者为调试器创建命令脚本以便执行自动下载。

编译过程然后可以直接从 make 进程中调用这些生成的文件,或者在创建可执行文件后调用这些文件。这是通过 STF_make_rtw_hook.m 机制完成的,如使用 STF_make_rtw_hook 文件自定义编译过程所述。

以下 TLC 代码显示了示例 mytarget_genfiles.tlc 文件。

%selectfile NULL_FILE

%assign ModelName = CompiledModel.Name

%% Create Debugger script
%assign model_script_file = "%<ModelName>.cfg"
%assign script_file = "debugger_script_template.tlc"

%if RTWVerbose
   %selectfile STDOUT
   ### Creating %<model_script_file>
   %selectfile NULL_FILE
%endif

%include "%<script_file>"
%openfile bld_file = "%<model_script_file>"
%<CreateDebuggerScript()>
%closefile bld_file

处理目标选项值的别名

本节介绍了一些工具函数,在测试用户为目标设备类型 (ProdHWDeviceType) 和代码替换库 (CodeReplacementLibrary) 所指定的值时,您可以使用这些函数来检测和解析别名值或已有值。

RTW.isHWDeviceTypeEq.  要测试两个目标设备类型值是否表示同一台硬件设备,请调用以下函数:

result = RTW.isHWDeviceTypeEq(type1,type2)

其中 type1type2 是包含目标设备类型值或别名的字符向量。

如果 type1type2 是表示同一台硬件设备的字符向量,则 RTW.isHWDeviceTypeEq 函数返回 true。例如,以下调用返回 true:

RTW.isHWDeviceTypeEq('Specified','Generic->Custom')

有关目标设备类型选项 ProdHWDeviceType 的说明,请参阅硬件实现窗格参数 Device vendorDevice type 的命令行信息。

RTW.resolveHWDeviceType.  要返回硬件设备的设备类型值(假设该值可能是别名或已有值),请调用以下函数:

result = RTW.resolveHWDeviceType(type)

其中 type 是包含目标设备类型值或别名的字符向量。

RTW.resolveHWDeviceType 函数返回设备的设备类型值。例如,以下调用都返回 'Generic->Custom'

RTW.resolveHWDeviceType('Specified')
RTW.resolveHWDeviceType('Generic->Custom')

有关目标设备类型选项 ProdHWDeviceType 的说明,请参阅硬件实现窗格参数 Device vendorDevice type 的命令行信息。

RTW.isTflEq.  要测试两个代码替换库 (CRL) 名称是否表示同一个 CRL,请调用以下函数:

result = RTW.isTflEq(name1,name2)

其中 name1name2 是包含 CRL 值或别名的字符向量。

如果 name1name2 是表示同一个代码替换库的字符向量,则 RTW.isTflEq 函数返回 true。例如,以下调用返回 true:

RTW.isTflEq('GNU','GNU C99 extensions')

有关 CodeReplacementLibrary 参数的说明,请参阅Code replacement library

RTW.resolveTflName.  要返回代码替换库的 CRL 值(假设该值可能是别名或已有值),请调用以下函数:

result = RTW.resolveTflName(name)

其中 name 是包含 CRL 值或别名的字符向量。

RTW.resolveTflName 函数返回引用的代码替换库的值。例如,以下调用都返回 'GNU C99 extensions'

RTW.resolveTflName('GNU')
RTW.resolveTflName('GNU C99 extensions')

有关 CodeReplacementLibrary 参数的说明,请参阅Code replacement library

支持多个开发环境

您的目标可能需要支持多个开发环境(例如,两个或多个交叉编译器)或多个代码生成模式(例如,是为编译器生成一个二进制可执行文件还是生成一个工程文件)。

要满足这项要求,一种方法是实现多个系统目标文件。每个系统目标文件为开发环境调用一个模板联编文件。这相当于提供两个单独的目标。

更新您的自定义系统目标文件

更新自定义系统目标文件可能会影响使用更新后的系统目标文件加载的模型的选项值。如果禁用某个选项,更新后的系统目标文件将使用该选项的默认值。如果模型对该选项具有不同值,则当您用更新后的系统目标文件加载模型时,模型中的值将被丢弃,而系统目标文件将使用默认值。

创建自定义目标配置

简介

本教程将指导您创建一个基于 ERT 的目标 my_ert_target。此练习说明了以下几个任务,它们是创建自定义目标的典型任务:

  • 设置目标文件夹并修改 MATLAB 路径。

  • 修改标准系统目标文件和 TMF,使自定义目标在系统目标文件浏览器中可见、继承 ERT 选项、显示目标特定的选项并使用基于主机的默认编译器生成代码。

  • 使用自定义目标和包含一个内联 S-Function 的简单模型测试编译过程。

在本练习中,您将实现一个可操作的、但较为基础的基于 ERT 的目标。此目标可作为完整实现自定义嵌入式目标的一个起点。

my_ert_target 概述

在以下各节,您将创建一个较为基础的目标 my_ert_target。此目标继承并支持 ERT 目标的标准选项,还在“配置参数”对话框中显示目标特定的附加选项(请参阅 my_ert_target 的目标特定的选项)。

my_ert_target 的目标特定的选项

my_ert_target 支持基于工具链的编译,生成可在主机系统上运行的代码和可执行文件。在 Microsoft Windows® 平台上,my_ert_target 使用 lcc 编译器,该编译器随代码生成器一起分发。

如果您尚未在您的 Microsoft Windows 平台上安装支持的编译器,软件将使用 lcc 进行 C 代码编译。

注意

lcc-win64 编译器在以后的版本中将会删除。有关支持的编译器的信息,请参阅 https://www.mathworks.com/support/requirements/supported-compilers.html

注意

在 Linux® 系统上,请确保您已安装 C 编译器。如果已经安装,则可以使用 Linux 文件夹语法来完成此练习。

my_ert_target 也可以支持基于模板联编文件的编译。有关将此目标与模板联编文件方法一起使用的详细信息,请参阅创建基于 ERT 的模板联编文件

您可以使用与 ERT 目标兼容的模型(请参阅配置系统目标文件 (Embedded Coder))来测试 my_ert_target。生成的程序与 ERT 生成的程序以相同的方式运行。

要简化您的目标测试,请使用 targetmodel 进行测试,这是一个非常简单的定步长模型(请参阅创建测试模型和 S-Function)。targetmodel 中的 S-Function 模块使用 timestwo 示例中的源代码,并生成完全内联的代码。有关 timestwo 示例 S-Function 的进一步讨论,请参阅 S-Function ExamplesInline S-Functions with TLC

创建目标文件夹

遵循建议的约定创建存储目标文件的文件夹,并将它们添加到 MATLAB 路径中(请参阅Folder and File Naming Conventions)。还要创建一个文件夹来存储测试模型、S-Function 和生成的代码。

此示例假定您的目标和模型文件夹位于文件夹 c:/work 中。不要将您的目标和模型文件夹放在 MATLAB 文件夹树中(即,在 matlabroot 文件夹中或在此文件夹下)。

要创建文件夹并使它们可访问,请执行以下操作:

  1. 创建目标根文件夹 my_ert_target。在 Windows 平台上,从 MATLAB 命令行窗口中输入:

    cd c:/work
    mkdir my_ert_target
  2. 在目标根文件夹中创建一个子文件夹,以存储您的目标文件。

    mkdir my_ert_target/my_ert_target
  3. 将这些文件夹添加到您的 MATLAB 路径中。

    addpath c:/work/my_ert_target
    addpath c:/work/my_ert_target/my_ert_target
  4. 创建文件夹 my_targetmodel,以存储测试模型、S-Function 和生成的代码。

    mkdir my_targetmodel

创建基于 ERT 的、与工具链兼容的系统目标文件

通过复制和修改 ERT 目标的标准系统目标文件,为您的目标创建一个系统目标文件。然后通过查看系统目标文件浏览器和“配置参数”对话框中的新目标来验证该系统目标文件。

编辑系统目标文件.  要编辑系统目标文件,请按以下步骤操作:

  1. 将您的工作文件夹更改为您在创建目标文件夹中创建的文件夹。

    cd c:/work/my_ert_target/my_ert_target
  2. matlabroot/rtw/c/ert/ert.tlc 复制到 c:/work/my_ert_target/my_ert_target 中并重命名为 my_ert_target.tlc。文件 ert.tlc 是 ERT 目标的系统目标文件。

  3. 在您选择的文本编辑器中打开 my_ert_target.tlc

  4. 自定义系统目标文件,将标头注释行替换为能让您的系统目标文件在系统目标文件浏览器中可见的指令以及其他用来定义关联的 TMF、make 命令和外部模式接口文件(如果有)的指令。有关这些指令的详细信息,请参阅标头注释

    用以下标头注释替换 my_ert_target.tlc 中的标头注释。

    %% SYSTLC: My ERT-based Target TMF: my_ert_target_lcc.tmf MAKE: make_rtw
  5. 文件 my_ert_target.tlc 按照继承目标选项中介绍的机制继承标准 ERT 选项。因此,现有的 rtwoptions 结构体定义是多余的。编辑 RTW_OPTIONS 部分,使其仅包含以下代码。

    /%
      BEGIN_RTW_OPTIONS
    
      %----------------------------------------%
      % Configure RTW code generation settings %
      %----------------------------------------%
    
      rtwgensettings.BuildDirSuffix = '_ert_rtw';
    
      END_RTW_OPTIONS
     %/
  6. 删除 RTW_OPTIONS 部分结束之后的代码,即指令 BEGIN_CONFIGSET_TARGET_COMPONENT and END_CONFIGSET_TARGET_COMPONENT 所包围的部分。这段代码仅供 MathWorks 内部开发人员使用。

  7. 根据rtwgensettings 结构体中介绍的约定修改 rtwgenSettings 结构体中的编译文件夹后缀。

    要将 _my_ert_target 自定义目标的编译文件夹后缀设置为字符向量,请将代码行

    rtwgensettings.BuildDirSuffix = '_ert_rtw'

    更改为

    rtwgensettings.BuildDirSuffix = '_my_ert_target_rtw'
    
  8. 按照rtwgensettings 结构体中的说明修改 rtwgenSettings 结构体,以便从 ERT 目标继承选项并声明与 14 版或更高版本的兼容性。将以下代码添加到 rtwgenSettings 定义中:

    rtwgensettings.DerivedFrom = 'ert.tlc';
    rtwgensettings.Version = '1';
  9. BEGIN_RTW_OPTIONS 指令之后添加一个 rtwoptions 结构体,它定义一个目标特定的选项类别,其中包含三个复选框。以下代码显示了完整的 RTW_OPTIONS 部分,包括之前的 rtwgenSettings 更改。

    /%
      BEGIN_RTW_OPTIONS
    
      rtwoptions(1).prompt         = 'My Target Options';
      rtwoptions(1).type           = 'Category';
      rtwoptions(1).enable         = 'on';
      rtwoptions(1).default        = 3;   % number of items under this category
                                          % excluding this one.
      rtwoptions(1).popupstrings  = '';
      rtwoptions(1).tlcvariable   = '';
      rtwoptions(1).tooltip       = '';
      rtwoptions(1).callback      = '';
      rtwoptions(1).makevariable  = '';
    
      rtwoptions(2).prompt         = 'Demo option 1';
      rtwoptions(2).type           = 'Checkbox';
      rtwoptions(2).default        = 'off';
      rtwoptions(2).tlcvariable    = 'DummyOpt1';
      rtwoptions(2).makevariable   = '';
      rtwoptions(2).tooltip        = ['Demo option1 (non-functional)'];
      rtwoptions(2).callback       = '';
    
      rtwoptions(3).prompt         = 'Demo option 2';
      rtwoptions(3).type           = 'Checkbox';
      rtwoptions(3).default        = 'off';
      rtwoptions(3).tlcvariable    = 'DummyOpt2';
      rtwoptions(3).makevariable   = '';
      rtwoptions(3).tooltip        = ['Demo option2 (non-functional)'];
      rtwoptions(3).callback       = '';
    
      rtwoptions(4).prompt         = 'Demo option 3';
      rtwoptions(4).type           = 'Checkbox';
      rtwoptions(4).default        = 'off';
      rtwoptions(4).tlcvariable    = 'DummyOpt3';
      rtwoptions(4).makevariable   = '';
      rtwoptions(4).tooltip        = ['Demo option3 (non-functional)'];
      rtwoptions(4).callback       = '';
    
      %----------------------------------------%
      % Configure RTW code generation settings %
      %----------------------------------------%
    
      rtwgensettings.BuildDirSuffix = '_my_ert_target_rtw';
      rtwgensettings.DerivedFrom = 'ert.tlc';
      rtwgensettings.Version = '1';
      rtwgensettings.SelectCallback = 'enableToolchainCompliant(hSrc, hDlg)';
      %SelectCallback provides toolchain approach support, but requires custom function
      %Omit this SelectCallback if using the template makefile approach
    
      END_RTW_OPTIONS
    %/
  10. 将更改保存到 my_ert_target.tlc 并关闭该文件。

创建与工具链兼容的函数.  要使编译使用工具链方法,需要在自定义系统目标文件接近末尾的位置创建一个与 SelectCallback 对应的函数。此函数用来设置工具链兼容性属性。

function enableToolchainCompliant(hSrc, hDlg)
  % The following parameters enable toolchain compliance.
  slConfigUISetVal(hDlg, hSrc, 'UseToolchainInfoCompliant', 'on');
  slConfigUISetVal(hDlg, hSrc, 'GenerateMakefile','on');
  
  % The following parameters are not required for toolchain compliance.
  % But, it is recommended practice to set these default values and 
  % disable the parameters (as shown).
  slConfigUISetVal(hDlg, hSrc, 'RTWCompilerOptimization','off');
  slConfigUISetVal(hDlg, hSrc, 'MakeCommand','make_rtw');
  slConfigUISetEnabled(hDlg, hSrc, 'RTWCompilerOptimization',false);
  slConfigUISetEnabled(hDlg, hSrc, 'MakeCommand',false);
  hCS = hSrc.getConfigSet(); 
  hCS.refreshDialog; 
end

注意

如果您使用模板联编文件方法,则可省略从系统目标文件中调用该函数以实现工具链兼容性的步骤,而改用创建基于 ERT 的模板联编文件中的信息。

查看系统目标文件.  此时,您可以按以下步骤验证目标是否继承并显示 ERT 选项:

  1. 创建一个新模型。

  2. 打开模型资源管理器或“配置参数”对话框。

  3. 选择代码生成窗格。

  4. 点击浏览以打开系统目标文件浏览器。

  5. 在文件浏览器中,滚动目标列表以查找新目标 my_ert_target.tlc。(此步骤假设您的 MATLAB 路径中包含 c:/work/my_ert_target/my_ert_target,如之前在创建目标文件夹中所做的设置。)

  6. 选择 My ERT-based Target,然后点击确定

  7. 代码生成窗格现在显示已针对 my_ert_target.tlc 目标对模型进行了配置。系统目标文件语言工具链编译配置字段应如下所示:

  8. 选择我的目标选项窗格。目标显示在 rtwoptions 结构体中定义的三个复选框选项。

  9. 选择代码生成窗格,然后重新打开系统目标文件浏览器。

  10. 选择 Embedded Coder 目标 (ert.tlc)。目标显示标准 ERT 选项。

  11. 关闭模型。您不需要保存它。

至此,基础目标的系统目标文件已完成。如果您使用工具链方法,现在即可为您的目标调用编译过程。

如果您更喜欢使用模板联编文件方法,则在系统目标文件标头注释中引用 TMF my_ert_target_lcc.tmf 将会阻止您为目标调用编译过程,直到该 TMF 文件就绪为止。因此,您必须先创建 my_ert_target_lcc.tmf 文件。

创建基于 ERT 的模板联编文件

如果您使用工具链联编文件方法以及与工具链兼容的自定义目标,则可以省略适用于模板联编文件方法的步骤。(请跳过本节内容。)

如果您使用模板联编文件方法,请按照适用于模板联编文件的步骤进行操作,并省略从系统目标文件中调用函数以实现工具链兼容性的步骤,如创建基于 ERT 的、与工具链兼容的系统目标文件 中所述。

通过复制和修改提供的 ERT 模板联编文件,为您的目标创建一个模板联编文件。选择最适合您的目标的模板联编文件。此示例使用 ert_lcc64.tmf,但您也可以使用 ert_vcx64.tmfert_unix.tmf

  1. 确保您的工作文件夹仍然设置为您之前在创建目标文件夹中创建的目标文件夹。

    c:/work/my_ert_target/my_ert_target
  2. matlabroot/toolbox/coder/compile/tmf/ert_lcc64.tmf 复制到 c:/work/my_ert_target/my_ert_target 中并重命名为 my_ert_target_lcc.tmf。文件 ert_lcc64.tmf 是适合 LCC 编译器的 ERT 编译器特定的模板联编文件。

  3. 在文本编辑器中打开 my_ert_target_lcc.tmf

  4. 更改 SYS_TARGET_FILE 参数,以便在 make 文件中生成对您的 .tlc 文件的文件引用。将以下代码行

    SYS_TARGET_FILE = any

    更改为

    SYS_TARGET_FILE = my_ert_target.tlc
  5. 将更改保存到 my_ert_target_lcc.tmf 并关闭该文件。

现在,您的目标即可生成代码并编译基于主机的可执行文件。在下面几节,您将创建一个测试模型并使用 my_ert_target 来测试编译过程。

创建测试模型和 S-Function

在本节中,您将构建一个简单的测试模型,以便在后面的代码生成中继续使用:

  1. 将您的工作文件夹设置为 c:/work/my_targetmodel

    cd c:/work/my_targetmodel

    在本教程的其余部分,假定 my_targetmodel 就是工作文件夹。您的目标将代码生成过程的输出文件写入工作文件夹内的编译文件夹中。为 timestwo S-Function 生成内联代码时,编译过程将在工作文件夹中查找 S-Function 的 TLC 实现。

  2. timestwo S-Function 的以下 C 和 TLC 文件复制到工作文件夹中:

    • matlabroot/toolbox/simulink/simdemos/simfeatures/src/timestwo.c

    • matlabroot/toolbox/simulink/simdemos/simfeatures/tlc_c/timestwo.tlc

  3. c:/work/my_targetmodel 中生成 timestwo MEX 文件。

    mex timestwo.c
  4. 使用 Simulink® User-Defined Functions 库中的 S-Function 模块创建以下模型。将该模型保存到工作文件夹中并命名为 targetmodel

  5. 双击 S-Function 模块以打开“模块参数”对话框。输入 S-Function 名称 timestwo。点击确定。该模块现在绑定到 timestwo MEX 文件。

  6. 打开模型资源管理器或“配置参数”对话框,然后选择求解器窗格。

  7. 将求解器的类型设置为固定步长,然后点击应用

  8. 保存模型。

  9. 打开示波器并运行仿真。验证并确认 timestwo S-Function 将其输入乘以 2.0。

targetmodel 模型保持打开状态供下一节使用,下一节将使用测试模型生成代码。

验证目标操作

在本节中,您将为 my_ert_target 自定义目标配置 targetmodel,然后使用该目标生成代码并编译可执行文件:

  1. 在“配置参数”对话框中,选择代码生成 窗格。

  2. 点击浏览以打开系统目标文件浏览器。

  3. 在该浏览器中,选择 My ERT-based Target,然后点击确定

  4. “配置参数”对话框现在显示 my_ert_target代码生成窗格。

  5. 选择代码生成 > 报告窗格,然后选择创建代码生成报告选项。

  6. 点击应用并保存模型。这样即为 my_ert_target 配置了该模型。

  7. 编译模型。如果编译成功,MATLAB 命令行窗口将显示以下消息。

    ### Created executable: ../targetmodel.exe
    ### Successful completion of build procedure for model:
    targetmodel

    您的工作文件夹包含 targetmodel.exe 文件和编译文件夹 targetmodel_my_ert_target_rtw,编译文件夹中包含生成的代码和其他文件。工作文件夹中还包含供编译过程在内部使用的 slprj 文件夹。

    代码生成器还创建代码生成报告。

  8. 要查看生成的代码,请在 C 代码选项卡上,点击查看代码。在代码生成报告的内容窗格中,点击 targetmodel.c 链接。

  9. targetmodel.c 中,找到模型阶跃函数 targetmodel_step。观察以下代码。

    /* S-Function Block: <Root>/S-Function */
    /* Multiply input by two */
    targetmodel_B.SFunction = targetmodel_B.SineWave * 2.0;

    这段代码的存在证实了 my_ert_target 自定义目标已为模型中的 S-Function 模块生成了内联输出计算。

相关主题