Main Content

将 S-Function 目标用于模型或子系统

S-Function 是代码生成器可为其生成代码的一类系统目标文件。S-Function 目标可以封装子系统来提高其执行效率,促进代码重用,并保护其知识产权。

注意

虽然您可以使用 S-Function 目标以在部署应用组件用于重用的同时保护其内部逻辑免遭窥探和修改,但在分布式组件中,保护知识产权的首选解决方案是:

  • 受保护模型,即隐藏模块和信号线信息的引用模型。有关详细信息,请参阅保护模型以隐藏内容

  • 共享库系统目标文件,用于为模型或子系统生成共享库,以便在 Simulink® 之外的系统仿真中使用。有关详细信息,请参阅将生成的代码打包为共享库

这些解决办法还可以提高执行效率,促进代码重用。

您可以将生成的 S-Function 目标与 Generated S-Function 模块结合使用。

S-Function 目标使用的 CodeFormat TLC 变量的值为 'S-Function' 时,会生成符合 Simulink C MEX S-Function 应用程序编程接口 (API) 规范的代码。

S-Function 部署所需的文件

部署生成的 S-Function 模块用于仿真和用于代码生成所需要的文件是不同的。

要部署生成的 S-Function 模块以包含在其他模型中用于仿真,只需提供创建 S-Function 模块时在当前工作文件夹中生成的二进制 MEX 文件对象。所需的文件为:

  • subsys_sf.mexext

其中 subsys 是子系统名称,mexext 是因平台而异的 MEX 文件扩展名(请参阅 mexext)。例如,SourceSubsys_sf.mexw64

要部署生成的 S-Function 模块以包含在其他模型中用于代码生成,请提供创建 S-Function 模块时在当前工作文件夹中生成的文件。所需的文件包括:

  • subsys_sf.c.cpp,其中 subsys 是子系统名称(例如,SourceSubsys_sf.c

  • subsys_sf.h

  • subsys_sf.mexext,其中 mexext 是因平台而异的 MEX 文件扩展名(请参阅 mexext

  • 子文件夹 subsys_sfcn_rtw 及其内容

生成的 S-Function 代码使用与创建函数时所在的主机系统匹配的配置参数 > 硬件实现参数值。当您使用模型中的 S-Function 来进行代码生成时,请确保模型的这些参数值与 S-Function 的参数值相匹配。

生成的 S-Function 中的采样时间传播

如果满足一定的条件,生成的 S-Function 模块可以从其所在的模型中继承采样时间。引用模型的采样时间S-Functions That Specify Sample Time Inheritance Rules介绍了决定 Model 模块和生成的 S-Function 模块的采样时间传播的条件。

要生成满足继承采样时间条件的 S-Function 模块,必须对从中生成 S-Function 模块的模型的求解器加以限制。将模型配置参数类型设置为“定步长”并将周期性采样时间约束设置“确保采样时间独立”。如果模型不能继承采样时间,此设置会导致 Simulink 软件在编译模型时显示错误消息。有关此选项的详细信息,请参阅周期性采样时间约束

具有生成的 S-Function 的顶层模型的求解器类型

下表显示顶层模型求解器类型(这些类型与模型是具有离散还是连续采样时间有关)与生成的 S-Function 的求解器类型的可能组合。

顶层模型求解器选项和采样时间

 模型配置参数:顶层模型配置
采样时间求解器选项,类型:变步长求解器选项,类型:定步长
离散生成的 S-Function 需要变步长求解器生成的 S-Function 可以具有变步长求解器或定步长求解器
连续生成的 S-Function 需要变步长求解器生成的 S-Function 需要定步长求解器

从子系统生成的 S-Function 的参数硬编码到模块中。Simulink 在生成模块时(而不是在仿真运行时)计算采样时间等参数。验证生成的 S-Function 模块是否能够在目标模型中按预期工作很重要。

生成的 S-Function 中的可调参数

要在生成的 S-Function 中使用可调参数,请使用模型配置参数来声明所需的模块参数可调。请参阅Declare Workspace Variables as Tunable Parameters Using the Model Parameter Configuration Dialog Box

您在源模型中使用“自动”存储类声明为可调的模块参数将成为生成的 S-Function 的可调参数。这些参数不会像从其他系统目标文件生成的代码中那样,成为生成的 model_P(以前称为 rtP)参数数据结构体的一部分。此时,生成的代码将使用 MEX API 调用(如 mxGetPrmxGetData)来访问这些参数。您的代码应该以相同的方式访问这些参数。

有关 MEX API 调用的详细信息,请参阅About C MEX S-Functions将 MATLAB 与外部编程语言和系统集成

使用 S-Function 目标创建的 S-Function 模块将自动封装。封装将每个可调参数显示在一个编辑字段中。默认情况下,编辑字段按变量名称显示参数,如下图所示。

Block parameter dialog box for generated S-Function that shows parameter by variable name

通过选择模型配置参数使用可调参数的值,您可以选择显示参数值,而不是其变量名称。

S-function target model configuration parameters with parameters Create new model and Use value for tunable parameters selected

选择此参数后,编辑字段中将显示变量的值(在代码生成时)。

Block parameter dialog box for generated S-Function that shows parameter by variable value

宏参数

假设您将存储类(如 Define)应用于 Simulink.Parameter 对象,以使该参数在生成的代码中显示为宏。如果在生成 ERT S-Function 的子系统中使用参数对象,则无法选择该参数对象作为可调参数。此时,S-Function 代码生成器将自定义存储类应用于参数对象。S-Function 代码中的这种宏生成使您能够从包含变体元素(如 Variant Subsystem 模块)的子系统中生成 S-Function,您可以配置这些变体元素以在生成的代码中产生预处理器条件句。在仿真 S-Function 期间,无法更改该参数的值。

要选择该参数对象作为可调参数,请应用不同存储类或创建您自己的存储类。将参数视为宏的存储类包括 DefineImportedDefineCompilerFlag 以及通过在自定义存储类设计器中将数据初始化设置为“”而创建的存储类。如果使用非宏存储类,则无法将参数对象用作变体控制项变量并生成预处理器条件句。

如果您应用的存储类将参数对象视为导入的宏,则在生成 ERT S-Function 之前,请提供宏定义。例如,假设您将存储类 ImportedDefine 应用于 Simulink.Parameter 对象,并将参数对象用作子系统中的变体控制项变量。如果将自定义属性 HeaderFile 设置为 'myHdr.h',则在生成 S-Function 时,请将自定义头文件 myHdr.h 放在当前文件夹中。生成的 S-Function 使用头文件中的宏值,而不是参数对象的 Value 属性中的值。

要使用通过编译器选项定义的宏(例如通过应用存储类 CompilerFlag),请使用模型配置参数代码生成 > 自定义代码 > 代码信息 > 定义来指定编译器选项。有关详细信息,请参阅“代码生成”窗格:自定义代码:附加编译信息:定义

系统目标文件

本软件提供了 rtwsfcn.tlc 系统目标文件供 S-Function 目标使用。

校验和与 S-Function 目标

代码生成器为模型创建一个校验和,并在编译过程中将校验和用于代码重用、模型引用和外部模式功能。

代码生成器通过以下方式计算模型校验和

  1. 计算模型中每个子系统的校验和。子系统的校验和是子系统模块的属性(数据类型、复/实性、采样时间、端口维度等)的合并。

  2. 将子系统校验和与其他模型级信息合并。

S-Function 可以通过调用函数 ssSetChecksumVal,将模块属性分析时未捕获的其他信息添加到校验和中。对于 S-Function 目标来说,添加到校验和中的值是生成 S-Function 的模型或子系统的校验和。

代码生成器按以下方式应用子系统和模型的校验和:

  • 代码重用 - 如果一个模型中的两个子系统具有相同的校验和,则代码生成器只为一个函数生成代码。

  • 模型引用 - 如果当前模型校验和与编译模型时的校验和匹配,则编译过程不会重新编译引用模型。

  • 外部模式 - 如果当前模型校验和与目标硬件上运行的代码的校验和不匹配,编译过程将产生错误。

生成的 S-Function 的兼容性

当您从模型编译 MEX S-Function 时,代码生成器将生成 2 级非内联 S-Function。跨版本使用生成的代码和二进制 MEX 文件(例如,*.mexw64)时存在以下限制:

  • 从旧版 MATLAB® 软件中生成的 S-Function 目标代码与新版本不兼容。不要使用新版本的 MATLAB 软件重新编译从旧版本中生成的代码。请使用相同版本的 MATLAB 软件为 S-Function 目标生成代码并将代码编译成 MEX 文件。

  • 您可以将从 MATLAB 早期版本生成的二进制 S-Function MEX 文件与相同版本或更新版本的软件一起使用,但兼容性注意事项与手写 S-Function 相同。有关详细信息,请参阅S-Function Compatibility

  • 代码生成器可从包含生成的 S-Function 的模型中生成代码并编译可执行文件。这项支持要求编译 S-Function 和编译模型时使用的 MATLAB 软件版本相同。您无法将从旧版 MATLAB 软件中生成的 S-Function MEX 文件纳入某个模型,然后使用新版本软件来编译该模型。

有关 S-Function 目标的限制

具有连续采样时间的 InportOutport 模块

通过右键点击编译方式来生成 S-Function 时不会保留 InportOutport 模块的连续采样时间。由于采样时间没有保留,因此生成的 S-Function 模块的仿真可能会受到影响。

表达式中的可调变量

在表达式中使用可调变量存在一些限制条件。当代码生成器在生成代码时遇到不受支持的表达式时,会显示警告并在代码中生成等效的数值。有关限制条件的列表,请参阅Tunable Expression Limitations

参数调整

S-Function 模块不支持调整具有以下值或类型的可调参数:

  • 复数值。

  • 转换为常量的值或数据类型(通过将模型配置参数优化 > 默认参数行为设置为“内联”)。

  • 非内置的数据类型。

  • 与内置类型不等效的浮点数据类型。

运行时参数和 S-Function 兼容性诊断

如果您将模型配置参数需要升级 S-Function 设置为“警告”或“错误”,代码生成器会指示您升级从子系统生成的 S-Function。S-Function 系统目标文件没有注册运行时参数。只有内联 S-Function 才支持运行时参数,而生成的 S-Function 支持的功能阻止了它内联,例如,它可能调用或包含其他非内联 S-Function。

要解决此限制,请将参数需要升级 S-Function 设置为“”。

GotoFrom 模块

当使用 S-Function 系统目标文件时,代码生成器将输入和输出限制为对应于根模型的 InportOutport 模块(或生成 S-Function 目标的 Subsystem 模块的 InportOutport 模块)。代码生成器不会为 GotoFrom 模块生成代码。

要绕过此限制,请使用所要求的 InportOutport 模块创建您的模型和子系统,而不要使用 GotoFrom 模块在根模型和子系统之间传递数据。将生成的 S-Function 融入模型中之后,可以再添加 GotoFrom 模块。

未绕过限制的示例

  • 根模型包括一个 From 模块和子系统 Subsystem1

    Root model that includes a From block and subsystem

  • Subsystem1 包括具有全局可见性的 Goto 模块,并将其输入传递给根模型中的 From 模块

    Subsystem that includes a Goto block that has global visibility and passes its input to From block in root model

  • Subsystem1 替换为使用 S-Function 系统目标文件生成的 S-Function - 运行模型时生成警告,因为生成的 S-Function 未实现 Goto 模块

    Subsystem replaced with S-function generated with S-Function system target file

绕过限制后的示例

Outport 模块替换 Subsystem1 中的 GoTo 模块。当您将生成的 S-Function 插入根模型时,其输出将直接连接到 To Workspace 模块。

In subsystem, GoTo block replaced by Outport block

Generated S-function plugged into root model and has output connected to To Workspace block

编译和更新 S-Function

以下限制适用于使用 S-Function 系统目标文件编译和更新 S-Function:

  • 不能使用 S-Function 系统目标文件编译包含 Model 模块的模型。这也意味着,如果子系统包含 Model 模块,则无法使用右键点击上下文菜单编译子系统。此限制仅适用于使用 S-Function 目标生成的 S-Function,不适用于 ERT S-Function。

  • 您可以使用以下工具编译模型:

    • 工具链 - 仅当工具链支持 MEX 文件生成时。

    • 模板联编文件 - 仅当模板联编文件与支持生成 MEX 文件的工具链关联时。

  • 如果修改了生成 S-Function 模块的模型,编译过程不会自动重新编译包含生成的 S-Function 模块的模型。与此不同的是,对于 Model 模块引用的模型,根据模型参考重新编译配置的设置,在修改后可自动重新进行编译。

  • 缺少对应 TLC 文件的手写 S-Function 必须包含无异常代码。有关无异常代码的详细信息,请参阅Exception Free Code

不支持的模块

S-Function 格式不支持以下内置模块:

  • Interpreted MATLAB Function 模块

  • 包含以下函数的 S-Function 模块:

    • MATLAB 语言 S-Function(除非您提供 TLC 文件进行 C 代码生成)

    • Fortran S-Function(除非您提供 TLC 文件进行 C 代码生成)

    • 调用 MATLAB 环境的 C/C++ MEX S-Function

  • Simulink Function 模块

  • Function Caller 模块

  • Scope 模块

  • To Workspace 模块

S-Function 格式不支持 embeddedtargetslib 模块库中的模块。

代码生成不支持模型工作点

您可以编写 C-MEX 和 2 级 MATLAB S-Function,能利用模型工作点保存和还原仿真状态,如 S-Function Compliance with the ModelOperatingPoint 中所述。模型工作点不支持代码生成,包括与 S-Function 系统目标文件一起使用的情况。

当您为指定默认工作点合规性或无工作点支持的 S-Function 生成代码时,生成的代码不包括模型工作点功能。您不能为实现自定义工作点功能的 S-Function 生成代码。

嵌套 S-Function

在模型或子系统中嵌套一个生成的 S-Function 模块,再从中生成另一个 S-Function 时,适用以下限制:

  • 本软件不支持对嵌套的 S-Function 使用非虚拟总线输入和输出。

  • 避免将 S-Function 嵌套在与其同名(可能相隔几个层级)的模型或子系统中。否则,可能会对 S-Function 进行递归调用。本软件当前不会检测这种 S-Function 循环依赖关系,它可能会导致您的 MATLAB 会话终止或挂起。为了防止这种情况发生,请为子系统或模型指定的名称生成具有唯一性的 S-Function 目标,以防与 MATLAB 路径中的现有 MEX 文件重名。

用户定义的数据类型

S-Function 系统目标文件不支持可在用户定义的数据类型上指定的 HeaderFile 属性,包括基于 Simulink.AliasTypeSimulink.BusSimulink.NumericType 对象的属性。如果您的模型中用户定义的数据类型使用 HeaderFile 属性指定关联的头文件,则使用 S-Function 系统目标文件生成代码时将忽略该值,并且不会生成对应的 include 语句。

右键点击生成 S-Function 目标

如果您通过右键点击 Function-Call Subsystem 模块来生成 S-Function 目标,则原始子系统和生成的 S-Function 可能不一致。当 Function-Call Subsystem 模块内的 Trigger Port 模块的启用时的状态参数设置为继承时,就会发生不一致。必须将启用时的状态参数设置为重置保持,否则 Simulink 将报告错误。

总线输入和输出

如果使用 S-Function 目标生成的 S-Function 具有总线输入或输出信号,则生成的总线数据结构体可能包含补白,以使总线元素的字段与仿真期间使用的 Simulink 表示形式对齐。但是,如果在模型中插入 S-Function 并使用模型目标(例如 grt.tlc)生成代码,则为模型编译生成的总线结构体对齐格式可能与为 S-Function 生成的补白不一致,这可能影响代码执行的数值结果。要使模型仿真和执行模型代码之间的结构体对齐格式保持一致,可以修改每个 Simulink.Bus 对象的 HeaderFile 属性,以删除未进行补白的总线结构体头文件。这样将在模型代码中重用为 S-Function 生成的总线类型定义。

具有函数调用输入和输出信号的子系统

S-Function 目标不支持从具有函数调用触发器输入或函数调用输出的子系统创建 S-Function 模块。

函数调用子系统建模模式

当您将生成的 S-Function 模块添加到模型中,然后仿真该模型时,如果生成的 S-Function 使用此函数调用子系统建模模式,MATLAB 可能会崩溃。

Function-call subsystem modeling pattern

函数调用子系统直接连接到 Outport 模块。将子系统连接到 Outport 模块的信号线分支到具有 Update 函数的模块(即在每个主时间步更新的模块,如 Unit DelayMemory)。分支既可以在子系统的内部,也可以在外部。

在包含函数调用子系统的模型中,这些位置之一的 Signal Conversion 模块可以使用生成的 S-Function 解决问题:

  1. 在子系统模块和分支之间

  2. 在分支和根 Outport 模块之间

  3. 在分支和具有 Update 函数的模块之间

Locations where you can insert a Signal Conversion block in function-call subsystem modeling pattern

解决办法中的 Signal Conversion 模块具有以下参数设置:

  • 输出设置为“信号副本

  • 已选择从 '模块简化' 优化中排除此模块

数据存储访问

当模型中的 S-Function 模块在仿真期间访问数据存储时,Simulink 将禁用数据存储诊断。

  • 如果该 S-Function 模块是从模型创建的,则会同时禁用对全局数据存储的诊断。

  • 如果该 S-Function 模块是从子系统创建的,则会禁用对以下数据存储的诊断:

    • 全局数据存储

    • 放置在子系统之外但由 Data Store ReadData Store Write 模块访问的数据存储。

通过子系统封装指定 InportOutport 模块参数

当您尝试运行使用 S-Function 模块的仿真时,从具有子系统封装变量指定的 InportOutport 模块参数的子系统生成的 S-Function 会生成错误。

Invalid setting in 'testSystem/Subsystem/__OutputSSForSFun__/Out2' 
for parameter 'PortDimensions'
...

MEX S-Function 包装器

仅在创建包装的 MATLAB 版本中使用 MEX S-Function 包装器。

相关主题