Main Content

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

为模型入口函数配置生成的 C 函数接口

什么是入口函数?

入口是代码中发生程序控制权(执行)转移的位置。主函数 (main()) 是进入 C/C++ 程序的入口,在应用程序开始执行时调用。对其他函数的调用(例如从 main 函数调用)是进入函数代码的入口。程序控制权会转移到被调函数。函数代码随后执行,在完成后将控制权交还给 main 或其他主调函数。

为模型生成代码时,代码生成器会定义一组入口函数,您可以调用这些函数来执行生成的代码。您可以从外部代码或生成的主函数的修改版调用生成的函数。

代码生成报告的“代码接口报告”部分会列出代码生成器为模型生成的入口函数。有关详细信息,请参阅 Analyze Generated Data Code Interface

生成的入口函数的类型

代码生成器为下列类型的模型函数生成入口函数。

模型函数的类型模型源函数名称默认的生成函数名称描述
导出函数(需要 Embedded Coder®ExportedFunction:slIdentifier,其中 slIdentifier 是模型中函数调用 Inport 模块的名称function-call-inport-block-namesignal-label(如果指定)对于导出函数模型,即为子系统的导出函数。
初始化函数Initializemodel_initialize

模型的初始化代码。在应用程序代码的开始,调用函数一次。请不要使用此函数重置实时模型数据结构体 (rtM)。

分区函数Partition:slIdentifier,其中 slIdentifier 是从模型中的模块显式创建的一个分区,显示在 Simulink® 调度编辑器中(例如,P1)model_stepn,其中 n 基于模型采样周期唯一标识生成的函数对于模型分区,输出并更新代码。模型配置参数 Single output/update function 处于选中状态(默认值)。
分区更新函数PartitionUpdate:slIdentifier,其中 slIdentifier 是从模型中的模块显式创建的一个分区,显示在 Simulink® 调度编辑器中(例如,P1)model_outputnmodel_updaten,其中 n 基于模型采样周期唯一标识生成的函数对于模型分区,使用分别的函数输出和更新代码。模型配置参数 Single output/update function 处于清除状态。
周期性多任务函数Periodic:slIdentifier,其中 slIdentifier 是一个注释,对应于多任务模型的一个周期性或连续速率的采样时间周期(例如,D1)model_stepn,其中 n 基于模型采样周期唯一标识生成的函数对于为多任务配置的一个基于速率的模型中的模块,输出和更新代码。代码生成器为每个采样周期生成一个函数。模型配置参数 Single output/update function 处于选中状态(默认值)。
周期性多任务更新函数PeriodicUpdate:slIdentifier,其中 slIdentifier 是一个注释,对应于多任务模型的一个周期性或连续速率的采样时间周期(例如,D1)model_outputnmodel_updaten,其中 n 基于模型采样周期唯一标识生成的函数对于为多任务配置的一个基于速率的模型中的模块,分别在单独的函数中输出和更新代码。代码生成器为每个采样周期生成输出和更新函数。模型配置参数 Single output/update function 处于清除状态。
周期性单任务函数Periodicmodel_step对于为单任务配置的基于速率的模型中的模块,输出和更新代码。模型配置参数 Single output/update function 处于选中状态(默认值)。
周期性单任务更新函数PeriodicUpdatemodel_outputmodel_update对于为单任务配置的基于速率的模型中的模块,分别在单独的函数中输出和更新代码。模型配置参数 Single output/update function 处于清除状态。
重置函数Reset:slIdentifier,其中 slIdentifier 是模型中重置函数的名称model_reset-function-name

如果模型包含 Reset Function 模块,则重置生成的代码。要重置条件或状态,请从应用程序代码中调用函数。

Simulink FunctionSimulink Function:slIdentifier,其中 slIdentifier 是模型中 Simulink Function 模块的名称对于全局 Simulink Function 模块,为 function-name;对于限定作用域的 Simulink Function 模块,为 model_function-name对于导出函数模型,是 Simulink Function 模块的导出函数。
终止函数Terminatemodel_terminate

用于关闭系统的代码。对于基于 ERT 的模型,您可以通过清除模型配置参数 Terminate function required(默认设置)来隐藏此函数的生成。

如果您有 Embedded Coder 软件,为了便于集成外部代码和生成的代码并符合代码标准和规范,您可以配置代码生成器如何从模型或子系统生成函数接口。

配置入口函数是否可重用

默认情况下,对于顶层模型,代码生成器生成不可重用或不可重入的代码。入口函数有一个 void-void 接口。代码通过直接访问驻留在共享内存中的全局数据结构体来与其他代码通信。

如果您的应用程序需要可重用的多实例入口函数代码,您可以配置代码生成器使用唯一数据来调用每个函数(实例)。在这种情况下,代码是可重入的。

您可以使用模型配置参数 Code interface packaging 和相关参数来配置入口函数是否可重用。您选择的参数设置取决于系统目标文件的配置选择、编程语言和参数接口等因素。

单实例 C 入口函数的默认配置

默认情况下,对于基于 GRT 和基于 ERT 的系统目标文件,代码生成器生成单实例 C 入口函数。生成的代码:

  • 创建不带参数的执行函数 (void-void)。

  • 为模型数据结构体静态分配内存(在编译时)。

配置单实例入口函数代码的默认模型配置参数设置为:

生成可重用的多实例 C 入口函数

您可以配置代码生成器,为基于 GRT 或基于 ERT 的系统目标文件生成可重用的 C 入口函数。但是,代码生成器默认生成的各函数接口有所不同。假设模型配置参数 Language 设置为 “C” 且 Code interface packaging 设置为 “Reusable function”,代码生成器为每个系统目标文件场景生成以下入口函数代码。

系统目标文件接口
基于 GRT
  • 可重用、可重入的多实例 C 入口函数。

  • 将模型根级 Inport 模块和 Outport 模块的值打包到实时模型数据结构体中。按引用将该结构体作为参数传递给执行函数。

  • 在运行时为模型实例的数据动态分配内存。通过调用函数(如 malloc)来分配内存。

基于 ERT
  • 可重用、可重入的多实例 C 入口函数。

  • 将每个模型根级 Inport 模块和 Outport 模块的值作为单独的参数传递给执行函数。

  • 为模型数据结构体静态分配内存。

如果您使用的是基于 ERT 的系统目标文件,并希望生成可重用、可重入的多实例 C 入口函数,请考虑:

  • 使用动态内存分配来初始化模型数据结构体。选择 Use dynamic memory allocation for model initialization

  • 将模型根级 Inport 模块的值打包到一个结构体中,将根级 Outport 模块的值打包到另一个结构体中,并按引用将这些结构体作为参数传递给执行函数。将 Pass root-level I/O as 设置为 “Structure reference”。

  • 将模型根级 Inport 模块和 Outport 模块的值打包到实时模型数据结构体中,并按引用将该结构体作为参数传递给执行函数。将 Pass root-level I/O as 设置为 “Part of model data structure”。

选择配置生成的 C 函数接口的方法

为了便于集成外部代码和生成的代码并符合代码标准和规范,您可以使用 Code Mappings 编辑器或代码映射 API 来配置代码生成器如何从模型或子系统生成函数接口。

配置更多信息
模型中函数类别(初始化/终止、执行和共享实用工具)的默认命名规则Configure Default Code Generation for Functions
单个入口函数的名称(覆盖默认命名规则)为单个 C 入口函数配置名称
基本速率单步入口函数的单步函数接口(函数名称、返回值和参数 C 类型限定符、名称和顺序),以交互方式配置为单个单步函数配置名称和参数
Simulink Function 和 Function Caller 模块的函数接口(函数名称、返回值和参数 C 类型限定符、名称和顺序),以交互方式配置Configure Entry-Point Function Interfaces for Simulink Function and Function Caller Blocks

您可以使用软件在环 (SIL) 测试来验证为自定义入口函数生成的代码。使用您的生成代码创建一个 SIL 模块。然后,将该 SIL 模块集成到一个模型中,以验证生成代码提供与原始模型或非虚拟子系统相同的结果。有关详细信息,请参阅 Choose a SIL or PIL Approach

为函数类别配置默认代码生成设置

通过为整个模型中的函数类别指定默认配置,减少为 C 代码生成而准备模型的工作量。例如,您可以配置函数命名规则和函数代码在内存段中的位置。应用默认配置可以节省时间并降低在代码中引入错误的风险,尤其是对于具有大量函数的模型。

代码生成器为下列类别的模型函数生成入口函数:

函数类别描述
初始化/终止用于初始化和关闭系统的函数
执行用于启动执行和重置的函数
共享实用工具共享工具函数代码

通过使用代码映射编辑器 - C 或代码映射 API 函数 setFunctionDefault,为函数配置默认代码映射。使用这些接口,您可以将函数类别与模型的 Embedded Coder 字典中定义的函数自定义模板相关联。

如果您的应用程序要求您配置内存中入口函数的位置(例如,用于针对特定硬件优化生成代码),您可以将默认内存段应用于模型中的一个函数类别。在 Code Mappings 编辑器中,将函数类别映射到定义为使用特定内存段的函数自定义模板。请参阅。

如果函数自定义模板不存在,您可以使用 Embedded Coder 字典创建一个(请参阅Define Service Interfaces, Storage Classes, Memory Sections, and Function Templates for Software Architecture)。

有关如何为函数类别设置默认配置的示例,请参阅Configure Default C Code Generation for Categories of Data Elements and Functions

为单个 C 入口函数配置名称

为了使您的生成的 C 代码符合代码标准和规范,或更轻松地将该代码与外部代码集成,您可以配置单个入口函数的名称。例如,您可以将为一个模型生成的初始化函数命名为 myInitFunc

如果您的模型满足下列至少一个条件,请考虑单独配置函数的名称:

  • 使用多个要求唯一命名的函数。

  • 使用很少的函数。

  • 具有函数类别的默认配置,并且您需要覆盖特定函数的配置。

通过使用 Code Mappings 编辑器或代码映射 API 函数 setFunction,为单个单步函数配置函数名称。使用这些接口,您可以将函数与在模型的 Embedded Coder 字典中定义的函数自定义模板相关联,并指定函数名称。

此示例说明如何更改模型 rtwdemo_fcnprotoctrlinitialize 函数的名称。

  1. 打开模型 rtwdemo_fcnprotoctrl 并将其副本保存在一个可写位置。

  2. 打开 Embedded Coder

  3. C Code 选项卡上,选择 Code Interface > Individual Element Code Mappings

  4. 在 Code Mappings 编辑器的 Functions 选项卡中,使用以下方法之一更改函数名称:

    • Function Name 列中,输入函数的名称。

    • Function Preview 列中,点击函数原型超链接以打开配置对话框。在 C Initialize Function Name 字段中,输入函数名称。点击 Apply 以验证 C function prototype 字段中的更改,或点击 OK 以退出对话框并在 Code Mappings 编辑器的 Function Preview 列中查看函数名称。

    在此示例中,将 initialize 函数的名称更改为 fcnprotoctrl_init

  5. 保存模型。

  6. 生成代码。

  7. 验证生成代码中的更改。在 Code 视图中,查找函数名称 fcnprotoctrl_init 的实例。函数名称出现在生成的文件 rtwdemo_fcnprotoctrl.hrtwdemo_fcnprotoctrl.c 中。

    • rtwdemo_fcnprotoctrl.h 中:

      extern void fcnprotoctrl_init(void);
      
    • rtwdemo_fcnprotoctrl.c 中:

      void fcnprotoctrl_init(void)
      {
        ...
      }

为单个单步函数配置名称和参数

为了使您的生成的 C 代码符合代码标准和规范,或更轻松地将代码与外部代码集成,您可以配置为 Simulink 周期性函数生成的各个单步函数的名称和参数。您可以自定义单步函数的以下方面:

  • 函数名称

  • 参数名称

  • 参数的顺序

  • 返回值和参数数据限定符

  • 参数的缓冲优化

如果您的模型满足下列至少一个条件,请考虑单独配置单步函数的名称和参数:

  • 是周期性单任务模型,且代码生成器为其生成一个单步函数。

  • Execution 函数类别具有默认配置,并且您需要覆盖特定单步函数的配置。

通过使用 Code Mappings 编辑器或代码映射 API 函数 setFunction,为各个单步函数配置代码映射。使用这些接口,您可以将函数与在模型的 Embedded Coder 字典中定义的函数自定义模板相关联,并完全自定义单步函数原型。

此示例说明如何为基于速率的单任务模型自定义单步函数名称和参数。

打开配置对话框

1.打开模型 rtwdemo_fcnprotoctrl 并将其副本保存到可写位置。

2.打开 Embedded Coder

3.在 C Code 选项卡上,选择 Code Interface > Individual Element Code Mappings

4.在 Code Mapping 编辑器中,点击 Functions 选项卡。

5.对于单步函数行,在 Function Preview 列中,点击原型超链接以打开 Configure C Step Function Interface 对话框。

在 Configure C Step Function Interface 对话框中,C function prototype 字段显示您对函数原型所做更改的预览。

有关配置为生成多实例代码的模型,请参阅从顶层模型生成可重入代码

自定义函数名称

1.在 Configure C Step Function Interface 对话框中,将 C Step Function Name 设置为 fcnprotoctrl_run。函数预览会更新以反映新函数名称。

2.点击 Apply,关闭对话框,然后保存模型。

3.生成代码并验证名称更改。

  • 点击 Code 选项卡。在 Code 视图的文件列表中,选择文件 rtwdemo_fcnprotoctrl.h。在 Search 字段中,验证代码元素列表是否包含函数名称 fcnprotoctrl_run。要查看声明,请选择函数名称。

声明在代码中高亮显示:

  • 验证文件 rtwdemo_fcnprotoctrl.c 中的名称更改。要查看源代码(定义),请在 Search 字段中,选择 fcnprotoctrl_run

有关更多示例,请参阅为单个 C 入口函数配置名称

自定义函数参数

配置全局数据结构体

默认情况下,顶层模型或引用模型使用 void-void 单步函数传递数据。借助此类型的函数,生成的代码可通过访问存储为共享内存中的数据结构体的全局数据与外部代码进行通信。

要将模型配置为具有 void-void 单步函数,请打开 Configure C Step Function Interface 对话框,并清除 Configure arguments for Step function prototype 复选框。验证 C function prototype 预览中的更改。

配置参数

基于速率的模型单步函数可以使用参数传递数据。您可以自定义下列参数设置:

  • 返回值

  • 类型限定符

  • 名称

  • 顺序

示例

1.打开 Configure C Step Function Interface 对话框。在 Code Mapping 编辑器中,点击 Functions 选项卡。然后,点击单步函数的函数预览。

2.在 Configure C Step Function Interface 对话框中,选择 Configure arguments for Step function prototype

3.点击 Get default。对话框将展开,以显示用于配置函数返回值的字段和用于列出具有默认设置的输入和输出参数的表。

4.自定义单步函数的返回值。将 C return argument 设置为 void 或输出参数之一。对于此示例,选择 void

5.对于每个参数,指定一个 C Type Qualifier

类型限定符:

  • Value:值,例如,arg

  • Const:具有 const 限定符的值,例如,const arg

  • Pointer to const:具有 const 限定符并由指针引用的值,例如,const *arg

  • Pointer:由指针引用的值,例如,*arg

  • Const pointer to const:具有 const 限定符、引用指针以及指针本身的值,例如,const *const arg

包含引用模型的模型

  • 对于引用模型,单步函数接口中根输入参数的类型限定符设置为 Auto。代码生成器通过生成从源信号中丢弃 const 限定符的类型转换来使用接口设定。

  • 对于引用模型的父模型,源信号的类型限定符设置为 Auto 以外的值。要覆盖此行为,请在引用模型中添加一个 const 类型限定符。

对于此示例,不要更改 C 类型限定符。

6.通过编辑 C Identifier Name 列中的值来自定义参数名称。

对于此示例,通过删除下划线来更改参数的名称,例如,将 arg_In1 更改为 argIn1。

7.通过将表行拖到新位置来自定义参数顺序。

对于此示例,将 Out1 移至第一个位置。将 Out 2 移至第三个位置。

8.验证、应用更改、关闭对话框并保存模型。

9.生成代码并在 Code 视图中确认更改。

  • 通过检查 Search 字段是否包含 fcnprotoctrl_run 函数,确认您在文件 rtwdemo_fcnprotoctrl.h 中所做的更改。要查看函数声明,请选择函数名称。

  • 验证您在文件 rtwdemo_fcnprotoctrl.c 中的更改。要查看函数的定义,请选择函数名称 fcnprotoctrl_run

实际原型不同于原型预览

在 Configure C Step Function Interface 对话框中,引用模型的函数原型预览可能比生成代码中的函数原型显示更少的参数。

例如,假设有名为 mdlref_counter 的模型,该模型包含输入端口 (arg_input)、输出端口 (arg_output) 及饱和模块,该饱和模块具有两个限值参数,它们在工作区中的名称为 lower_saturation_limitupper_saturation_limit。Configure C Step Function Interface 对话框将函数原型预览显示为:

mdlref_counter_custom(arg_input, arg_output)

在生成的代码中,原型包括以下参数:

mdlref_counter_custom(real_T arg_input, real_T arg_output, real_T 
  rtp_lower_saturation_limit, real_T rtp_upper_saturation_limit)

优化参数的缓冲

您可以在模型的单步函数中优化 I/O 参数所需的缓冲。如果在配置输入端口和输出端口对组时遵守以下要求,则代码生成器会合并对应的参数并重用相关联的缓冲区。

  • Inport 和 Outport 模块必须具有相同的属性,包括数据类型、维度和采样率。

  • Inport 和 Outport 模块的采样率必须与模型的基本速率相同。

  • 条件执行子系统不能驱动 Outport 模块。

  • 单个非虚拟模块输出必须驱动 Outport 模块。例如,合并多个缓冲区的 Mux 模块不能驱动 Outport 模块。

  • 在 Configure C Step Function Interface 对话框中,必须使用相同的 C 类型限定符和标识符名称配置输入端口和输出端口。

此示例说明如何合并示例模型 rtwdemo_fcnprotoctrl 的端口 In3Out2 的参数。

1.打开模型 rtwdemo_fcnprotoctrl 的 Configure C Step Function Interface 对话框。

2.通过选择 Configure arguments for Step function prototype 打开参数的显示。

3.对于端口 In3Out2,将 C Type Qualifier 设置为 Pointer,将 C Identifier Name 设置为 sharedArg

4.确认预览显示 argIn3argOut2 的合并后的参数。

5.验证、应用更改、关闭对话框并保存模型。

6.生成并查看代码。在 Code 视图中,搜索 fcnprotoctrl_run 函数并检查函数接口。对于此示例,共享参数显示在 Inport 模块的读取代码中和 Outport 模块的写入代码中。

以编程方式配置 C 入口函数的代码生成设置

要为 C 代码生成自动配置模型函数,请使用代码映射的编程接口。例如,当创建自定义模块库或应用程序测试环境的一部分时,可使用编程接口来自动化函数配置。

这些函数的典型用途包括:

  • 创建一个函数接口。

  • 修改一个现有函数接口。

  • 基于模型的默认配置信息创建一个函数接口。

  • 将该模型函数接口重置为默认 ERT 函数配置。

有关如何以编程方式配置 C 入口函数的代码生成设置的示例,请参阅Configure Default Data and Function Code Generation Programmatically。此示例说明如何为函数类别和单个函数配置默认设置。

如何与生成的入口函数对接

  1. 为模型生成代码后,使用 Code 视图查看生成的入口函数,以及表示外部输入和输出端口的变量(如果适用)。

  2. #include 语句添加到外部代码中,这些语句包括声明模型入口函数的生成的头文件。

  3. 添加一条 #include 语句以包含生成的文件 rtwtypes.h。此文件提供类型定义、#define 语句和枚举。

  4. 初始化目标特定的数据结构体和硬件,如 ADC 或 DAC。

  5. 如果适用,为可重用模型的每个实例初始化数据。

  6. 如果适用,将输入数据写入表示模型 Inport 模块的生成变量。

  7. 调用生成的入口函数或设置 rt_OneStep 函数的使用。

  8. 如果适用,从表示模型 Outport 模块的生成变量中读取数据。

有关详细信息,请参阅Deploy Applications to Target Hardware

C 函数接口自定义限制

生成的 C 函数接口的自定义有以下限制:

  • 您必须选择模型配置参数 Single output/update function

  • 支持多速率模型,但您必须为单任务配置模型。

  • 您必须配置根级输入端口和输出端口以使用 Default 存储类。

  • 如果您选择自定义函数接口,您必须提供自己的自定义 main 程序。您无法使用 MathWorks® 提供的静态 rt_main.c 来配置函数接口。指定非默认的函数接口配置会导致生成的代码与默认静态 rt_main.c 不匹配。

  • 代码生成器会删除模型根输入端口的数据结构体,除非由不可重用函数实现的子系统使用一个或更多个输入端口的值。

  • 代码生成器会删除模型的根输出端口的数据结构体,除非您启用 MAT 文件日志记录或者一个或更多个输出端口的采样时间不是基本速率(包括恒定速率)。

  • 如果您复制子系统模块以在新模型或同一模型中创建模块,则原始子系统模块的函数接口信息不会复制到新子系统模块中。

  • 如果您有 Stateflow®,则对于使用模型根输入端口值或调用使用模型根输入端口值的子系统的 Stateflow 图,请执行以下操作之一来生成代码:

    • 在 Stateflow 图中,清除 Execute (enter) Chart At Initialization 复选框。

    • 将 Stateflow 函数设置为不可重用的函数。

    • 在根输入端口后立即插入 Simulink® Signal Conversion 模块。在 Signal Conversion 模块参数对话框中,选择 Exclude this block from 'Block reduction' optimization

  • 如果模型根输入端口值连接到 Simscape™ 转换模块,请在根输入端口和 Simscape 转换模块之间插入 Simulink Signal Conversion 模块。在 Signal Conversion 模块参数对话框中,选择 Exclude this block from 'Block reduction' optimization

  • 当编译配置有函数接口的引用模型时,不要使用虚拟总线作为引用模型的输入或输出。请改用非虚拟总线。

  • 如果 C 函数接口不是默认值,则忽略模型配置参数 Pass fixed-size scalar root inputs by value for code generation 的值。有关详细信息,请参阅Pass fixed-size scalar root inputs by value for code generation

另请参阅

|

相关主题