对于某些应用程序,您可以使用pragmas和其他代码修饰来控制数据(全局变量)和函数定义在内存中的位置。例如,链接器配置文件可以在类中定义命名节部分
指令并将每个部分映射到一个内存地址范围。在C代码中,可以包含将全局变量和函数分配给这些命名段的pragmas,并扩展到内存范围。通过控制内存位置,你可以:
生成对硬件更有效的代码。
模块化您的应用程序代码,以便在开发过程后期和部署之后更容易维护和修改。
使用嵌入式编码器®内存部分,你可以:
对模型数据和入口点函数的类别应用默认的pragmas或其他装饰。要配置这些默认值,请使用Code Mappings编辑器。例如,你可以:
对内部数据应用默认的pragma,其中包括代码生成器无法通过优化消除的块状态。您可以对常量参数应用不同的默认pragma,例如生成的代码必须存储在内存中的非标量参数。
对生成的函数类别应用默认的pragma,包括入口点函数,例如
.模型
_step
重写个别数据项(如块参数、状态和信号)的默认pragmas。为此,创建自己的存储类。
覆盖对应于原子子系统的单个函数的默认pragmas,您可以将其配置为在生成的代码中作为具有独立数据的独立函数出现。使用子系统参数对话框。
在本例中,为示例模型表示的算法的所有数据和函数配置默认内存位置rtwdemo_roll
.然后,对于某些信号数据,重写默认位置。
打开示例模型。
open_system (“rtwdemo_roll”)
该模型被配置为生成高效的生产代码。例如,配置参数默认参数行为设置为内联
.
在应用程序画廊,下代码生成,点击嵌入式编码器.的C代码选项卡打开。从模型生成代码。
在代码生成报告中,检查文件rtwdemo_roll.h
.该文件定义了表示算法所需数据的结构类型。例如,文件定义了表示块状态的结构类型,例如的状态离散时间积分器块。
/*块信号和状态(默认存储)系统'<根>' */ typedef struct {real32_T FixPtUnitDelay1_DSTATE;/* '/FixPt Unit Delay1' */ real32_T Integrator_DSTATE;/* ' /Integrator' */ int8_T Integrator_PrevResetState;/* ' /Integrator' */} DW;
该文件还声明了模型的入口点函数。
/*模型入口函数*/ extern void rtwdemo_roll_initialize(void);Extern void rtwdemo_roll_step(void)
检查rtwdemo_roll.c
.该文件定义用于存储数据的全局结构变量。该文件还定义了函数。
在本例中,假设连接器配置文件定义了命名节MYALGORITHM_DATA
而且MYALGORITHM_CODE
在一个部分
指令。您可以配置模型,以便生成的代码包括pragmas,将分配给数据和函数的内存放在这些命名的部分中。
的全局变量myvar#
时,pragma语法为:
#pragma SEC_MYALGORITHM_DATA("myVar");
对于一个名为myFunction
,除了section名,pragma语法是一样的:
#pragma SEC_MYALGORITHM_CODE("myFunction")
在本例中,使用了两个语法不同的pragmas,因此必须创建两个内存部分。
打开嵌入式编码器应用程序C代码选项卡上,选择代码接口>嵌入式编码器词典.
在嵌入式编码器词典对话框中,选择记忆的部分选项卡,然后单击添加按钮。
对于新内存部分,设置这些选项:
的名字来MYALGORITHM_DATA
.
语句包围来每个变量
.
之前的声明来# pragma SEC_MYALGORITHM_DATA (" $ N”)
.令牌$ N
表示使用内存段的每个变量的名称。
创建另一个类似的内存段,对应于MYALGORITHM_CODE
.
在C代码选项卡上,选择代码接口>默认代码映射或代码接口>单个元素代码映射
在数据默认值选项卡,扩大导入和输出,信号而且参数.
在表中,选择港口行。
在属性检查器中,设置记忆的部分来MYALGORITHM_DATA
.
对于表中的其他行,请设置记忆的部分来MYALGORITHM_DATA
.
下功能默认值,对于表中的每一行,设置记忆的部分来MYALGORITHM_CODE
.
在当前文件夹中,删除现有的slprj
文件夹中。
将模型配置为只生成代码。选择配置参数配置参数>只生成代码.
点击生成代码.
现在,rtwdemo_roll.c
文件将pragmas应用于结构变量和函数的定义。对于您在Code Mappings编辑器中配置的每个数据和函数类别,代码应用一个pragma。例如,代码应用MYALGORITHM_DATA
到每个存储块状态、根级输入和根级输出的结构的Pragma。
/*块信号和状态(默认存储)*/ #pragma SEC_MYALGORITHM_DATA("rtDW") DW rtDW;/*外部输入(默认存储的根输入信号)*/ #pragma SEC_MYALGORITHM_DATA("rtU") ExtU rtU;/*外部输出(根输出由默认存储的信号提供)*/ #pragma SEC_MYALGORITHM_DATA("rtY") ExtY rtY;
在“代码映射”编辑器中,可以使用存储类而且功能定制模板列来控制生成代码中数据和函数的默认外观。当使用这些列应用其他设置时默认的
,“代码映射”编辑器将丢弃您在“属性检查器”中应用的内存部分。若要保留内存段,请使用嵌入式编码器字典创建存储类或函数模板,然后将内存段应用于该存储类或函数模板。
在本例中,通过创建存储类,将模型的非参数数据(如信号和状态)配置为出现在相同的结构中。为了保留MYALGORITHM_DATA
内存段,将内存段应用到存储类。
在模型的嵌入式编码器字典中,选择存储类选项卡,然后单击添加按钮。
对于新的存储类,设置:
的名字来STRUCT_DATA
.
存储类型来结构化
.
记忆的部分来MYALGORITHM_DATA
.
在“代码映射”编辑器中数据默认值,在存储类列,选择STRUCT_DATA
对于这些行:
港口
外港
信号、状态和内部数据
从模型生成代码。
检查rtwdemo_roll.c
.现在,该文件定义了一个包含非参数数据的结构变量,并将pragma应用于该变量。
/*存储类STRUCT_DATA */ #pragma SEC_MYALGORITHM_DATA("STRUCT_DATA_rtwdemo_roll") rtwdemo_roll_STRUCT_DATA STRUCT_DATA_rtwdemo_roll;
中指定的默认存储类代码映射- C>数据默认值,使用“代码映射”编辑器将存储类直接应用到数据项。直接应用存储类汽车
或模型的默认
绕过中指定的默认内存段数据默认值.要保留内存段,请在嵌入式编码器字典中创建一个存储类,并将所需的内存段应用到它。然后,将存储类应用于Code Mappings编辑器中的各个数据项。其他模型不能访问您在嵌入式编码器字典中定义的存储类和内存部分。若要在其他模型之间共享存储类和内存节节,请将嵌入式编码器字典存储在Simulink数据字典数据(万博1manbetxsldd
)在你的模型之外。然后,在目标模型之间共享字典。有关更多信息,请参见将定义从模型文件迁移到共享数据字典.
在rtwdemo_roll
,在BasicRollMode
子系统中,三个增益块代表PID控制算法的参数。在应用默认存储类或函数模板后保留默认内存段节中,通过应用默认存储类,将模型的非参数数据(如信号和状态)配置为出现在相同的结构中STRUCT_DATA
.在本例中,配置增益块的输出信号,以便生成的代码在中为它们分配内存MYALGORITHM_DATA
节,但不会出现在默认存储类结构中。定义一个新的存储类myStore
在嵌入式编码器字典,并应用所需的内存部分MYALGORITHM_DATA
到它。然后,直接将存储类应用于增益块的输出信号。
在模型的“嵌入式编码器字典”中,选择存储类选项卡,然后单击添加按钮。
对于新的存储类,设置:
的名字来myStore
.
存储类型来结构化
.
记忆的部分来MYALGORITHM_DATA
.
模型中,导航到BasicRollMode
子系统。子系统的信号不会自动填充到Code Mappings编辑器中。您需要手动添加信号,方法是在出现在信号线上方或下方的省略号上暂停以打开操作栏。单击添加信号按钮。控件上的代码映射编辑器中也可以使用该按钮信号/州选项卡。
添加增益块的输出信号后,信号行将出现在代码映射-C>信号/州选项卡。通过选择信号行打开属性检查器。在代码部分,设置这些属性:
存储类来myStore
.
标识符到块名。
从模型生成代码。
检查生成的文件rtwdemo_roll.c
.该文件定义了一个结构变量myStore_rtwdemo_roll
并将pragma应用于变量。
/*存储类myStore */ #pragma SEC_MYALGORITHM_DATA("myStore_rtwdemo_roll") rtwdemo_roll_myStore myStore_rtwdemo_roll;
检查生成的文件rtwdemo_roll.h
.结构变量包含增益块的输出信号。输出信号现在处于不同的结构中,但存储在相同的结构中MYALGORITHM_DATA
内存区。
/*存储类'myStore',用于系统'<根>' */ typedef struct {real32_T disgain;/* '/ disgain ' */ real32_T RateGain;/* ' /RateGain' */ real32_T IntGain;/* ' /IntGain' */} rtwdemo_roll_myStore;
如果构建工具链要求pragma或其他装饰同时包围变量或函数的多个定义,请在嵌入式编码器字典或自定义存储类设计器中设置语句包围来变量组
(自定义存储类设计器中的默认值)。
在代码映射编辑器中配置内存段默认值后(请参阅为数据元素和函数类别配置默认的C代码生成),以覆盖各个数据元素(信号、参数和状态)的默认设置,通过使用嵌入式编码器字典创建一个存储类和任何所需的内存段。欲了解更多信息,选择在哪里创建和存储内存段定义.创建存储类时,设置记忆的部分属性设置为适当的内存部分。然后,使用Code Mappings编辑器将存储类应用到各个数据元素。
要定义内存段,必须选择在何处创建它:在嵌入式编码器字典中还是在Simulink共享字典中。万博1manbetx
如果您只需要在“代码映射”编辑器中使用内存部分,请在“嵌入式编码器字典”中定义内存部分。
如果您只需要在“代码映射”编辑器中使用内存部分,并希望与其他模型共享它,请在Simulink®数据字典(sldd)中定义内存部分。万博1manbetx有关更多信息,请参见在模型之间共享嵌入式编码器字典定义.
如果需要在Code Mappings编辑器之外使用内存部分,请在包中定义内存部分。例如,在包中定义内存段来配置原子子系统的内存段。有关更多信息,请参见覆盖原子子系统的内存部分.
如果在模型的嵌入式编码器字典中定义了内存段,则不能在其他模型中使用该内存段。若要共享内存部分,请将定义迁移到Simulink万博1manbetx®数据字典(sldd
).然后,在目标模型之间共享字典。有关更多信息,请参见将定义从模型文件迁移到共享数据字典.
如果您使用自定义存储类设计器在包中定义内存段,则任何模型都可以使用内存段。有关更多信息,请参见使用自定义存储类设计器创建存储类.将包含包文件夹的文件夹添加到MATLAB中®路径(见什么是MATLAB搜索路径?).
当您使用原子子系统将生成的代码划分为函数时(请参阅将子系统代码生成为独立的函数和文件),您可以将不同的内存段应用于每个子系统的功能和数据。您还可以指定子系统不使用内存段。
若要使用不同的内存部分覆盖在代码映射编辑器中设置的模型级默认值,请参见覆盖原子子系统的内存部分.
若要指定子系统不使用内存段(换句话说,防止子系统继承模型级默认值),请参见指定原子子系统不使用内存段.
您为子系统指定的内存部分将覆盖您在Code Mappings编辑器中设置的模型级默认值。使用这种技术将子例程或子组件(由子系统表示)的数据和指令代码聚合到内存的不同区域。要将内存段直接应用到原子子系统,请使用自定义存储类设计器在包中定义内存段。不能使用在嵌入式编码器字典中定义的内存段。然后,将包加载到模型中,并配置子系统块参数以指定内存部分。
创建内存段:
在当前文件夹中创建名为+ myPackage
.该文件夹定义了一个名为myPackage
.有关更多信息,请参见创建数据类包.
控件的文件夹可用于当前文件夹之外的包+ myPackage
文件夹到MATLAB路径。
打开自定义存储类设计器。
cscdesigner (“myPackage”);
在自定义存储类设计器中,选择记忆的部分选项卡。
点击新.
对于新内存部分,设置这些选项:
的名字来MYALGORITHM_DATA
.
语句包围来每个变量
.
之前的声明来# pragma SEC_MYALGORITHM_DATA (" $ N”)
.
点击应用而且保存.
将当前文件夹设置为包含+ myPackage
文件夹中。
在原子子系统中应用内存段:
配置模型的嵌入式编码器字典,以按照参考包中的代码生成定义.
要将目标子系统配置为指定内存部分,请打开子系统参数对话框。在代码生成标签:
集函数包装来那种一次性的功能
或可重用的功能
(用于可重入代码)。
如果你设置函数包装来那种一次性的功能
,以启用子系统数据的内存段配置,选择具有独立数据的函数.如果不选择具有独立数据的函数,子系统数据从模型继承内存段,如果适用的话,从父子系统继承内存段。
申请MYALGORITHM_DATA
内存段直接给子系统的功能和数据,使用这些块参数:
用于初始化/终止函数的内存部分
内存部分用于执行函数
常量内存区
内存部分用于内部数据
参数内存部分
默认情况下,子系统函数和数据继承您在Code Mappings编辑器中为相关函数和数据类别指定的模型级内存部分。类的函数自定义模板执行类别,并且该模板携带一个内存部分,内存部分应用于子系统执行函数以及模型入口点执行函数。
若要指定子系统不使用内存段,请打开子系统参数对话框。在代码生成选项卡,将这些参数设置为默认的
:
用于初始化/终止函数的内存部分
内存部分用于执行函数
常量内存区
内存部分用于内部数据
参数内存部分
通过这些设置,子系统不再为每个参数所代表的数据或函数使用内存部分。
为具有独立数据的原子性、不可重用子系统指定的设置仅应用于该子系统的数据和函数,而不适用于配置类似的子子系统中的数据。具有独立数据的原子的、不可重用的子子系统可以从包含模型继承内存段,而不是从父子系统继承。
如果你使用构建这个子系统或构建选定的子系统为了为指定内存段的原子子系统生成代码,代码生成器会忽略子系统级规范,而是使用模型级规范。有关构建子系统的信息,请参见为各个子系统生成代码和可执行文件.
包可以访问和使用在其他包中定义的内存段,包括自定义包和内置包,如万博1manbetx
.内存段只存在一个副本,在定义它的包中。其他包通过指向内存段的原始位置来引用它。内存部分的更改,包括对以后MathWorks中内置内存部分的更改®产品发行版,在每个参考包中立即可用。
将一个包配置为引用另一个包中定义的内存段:
打开自定义存储类设计器。在命令提示符下,输入cscdesigner
.
选择记忆的部分选项卡。
使用选择包选择要在其中引用其他包中定义的类或节的包。
在内存段定义窗格中,选择要在其下方插入引用的现有定义。
点击新参考.
具有默认名称和属性的新引用将出现在先前选择的定义下面。新引用被选中,a参考选项卡显示引用的初始属性。
使用的名字字段为新引用输入名称。该名称在导入包中必须唯一,但可以与源包中的名称重复。
集参考包装中的内存部分指定包含要引用的内存段的包。
集要引用的内存段指定要引用的内存段。
点击好吧或应用将更改保存到内存中。若要永久保存更改,请单击保存.
应用包内存段时,从下拉列表中选择内存段。要控制列表中内存段的顺序,请在自定义存储类设计器中使用向上而且下来按钮。下拉列表中内存段的顺序与自定义存储类设计器中的顺序匹配。
当你点击保存中的自定义存储类设计器中,设计器将内存部分和自定义存储类定义保存到csc_registration.m
文件在包文件夹。要确定此文件的位置,请在自定义存储类设计器中检查文件名.
类型的内存段定义可以防止对整个包的内存段定义的更改csc_registration.m
从MATLAB文件到p文件。使用pcode
函数。
最好的做法是坚持csc_registration.m
而且csc_registration.p
在你的包文件夹中。这样,如果需要使用设计器修改内存部分,可以删除csc_registration.p
然后在你完成修改后重新生成。由于文件的p编码版本具有优先级,当两个文件都存在于包中时,内存部分受到保护。
.
代码生成器不会对使用这些内置存储类的数据应用内存段:
ExportedGlobal
ImportedExtern
ImportedExternPointer
在自定义存储类设计器中,使用为内存部分指定的存储类型限定符限定符文本框仅影响使用以下内置存储类以外的存储类设置的数据项:
ExportedGlobal
ImportedExtern
ImportedExternPointer
代码生成器从其他数据类别中省略限定符。
在自定义块库中创建子系统时,不能为库中的子系统定义指定内存段。相反,为您放置在模型中的子系统实例指定内存部分。
这个例子展示了如何在生成的代码中插入pragmas来控制数据和函数在内存中的位置。要为子系统功能配置内存位置,请使用在包中定义的内存部分。这个例子说明了如何使用包中定义的内存段在生成的代码中插入函数和数据的pragmas。
探索范例模型
打开示例模型。
open_system (“rtwdemo_memsec”)
要查看ECoderDemos包中的内存部分,请单击内存段定义按钮,然后在模型中选择记忆的部分选项卡。
若要配置功能和数据的内存区域,请单击为该型号配置内存段按钮。在“代码映射”编辑器中,选择适当的行,然后在“属性检查器”中指定内存段。
模型级设置是原子子系统的默认设置。打开子系统参数下拉列表,查看模型中每个原子子系统的内存部分设置。您可以通过配置子系统块参数来覆盖默认的模型级设置。
要生成代码,请单击使用嵌入式编码器生成代码按钮。自动打开一个代码生成报告。中的数据和函数定义.c
文件,并观察生成的pragmas如何对应于指定的内存段。