文档

通过插入Pragmas来控制数据和功能放置

对于某些应用程序,可以使用pragmas和其他代码修饰来控制数据(全局变量)和函数定义在内存中的位置。例如,链接器配置文件可以在部分指令并将每个section映射到一个内存地址范围。在C代码中,您包含了将全局变量和函数赋给这些命名部分的pragmas,并通过扩展将其赋给内存范围。通过控制内存位置,您可以:

  • 生成对硬件更有效的代码。

  • 模块化应用程序代码,以便在开发过程后期和部署后更容易维护和修改。

嵌入式编码器®和内存部分,你可以:

  • 对模型数据和入口点函数的类别应用默认的实用程序或其他修饰。要配置这些默认值,请使用代码映射编辑器。例如,你可以:

    • 对内部数据应用默认的pragma,其中包括代码生成器无法通过优化消除的块状态。您可以对常量参数应用不同的默认pragma,例如生成的代码必须存储在内存中的非标量参数。

    • 对生成函数的类别应用默认的pragma,包括入口点函数,例如模型_step

  • 覆盖单个数据项(如块参数、状态和信号)的默认pragmas。为此,创建您自己的存储类。

  • 覆盖对应于原子子系统的各个函数的默认实用程序,您可以将其配置为在生成的代码中作为带有独立数据的独立函数出现。使用子系统参数对话框。

通过使用内存段插入Pragmas

在本例中,您为示例模型所表示的算法的所有数据和函数配置了默认内存位置rtwdemo_roll.然后,对于一些信号数据,覆盖默认位置。

探索示例模型并检查默认生成的代码

  1. 打开示例模型。

    Open_System(“rtwdemo_roll”

    该模型被配置为生成有效的生产代码。例如,配置参数默认参数行为被设定为

  2. 应用程序画廊,下面代码生成, 点击嵌入式编码器.这C代码选项卡打开。从模型生成代码。

  3. 在代码生成报告中,检查该文件RTWDEMO_ROLL.H..该文件定义了表示算法所需数据的结构类型。例如,该文件定义了表示块状态的结构类型,例如离散时间积分器块。

    /* Block states (default storage) for system '' */ typedef struct {real32_T FixPtUnitDelay1_DSTATE;/* '/FixPt Unit Delay1' */ real32_T Integrator_DSTATE;/* '/Integrator' */ int8_T integrator_preresetstate;/* '/Integrator' */} DW_rtwdemo_roll_T;

    该文件还声明了模型的入口点函数。

    / *模型入口点函数* / extern void RTWDEMO_ROLL_INITIALIZE(void);extern void rtwdemo_roll_step(void);
  4. 检查RTWDEMO_ROLL.C..这个文件定义了全局结构变量来存储数据。该文件还定义了函数。

在本例中,假设链接器配置文件定义了命名节myalgorithm_data.MYALGORITHM_CODE在一个部分指示。您可以配置模型,以便生成的代码包括Pragmas,将分配的内存放置在这些命名部分中的数据和函数。

  • 的全局变量Myvar.,语用语法为:

    #pragma sec_myalgorithm_data(“myvar”)双重myvar;

  • 的函数myFunction, pragma语法是相同的,除了节名:

    #pragma SEC_MYALGORITHM_CODE("myFunction") void myFunction(void)

创建内存部分

在此示例中,您使用两个具有不同语法的Pragmas,因此您必须创建两个内存部分。

  1. 在框图下面代码的映射>数据默认值,单击嵌入式编码字典图标。

  2. 嵌入式编码字典对话框中,选择记忆的部分选项卡。

  3. 点击添加按钮。

  4. 对于新内存部分,设置以下选项:

    • 的名字myalgorithm_data.

    • 陈述周围每个变量

    • 初级陈述#pragma sec_myalgorithm_data(“$ n”).令牌$ N表示使用内存段的每个变量的名称。

  5. 创建另一个类似的内存部分MYALGORITHM_CODE

配置数据和函数的默认Pragmas

  1. 在模型中,检查代码的映射>数据默认值选项卡。

  2. 在表中,选择港口行。

  3. 在属性检查器中,设置记忆部分myalgorithm_data.

  4. 对于表中的其他行,设置记忆部分myalgorithm_data.

  5. 功能默认值,表示表中每一行的集合记忆部分MYALGORITHM_CODE

  6. 在当前文件夹中,删除现有的slprj.文件夹中。

  7. 配置模型以只生成代码。选择配置参数配置参数>只生成代码

  8. 从模型生成代码。

现在,RTWDEMO_ROLL.C.文件将实用程序应用于结构变量和函数的定义。对于您在代码映射编辑器中配置的每一类数据和函数,代码都应用一个实用程序。例如,代码应用myalgorithm_data.对存储块状态、根级输入和根级输出的每个结构的Pragma。

/*块状态(默认存储)*/ #pragma SEC_MYALGORITHM_DATA("rtwdemo_roll_DW") DW_rtwdemo_roll_T rtwdemo_roll_DW;/*外部输入(root inport signals with default storage) */ #pragma SEC_MYALGORITHM_DATA("rtwdemo_roll_U") ExtU_rtwdemo_roll_T rtwdemo_roll_U;/*外部输出(由默认存储的信号提供的根输出)*/ #pragma SEC_MYALGORITHM_DATA("rtwdemo_roll_Y") ExtY_rtwdemo_roll_T rtwdemo_roll_Y;

在应用默认存储类或函数模板后保留默认内存段

在代码映射编辑器中,您可以使用存储类功能定制模板列,用于控制生成代码中数据和函数的默认外观。当您使用这些列应用除默认的,代码映射编辑器将丢弃您在属性检查器中应用的内存部分。要保留内存部分,请使用Embedded Coder Dictionary创建存储类或函数模板,然后将内存部分应用于该存储类或函数模板。

在此示例中,您可以通过创建存储类来配置模型的非参数数据,例如信号和状态,以与相同的结构中出现。保留myalgorithm_data.内存部分,你将内存部分应用到存储类。

  1. 在模型的嵌入式编码器字典中,选择存储类标签并单击添加按钮。

  2. 对于新的存储类,设置:

    • 的名字struct_data.

    • 存储类型结构化

    • 记忆部分myalgorithm_data.

  3. 在代码映射编辑器中,在数据默认值,在存储类列,选择struct_data.对于所有行,除了:

    • 外部参数对象

    • 模型参数

    • 全球数据存储

    • 常数

  4. 从模型生成代码。

  5. 检查RTWDEMO_ROLL.C..现在,该文件定义了一个包含非参数数据的结构变量,并对该变量应用了pragma。

    /*存储类'STRUCT_DATA' */ #pragma SEC_MYALGORITHM_DATA("STRUCT_DATA_rtwdemo_roll") rtwdemo_roll_STRUCT_DATA STRUCT_DATA_rtwdemo_roll;

在直接应用存储类后保留默认内存部分

中指定的默认存储类代码的映射>数据默认值,您可以使用模型数据编辑器将存储类直接应用于数据项。直接应用任何存储类汽车模型的默认中指定的默认内存部分数据默认值.要保留内存部分,必须将内存部分定义迁移出嵌入的编码器字典和包中,该包是可以包含存储类和内存部分定义的文件夹。然后,您可以在包中创建存储类,将内存部分应用于存储类,并将存储类直接应用于模型数据编辑器中的各个数据项。

rtwdemo_roll,在BasicRollMode子系统中,三个增益块表示PID控制算法的参数。在本例中,配置这些块的输出信号,以便生成的代码为它们分配内存,并将内存放在myalgorithm_data.部分。您还可以配置信号,以便代码在mysigs.c.并在mysigs.h.

要创建内存部分和存储类:

  1. 在当前文件夹中,创建一个名为的文件夹+ mypackage.这个文件夹定义了一个名为myPackage

    要使该包在当前文件夹之外可用,您可以添加包含+ mypackage文件夹到MATLAB路径。

  2. 打开自定义存储类设计器。

    cscdesigner (“myPackage”);
  3. 在自定义存储类设计器中,选择记忆部分选项卡。

  4. 点击

  5. 对于新内存部分,设置这些选项,它们与您设置的选项相匹配myalgorithm_data.在嵌入式编码器字典中:

    • 的名字myalgorithm_data.

    • 陈述周围每个变量

    • 之前的声明#pragma sec_myalgorithm_data(“$ n”)

  6. 点击应用保存

  7. myPackage包文件夹,创建文件夹名为@Signal

  8. @Signal文件夹,创建一个名为的文件Signal.m

    classdef信号方法函数setupCoderInfo (h) useLocalCustomStorageClasses (h,“myPackage”);结束函数h =信号()% SIGNAL类构造函数。结束%构造函数结束结束%的方法结束% classdef

    该文件定义了一个名为myPackage。信号,它派生自内置类金宝app仿真软件。信号.类定义覆盖setupCoderInfo方法,该方法的金宝app仿真软件。信号类已经实现。的新实现指定myPackage。信号类使用自定义存储类myPackage包而不是内置的自定义存储类金宝app包中。

  9. 将当前文件夹设置为包含+ mypackage文件夹中。

  10. 的自定义存储类设计器中myPackage,选择定制的存储类选项卡。

  11. 点击

  12. 对于新的自定义存储类,请设置以下属性:

    • 的名字myCSC

    • 清晰的对于参数

    • 记忆部分myalgorithm_data.

    • 数据范围出口

    • 头文件mysigs.h.

    • 定义文件mysigs.c.

  13. 点击应用保存

要在模型中应用存储类:

  1. 在模型中,在建模选项卡上,选择模型浏览器

  2. 在模型浏览器中模型层次结构窗格中,选择基本工作空间

  3. 在模型资源管理器工具栏中,单击添加信号按钮并选择自定义类列表

  4. 自定义类列表对话框,下信号类,选中旁边的复选框myPackage。信号然后点击好吧

  5. 在模型资源管理器中,单击旁边的箭头添加信号再次,选择myPackage信号.一个myPackage。信号对象出现在基本工作区中。

  6. 删除myPackage。信号对象。现在,当您使用模型数据编辑器将存储类应用于信号时,您可以从myPackage包中。

  7. 在模型中,导航到BasicRollMode子系统。

  8. 在框图下面,选择模型数据编辑器>信号选项卡。

  9. 在模型中,选择三个增益块。

  10. 在模型数据编辑器中,在数据表中,为突出显示的任何行设置存储类myCSC

  11. 从模型生成代码。

  12. 检查生成的文件mysigs.c..该文件定义了与获得块输出在模型中。pragma应用于定义。

    /*定义自定义存储类:myCSC */ #pragma SEC_MYALGORITHM_DATA(" disgain ") real32_T disgain;#pragma SEC_MYALGORITHM_DATA("IntGain") real32_T IntGain;#pragma SEC_MYALGORITHM_DATA("RateGain") real32_T RateGain;

现在,有两个定义myalgorithm_data.内存段存在:一个在嵌入式编码器字典中,一个在myPackage.当您对内存部分进行更改时,请对每个定义进行相同的更改。

配置Pragma以包围定义组

如果构建工具链要求在嵌入式编码器字典或自定义存储类设计器中同时包含多个变量或函数定义的pragma或其他装饰,请设置陈述周围组变量(自定义存储类设计器中的默认值)。

覆盖单个数据元素的默认内存位置

在代码映射编辑器(请参阅配置用于模型数据和函数类别的默认C代码生成),要覆盖单个数据元素(信号、参数和状态)的这些默认设置,请使用自定义存储类设计器创建存储类和任何所需的内存段。在设计器中,当您创建存储类时,将记忆部分属性到适当的内存部分。然后,使用模型数据编辑器将存储类应用于单个数据元素。

选择在何处创建和存储内存段定义

要定义内存段,必须选择创建内存段的位置:在嵌入式编码器字典中还是在包中(通过使用自定义存储类设计器)。

  • 如果需要仅在代码映射编辑器中使用内存部分,请在嵌入的编码器字典中定义内存部分。

  • 例如,如果您需要在模型数据编辑器中使用代码映射编辑器外部的内存部分,请在包中定义包中的内存部分。

    另外,您可以通过将包加载到嵌入式编码器字典(请参阅)来启用代码映射编辑器中的包内存部分请参阅包中的代码生成定义).但是,如果在字典中创建存储类,则不能对它们应用包内存部分。要将内存段与在Embedded Coder Dictionary中定义的存储类以及在包中定义的其他存储类相关联,请维护内存段的两个定义:一个在字典中,另一个在包中。

在模型之间共享内存段定义

  • 如果在模型的嵌入式编码器字典中定义了内存部分,则不能在其他模型中使用内存部分。要共享内存部分,请将定义迁移到Simulink金宝app®数据字典(sldd).然后,在目标模型之间共享字典。有关更多信息,请参见在模型之间共享嵌入式编码器字典定义

  • 如果您在包中定义了内存部分,那么任何模型都可以使用内存部分。将包含包文件夹的文件夹添加到MATLAB中®道路(参见什么是MATLAB搜索路径?(MATLAB))。

包之间共享内存段(仅包内存段)

包可以访问和使用其他包中定义的内存部分,包括自定义包和内置包,例如金宝app.在定义内存部分的包中,内存部分只存在一个副本。其他包通过将内存段指向它的原始位置来引用它。对内存部分的更改,包括稍后MathWorks中对内置内存部分的更改®产品发布,可立即在每个引用包中提供。

将一个包配置为引用另一个包中定义的内存部分:

  1. 打开自定义存储类设计器。在命令提示符处,输入cscdesigner

  2. 选择记忆部分选项卡。

  3. 使用选择包选择要在其中引用其他包中定义的类或节的包。

  4. 记忆部分定义窗格中,选择要在其下面插入引用的现有定义。

  5. 点击新参考

    具有默认名称和属性的新引用将出现在前面选择的定义下方。新引用被选中,并且参考选项卡显示引用的初始属性。

  6. 使用的名字字段输入新引用的名称。名称在导入包中必须是唯一的,但可以在源包中重复名称。

  7. 请参阅包中的内存部分指定包含要引用的内存部分的包。

  8. 记忆部分参考指定要引用的内存段。

  9. 点击好吧应用将更改保存到内存中。要永久保存更改,请单击保存

内存段控制外观下拉列表(仅限包内存段)

当您应用包内存部分时,您可以从下拉列表中选择内存部分。要控制列表中内存段的顺序,请在自定义存储类设计器中使用向上下来纽扣。下拉列表中的内存部分顺序与自定义存储类设计器中的顺序匹配。

包内存段的保护定义(仅包内存段)

当你点击保存在自定义存储类设计器中,设计器将内存段和自定义存储类定义保存到csc_registration.m文件在包文件夹中。要确定此文件的位置,请在自定义存储类设计器中检查文件名

的内存段定义可以避免更改整个包的内存段定义csc_registration.m文件从MATLAB文件到p文件。使用pcode函数。

最好的做法是保持csc_registration.mcsc_registration.p在您的软件包文件夹中。这样,如果您需要使用设计器修改内存段,您可以删除csc_registration.p后来在完成修改后重新生成它。由于文件的poded版本优先于包装中,因此在包中存在两个文件时,内存部分受到保护。

覆盖子系统函数和数据的默认内存位置

当您使用原子子系统将生成的代码分区时(参见生成子系统代码作为单独的函数和文件),您可以对每个子系统的功能和数据应用不同的内存段。您还可以指定一个子系统不使用内存段。

重写原子子系统的内存部分

您为子系统指定的内存部分覆盖您在代码映射编辑器中设置的模型级默认值。使用此技术将子程序或子组件(由子系统表示)的数据和指令代码聚合到内存的不同区域。将内存部分直接应用到原子子系统:

  1. 定义包中的内存段。不能使用在嵌入式编码器字典中定义的内存部分。

  2. 在目标模型中,设置配置参数>代码生成>高级参数>记忆的部分>包裹到包的名称。如果包没有出现在列表中,单击刷新包列表

  3. 配置模型的Embedded Coder Dictionary以加载目标包,如请参阅包中的代码生成定义

  4. 配置目标子系统以使用内存部分。在“子系统参数”对话框中代码生成标签:

    • 函数包装那种一次性的功能可重用的功能可重入代码()。

    • 如果你设置函数包装那种一次性的功能,要启用子系统数据的内存段配置,请选择具有独立数据的函数.如果不选择具有独立数据的函数,子系统数据从模型或(如果适用)父子系统继承内存段。

    • 使用以下参数用于初始化/终止功能的内存部分将默认内存段应用于子系统函数和数据。

指定原子子系统不使用内存部分

默认情况下,子系统函数和数据继承了在代码映射编辑器中指定相关函数和数据类别的模型级存储部分。例如,如果为此指定函数自定义模板执行类别,并且该模板承载存储器部分,存储部分适用于子系统执行功能以及模型入口点执行功能。

要指定子系统不使用内存部分:

  1. 在目标模型中,设置配置参数>代码生成>高级参数>记忆的部分>包裹这些价值观中的一个:

    • 如果模型的Embedded Coder Dictionary没有引用包中的代码生成定义(参见请参阅包中的代码生成定义), 放包裹金宝app

    • 如果嵌入式编码器字典是指模型的涉及包,请设置包裹这个包。

  2. 在目标子系统中,在代码生成页签,设置参数,如用于初始化/终止功能的内存部分默认的.使用此设置,子系统不使用每个参数表示的数据或函数的存储器部分。

限制和其他考虑因素

  • 为具有独立数据的原子、不可重用子系统指定的设置仅适用于该子系统的数据和函数,而不适用于配置类似的子子系统中的数据。具有独立数据的原子的、不可重用的子子系统可以从包含模型(而不是从父子系统)继承内存段。

  • 如果你使用构建这个子系统构建选择子系统要为指定内存段的原子子系统生成代码,代码生成器将忽略子系统级规范,而使用模型级规范。有关构建子系统的信息,请参见为单个子系统生成代码和可执行文件(金宝app仿真软件编码器)。

创建更少的自定义存储类(仅包内存段)

在这个例子中通过使用内存段插入Pragmas,若要将内存部分应用于单个信号数据项,请使用自定义存储类设计器创建自定义存储类。假设您想对每个信号应用不同的存储部分。不复制自定义存储类(myCSC),并将不同的内存部分与副本关联,这将在自定义存储类设计器中产生两个非常相似的自定义存储类myCSC,设置记忆部分实例具体.然后,当您将自定义存储类应用于数据项时,可以为该数据项选择内存部分。

限制

  • 代码生成器不会将内存部分应用于使用这些内置存储类的数据:

    • ExportedGlobal.

    • ImportedExtern

    • ImportedExternPointer

  • 在自定义存储类设计器中,通过使用限定符文本框只影响使用存储类设置(内置存储类除外)的数据项:

    • ExportedGlobal.

    • ImportedExtern

    • ImportedExternPointer

    代码生成器省略了其他数据类别中的限定符。

  • 在自定义块库中创建子系统时,不能在库中为子系统定义指定内存段。相反,为您放置在模型中的子系统实例指定内存部分。

在生成的代码中插入函数和数据的Pragmas

这个模型展示了如何在生成的代码中插入函数和数据的pragmas。

探索示例模型

打开示例模型。

Open_System(“rtwdemo_memsec”

指示

  1. 通过单击模型中的文档链接了解内存部分。

  2. 通过单击模型中的按钮,然后选择来查看ECoderDemos包中的内存部分记忆的部分选项卡。

  3. 通过单击模型中的按钮,查看为该模型选择的内存部分。模型级设置也是原子子系统的默认设置。

  4. 打开子系统的子系统参数对话框,查看模型中每个原子子系统的内存部分设置。

  5. 通过单击模型中的按钮生成代码。代码生成报告将自动显示。中的数据和函数定义.c文件,并观察生成的pragmas如何与指定的内存段相对应。

相关的话题