通过插入pragma在内存中放置控制数据和函数
对于某些应用程序,可以使用pragmas和其他代码装饰来控制数据(全局变量)和函数定义在内存中的位置。例如,链接器配置文件可以在类中定义命名节部分
指令并将每个节映射到一个内存地址范围。在C代码中,您可以包含将全局变量和函数赋值给这些命名段的pragma,并通过扩展将其赋值给内存范围。通过控制内存位置,您可以:
生成对硬件更有效的代码。
模块化应用程序代码,以便在开发过程后期和部署后更容易维护和修改。
使用嵌入式编码器®内存部分,你可以:
对模型数据和入口点函数的类别应用默认的pragmas或其他装饰。要配置这些默认值,请使用代码映射编辑器。例如,您可以:
对内部数据应用默认pragma,其中包括代码生成器无法通过优化消除的块状态。可以对常量参数应用不同的默认pragma,例如生成的代码必须存储在内存中的非标量参数。
对生成函数的类别应用默认的pragma,包括入口点函数,如
。模型
_step
覆盖单个数据项(如块参数、状态和信号)的默认pragmas。为此,创建您自己的存储类。
覆盖对应于原子子系统的单个函数的默认pragmas,您可以将其配置为在生成的代码中显示为具有单独数据的单独函数。使用子系统参数对话框。
使用内存段插入Pragmas
在本例中,您将为示例模型表示的算法的所有数据和函数配置默认内存位置rtwdemo_roll
。然后,对于一些信号数据,您将覆盖默认位置。
探索示例模型并检查默认生成的代码
打开示例模型。
open_system (“rtwdemo_roll”)
该模型被配置为生成高效的产品代码。例如,配置参数默认参数行为设为
内联
。从模型生成代码。
在代码生成报告中,检查文件
rtwdemo_roll.h
。该文件定义了表示算法所需数据的结构类型。例如,该文件定义了一个表示块状态的结构类型,例如的状态离散时间积分器块。/*块状态(默认存储)系统'
' */ typedef struct {real32_T FixPtUnitDelay1_DSTATE;/* ' /FixPt Unit Delay1' */ real32_T Integrator_DSTATE;/* ' /Integrator' */ int8_T integrator_preresetstate;/* ' /Integrator' */} DW_rtwdemo_roll_T; 该文件还声明了模型的入口点函数。
/*模型入口点函数*/ external void rtwdemo_roll_initialize(void);外部void rtwdemo_roll_step(void);外部void rtwdemo_roll_terminate(void);
检查
rtwdemo_roll.c
。这个文件定义了全局结构变量来存储数据。该文件还定义了函数。
在本例中,假设您的链接器配置文件定义了命名节MYALGORITHM_DATA
和MYALGORITHM_CODE
在一个部分
指令。您可以配置模型,以便生成的代码包含pragmas,将为数据和函数分配的内存放在这些已命名的部分中。
的全局变量
myvar#
, pragma语法为:#pragma SEC_MYALGORITHM_DATA("myVar");
对于名为
myFunction
,除了节名之外,pragma语法是相同的:#pragma SEC_MYALGORITHM_CODE("myFunction") void myFunction(void)
创建内存部分
在本例中,您使用两个语法不同的pragma,因此必须创建两个内存部分。
在模型窗口中,选择代码>C / c++代码>在代码透视图中配置模型。万博1manbetx动态仿真模块®将模型置于代码透视图中,您可以使用该透视图为模型配置代码生成设置。
在框图下面代码的映射>数据默认值,点击嵌入式编码器字典图标。
在嵌入式编码器字典对话框中,选择记忆的部分选项卡。
单击添加按钮。
对于新的内存部分,设置这些选项:
名字来
MYALGORITHM_DATA
。语句包围来
每个变量
。之前的声明来
# pragma SEC_MYALGORITHM_DATA (" $ N”)
。令牌$ N
表示使用内存段的每个变量的名称。
创建另一个与
MYALGORITHM_CODE
。
配置数据和函数的默认Pragmas
在模型中,检查代码的映射>数据默认值选项卡。
在表中,选择港口行。
在属性检查器中,设置记忆的部分来
MYALGORITHM_DATA
。对于表中的其他行,设置记忆的部分来
MYALGORITHM_DATA
。下功能默认值,对于表中的每一行,设置记忆的部分来
MYALGORITHM_CODE
。在当前文件夹中,删除现有的
slprj
文件夹中。配置模型以只生成代码。选择配置参数配置参数>只生成代码。
从模型生成代码。
现在,rtwdemo_roll.c
文件将语法应用于结构变量和函数的定义。对于在“代码映射编辑器”中配置的每一类数据和函数,代码将应用一个pragma。例如,代码应用MYALGORITHM_DATA
Pragma到存储块状态、根级输入和根级输出的每个结构。
/*块状态(默认存储)*/ #pragma SEC_MYALGORITHM_DATA("rtwdemo_roll_DW") DW_rtwdemo_roll_T rtwdemo_roll_DW;/*外部输入(根输入信号默认存储)*/ #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;
在应用默认存储类或函数模板后保留默认内存部分
在“代码映射编辑器”中,可以使用存储类和功能定制模板列,以控制生成代码中数据和函数的默认外观。当使用这些列应用设置时默认的
,代码映射编辑器将丢弃您在属性检查器中应用的内存部分。要保留内存部分,请使用嵌入式编码器字典创建存储类或函数模板,然后将内存部分应用于该存储类或函数模板。
在本例中,您通过创建存储类来配置模型的非参数数据,例如信号和状态,以显示在相同的结构中。为了保留MYALGORITHM_DATA
内存部分,您将内存部分应用于存储类。
在模型的嵌入式编码器字典中,选择存储类选项卡,然后单击添加按钮。
对于新的存储类,设置:
名字来
STRUCT_DATA
。存储类型来
结构化
。记忆的部分来
MYALGORITHM_DATA
。
在“代码映射编辑器”中,在数据默认值,在…存储类列,选择
STRUCT_DATA
对于所有行,除了:全局参数
本地参数
全局数据存储
常量
从模型生成代码。
检查
rtwdemo_roll.c
。现在,该文件定义了一个包含非参数数据的单一结构变量,并对该变量应用了编译。/*存储类STRUCT_DATA */ #pragma SEC_MYALGORITHM_DATA("STRUCT_DATA_rtwdemo_roll") rtwdemo_roll_struct_data_rtwdemo_roll;
在直接应用存储类之后保留默认内存部分
中指定的默认存储类代码的映射>数据默认值时,可以使用模型数据编辑器将存储类直接应用于数据项。直接应用任何存储类,除了汽车
或模型的默认
中指定的默认内存部分数据默认值。要保留内存部分,必须将内存部分定义从嵌入式编码器字典中迁移到一个包中,该包是一个可以包含存储类和内存部分定义的文件夹。然后,您可以在包中创建存储类,将内存部分应用于存储类,并将存储类直接应用于模型数据编辑器中的单个数据项。
在rtwdemo_roll
,在…BasicRollMode
在子系统中,三个增益块表示PID控制算法的参数。在本例中,您配置了这些块的输出信号,以便生成的代码为它们分配内存,并将内存放入MYALGORITHM_DATA
部分。您还可以配置信号,以便代码以mySigs.c
并宣布mySigs.h
。
创建内存段和存储类:
在当前文件夹中,创建一个名为
+ myPackage
。文件夹定义了一个名为myPackage
。要使包在当前文件夹之外可用,您可以添加包含
+ myPackage
文件夹到MATLAB路径。打开自定义存储类设计器。
cscdesigner (“myPackage”);
在自定义存储类设计器中,选择记忆的部分选项卡。
点击新。
对于新的内存部分,设置这些选项,它们与您所设置的选项相匹配
MYALGORITHM_DATA
在嵌入式编码器字典中:名字来
MYALGORITHM_DATA
。语句包围来
每个变量
。之前的声明来
# pragma SEC_MYALGORITHM_DATA (" $ N”)
。
点击应用和保存。
在
myPackage
包文件夹,创建一个名为@Signal
。在
@Signal
文件夹,创建一个名为Signal.m
。classdef信号< Simul万博1manbetxink。信号方法函数setupCoderInfo (h) useLocalCustomStorageClasses (h,“myPackage”);结束函数h =信号()% SIGNAL类的构造函数。结束%构造函数结束结束%的方法结束% classdef
该文件定义了一个名为
myPackage。信号
,它派生自内置类万博1manbetx仿真软件。信号
。类定义覆盖setupCoderInfo
方法,其中万博1manbetx仿真软件。信号
类已经实现。的对象myPackage。信号
类中使用自定义存储类myPackage
包,而不是内置的自定义存储类万博1manbetx
包中。将当前文件夹设置为包含控件的文件夹
+ myPackage
文件夹中。的自定义存储类设计器中
myPackage
,选择自定义存储类选项卡。点击新。
对于新的自定义存储类,设置以下属性:
名字来
myCSC
。清晰的为参数。
记忆的部分来
MYALGORITHM_DATA
。数据范围来
出口
。头文件来
mySigs.h
。定义文件来
mySigs.c
。
点击应用和保存。
要在模型中应用存储类:
在模型中,选择视图>模型浏览器>模型浏览器。
在模型资源管理器模型层次结构窗格中,选择基本工作空间。
在模型资源管理器工具栏中,单击添加信号按下并选择自定义类列表。
在自定义类列表对话框,在信号类,选中旁边的复选框myPackage。信号并点击好吧。
在Model Explorer中,单击旁边的箭头添加信号再次选择myPackage信号。一个
myPackage。信号
对象出现在基本工作区中。删除
myPackage。信号
对象从基本工作区中获取。现在,当您使用模型数据编辑器将存储类应用于信号时,您可以从myPackage
包中。在模型中,导航到
BasicRollMode
子系统。在框图下面,选择模型数据编辑器>信号选项卡。
在模型中,选择三个增益模块。
在模型数据编辑器中,在数据表中,对于任何突出显示的行,设置存储类来
myCSC
。从模型生成代码。
检查生成的文件
mySigs.c
。的全局变量获得块模型中的输出。编译符应用于定义。/*定义自定义存储类: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或其他装饰,请在嵌入式编码器字典或自定义存储类设计器中设置语句包围来变量组
(自定义存储类设计器中的默认值)。
覆盖单个数据元素的默认内存位置
在代码映射编辑器中配置内存部分默认值后(请参阅为模型数据和功能的类别配置默认代码生成),以覆盖单个数据元素(信号、参数和状态)的这些默认设置,通过使用自定义存储类设计器创建存储类和任何所需的内存部分。在设计器中创建存储类时,设置记忆的部分属性设置为适当的内存部分。然后,使用模型数据编辑器将存储类应用于单个数据元素。
选择在哪里创建和存储内存段定义
若要定义内存部分,必须选择在何处创建它:在嵌入式编码器字典中还是在包中(通过使用自定义存储类设计器)。
如果只需要在“代码映射编辑器”中使用内存部分,请在“嵌入式编码器字典”中定义内存部分。
如果您需要在代码映射编辑器之外使用内存部分,例如,在模型数据编辑器中,请在包中定义内存部分。
可选地,您可以通过将包加载到嵌入式编码器字典(参见参考包中的代码生成定义)。但是,如果在字典中创建存储类,则不能将包内存部分应用于它们。要将内存部分与在嵌入式编码器字典中定义的存储类以及在包中定义的其他存储类相关联,请维护内存部分的两个定义:一个在字典中,一个在包中。
在模型之间共享内存段定义
如果在模型的嵌入式编码器字典中定义了内存部分,则不能在其他模型中使用该内存部分。要共享内存部分,请将定义迁移到Simulink数据字典(万博1manbetx
sldd
)。然后,在目标模型之间共享字典。有关更多信息,请参见在模型之间共享嵌入式编码器字典定义。如果您在包中定义了内存部分,那么任何模型都可以使用内存部分。将包含包文件夹的文件夹添加到MATLAB中®路径(见什么是MATLAB搜索路径?(MATLAB))。
在包之间共享内存段(仅限包内存段)
包可以访问和使用在其他包中定义的内存部分,包括自定义包和内置包,如万博1manbetx
。在定义内存部分的包中,只存在一个内存部分的副本。其他包通过指向内存部分的原始位置来引用它。对内存部分的更改,包括对后来MathWorks中内置内存部分的更改®产品发布,立即可在每个参考包。
将一个包配置为引用另一个包中定义的内存部分:
打开自定义存储类设计器。在命令提示符下,输入
cscdesigner
。选择记忆的部分选项卡。
使用选择包选择要引用在其他包中定义的类或节的包。
在内存段定义窗格中,选择要在其下面插入引用的现有定义。
点击新参考。
具有默认名称和属性的新引用将出现在前面选择的定义下面。新的引用被选中,并且参考TAB显示了引用的初始属性。
使用名字字段输入新引用的名称。该名称在导入包中必须是唯一的,但可以与源包中的名称重复。
集参考包中的内存部分指定包含要引用的内存部分的包。
集要引用的内存部分指定要引用的内存部分。
点击好吧或应用将更改保存到内存中。要永久保存更改,请单击保存。
控制内存部分下拉列表外观(仅限包内存部分)
当您应用包内存部分时,您可以从下拉列表中选择内存部分。若要在自定义存储类设计器中控制列表中内存节的顺序,请使用向上和下来按钮。下拉列表中内存部分的顺序与自定义存储类设计器中的顺序相匹配。
保护包内存节的定义(仅限包内存节)
当你点击保存在自定义存储类设计器中,设计器将内存部分和自定义存储类定义保存到csc_registration.m
包文件夹中的文件。若要确定此文件的位置,请在“自定义存储类设计器”中检查文件名。
方法,可以防止对整个包的内存部分定义进行更改csc_registration.m
从MATLAB文件到p文件。使用pcode
函数。
最佳实践是保持csc_registration.m
和csc_registration.p
在您的包文件夹中。这样,如果需要使用设计器修改内存部分,则可以删除csc_registration.p
然后在完成修改后重新生成它。由于文件的p编码版本优先,而这两个文件都存在于包中,因此内存部分受到保护。
。
覆盖子系统功能和数据的默认内存位置
当您使用原子子系统将生成的代码划分为函数时(参见生成子系统代码作为单独的函数和文件),您可以对每个子系统的功能和数据应用不同的内存部分。您还可以指定一个子系统不使用内存区。
若要使用不同的内存部分来覆盖在“代码映射编辑器”中设置的模型级默认值,请参见覆盖原子子系统的内存部分。
要指定子系统不使用内存部分(换句话说,防止子系统继承模型级默认值),请参见指定原子子系统不使用内存部分。
覆盖原子子系统的内存部分
您为子系统指定的内存部分覆盖您在代码映射编辑器中设置的模型级默认值。使用这种技术可以将子例程或子组件(由子系统表示)的数据和指令代码聚合到内存的不同区域。将内存段直接应用于原子子系统:
在包中定义内存部分。不能使用在嵌入式编码器字典中定义的内存部分。
在目标模型中,设置配置参数>代码生成>先进的参数>记忆的部分>包到包的名称。如果软件包没有出现在列表中,请单击刷新包列表。
配置模型的Embedded Coder Dictionary以加载目标包,如参考包中的代码生成定义。
配置目标子系统以使用内存部分。在子系统参数对话框中,在代码生成标签:
集函数包装来
那种一次性的功能
或可重用的功能
(对于可重入代码)。如果你设置函数包装来
那种一次性的功能
,为子系统数据启用内存部分的配置,选择具有单独数据的函数。如果不选择具有单独数据的函数,则子系统数据继承来自模型的内存部分,或者,如果适用的话,继承父子系统。使用如下参数用于初始化/终止函数的内存部分将默认内存段应用于子系统函数和数据。
指定原子子系统不使用内存部分
默认情况下,子系统功能和数据继承您在代码映射编辑器中为相关功能和数据类别指定的模型级内存部分。方法指定函数自定义模板执行类别,该模板携带一个内存段,该内存段应用于子系统执行函数以及模型入口点执行函数。
指定一个子系统不使用内存段:
在目标模型中,设置配置参数>代码生成>先进的参数>记忆的部分>包到以下值之一:
如果模型的嵌入式编码器字典没有引用包中的代码生成定义(参见参考包中的代码生成定义),设置包来
万博1manbetx
。如果模型的嵌入式编码器字典引用了一个包,则设置包那个包裹。
在目标子系统中,在代码生成页签,设置参数,如用于初始化/终止函数的内存部分来
默认的
。有了这个设置,子系统就不用为每个参数所表示的数据或函数使用内存区。
限制和其他考虑
您为具有独立数据的原子的、不可重用的子系统指定的设置仅应用于该子系统的数据和功能,而不适用于类似配置的子子系统中的数据。具有独立数据的原子的、不可重用的子子系统可以从包含模型继承内存部分,而不是从父子系统继承。
如果你使用构建这个子系统或构建选定的子系统要为指定内存部分的原子子系统生成代码,代码生成器将忽略子系统级规范,而使用模型级规范。有关构建子系统的信息,请参见为单个子系统生成代码和可执行文件(万博1manbetx仿真软件编码器)。
创建更少的自定义存储类(仅限包内存部分)
在这个例子中使用内存段插入Pragmas,若要将内存部分应用于单个信号数据项,请使用“自定义存储类设计器”创建自定义存储类。假设您希望对每个信号应用不同的内存部分。而不是复制自定义存储类(myCSC
),并将不同的内存部分与副本关联,从而在自定义存储类设计器中生成两个非常相似的自定义存储类,用于myCSC
,设置记忆的部分来具体的实例
。然后,当您将自定义存储类应用于数据项时,您可以为该数据项选择内存部分。
限制
代码生成器不会将内存段应用于使用这些内置存储类的数据:
ExportedGlobal
ImportedExtern
ImportedExternPointer
在自定义存储类设计器中,为内存部分指定的存储类型限定符限定符文本框仅影响使用以下内置存储类以外的存储类设置的数据项:
ExportedGlobal
ImportedExtern
ImportedExternPointer
代码生成器从其他数据类别中省略限定符。
在自定义块库中创建子系统时,不能为库中的子系统定义指定内存段。相反,为您放置在模型中的子系统实例指定内存部分。
在生成的代码中插入函数和数据的Pragmas
该模型显示了如何在生成的代码中插入函数和数据的pragmas。
探索示例模型
打开示例模型。
open_system (“rtwdemo_memsec”)
指令
通过单击模型中的文档链接了解内存部分。
查看ECoderDemos包中的内存部分,方法是单击模型中的按钮,然后选择记忆的部分选项卡。
通过单击模型中的按钮,查看为该模型选择的内存部分。模型级设置也是原子子系统的默认设置。
打开子系统的子系统参数对话框,以查看模型中每个原子子系统的内存部分设置。
通过单击模型中的按钮生成代码。系统将自动显示HTML格式的报告。类中的数据和函数定义
。c
文件并观察生成的pragmas如何对应于指定的内存段。