文档

生成的代码如何存储内部信号,状态和参数数据

为了从输入中计算输出,生成的代码存储了一些内部数据在全局内存中。不连接到根级输入或输出的信号(轮廓尺寸外港块)是内部数据。

内部数据还包括:

  • 块状态,例如单位延迟块。算法必须在执行周期之间保留状态值,因此生成的代码通常将状态存储在全局内存中(例如,作为全局变量或全局结构变量的字段)。

  • 块参数,例如获得a的参数获得块,代码生成器不能将其值内联到代码中。例如,代码生成器不能内联非标量参数的值。

  • 有条件执行的子系统(如已启用的子系统)的状态指示器。

对于更高效的代码,您可以配置优化,例如配置参数>默认参数行为配置参数>信号存储重用试图消除内部数据的存储。但是,优化不能消除某些数据的存储,这些数据会在生成的代码中消耗内存。

当你理解生成的代码存储内部数据的默认格式时,你可以:

  • 默认情况下使信号可访问和参数可调。然后,您可以在执行期间与代码交互并监视代码。

  • 通过消除内部数据的存储来生成高效的生产代码,并根据硬件和构建工具链控制优化无法消除的数据在内存中的位置。

  • 将内部数据块提升到模型接口,以便其他组件和系统可以访问该数据。

有关生成的代码如何通过接口与调用环境交换数据的信息,请参见生成的代码如何与环境交换数据

生成代码中的内部数据

这个示例展示了生成的代码如何存储块状态等内部数据。

探索范例模型

打开示例模型rtwdemo_roll

open_system (“rtwdemo_roll”

该模型包含不连接到根级导入或输出块的内部信号。一些信号有一个名称,例如phiCmd信号。

该模型还包含一些维护状态数据的块。例如,在BasicRollMode子系统,一个离散时间积分器块标记积分器维护一个状态。

在模型中,设置>代码生成>系统目标文件grt.tlc

set_param (“rtwdemo_roll”“SystemTargetFile”“grt.tlc”

检查以下设置配置参数>代码生成>接口>代码接口封装。设置那种一次性的功能意味着生成的代码不可重用(可重入)。

对于本例,通过清除生成更简单的代码配置参数>代码生成>接口>高级参数> mat文件日志

set_param (“rtwdemo_roll”“MatFileLogging”“关闭”

生成不可重用的代码

设置以下配置参数:

  • 默认参数行为可调

  • 清晰的信号存储重用

set_param (“rtwdemo_roll”“DefaultParameterBehavior”可调的...“OptimizeBlockIOStorage”“关闭”

从模型生成代码。

rtwbuild (“rtwdemo_roll”
开始模型的构建过程:rtwdemo_roll成功完成模型的构建过程:rtwdemo_roll

该文件rtwdemo_roll.h定义几个表示内部数据的结构类型。例如,块输入和输出结构为模型中的每个内部信号定义了一个字段。每个字段名派生于生成信号的块的名称,或者(如果您为信号指定了名称)派生于信号的名称。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.h”);rtwdemodbtype(文件,...'/*块信号(默认存储)*/'“}B_rtwdemo_roll_T;”, 1, 1)
/*块信号(默认存储)*/ typedef struct {real32_T phiCmd;/* '/ModeSwitch' */ real32_T Abs;/* '/Abs' */ real32_T FixPtUnitDelay1;/* '/FixPt Unit Delay1' */ real32_T Xnew;/* '/Enable' */ real32_T TKSwitch;/* '/TKSwitch' */ real32_T RefSwitch;/* '/RefSwitch' */ real32_T Integrator;/* '/Integrator' */ real32_T DispLimit;/* '/DispLimit' */ real32_T Sum;/* '/Sum' */ real32_T disgain; /* '/DispGain' */ real32_T RateLimit; /* '/RateLimit' */ real32_T Sum1; /* '/Sum1' */ real32_T RateGain; /* '/RateGain' */ real32_T Sum2; /* '/Sum2' */ real32_T CmdLimit; /* '/CmdLimit' */ real32_T IntGain; /* '/IntGain' */ real32_T hdgError; /* '/Sum' */ real32_T DispGain_a; /* '/DispGain' */ real32_T Product; /* '/Product' */ boolean_T NotEngaged; /* '/NotEngaged' */ boolean_T TKThreshold; /* '/TKThreshold' */ boolean_T RefThreshold2; /* '/RefThreshold2' */ boolean_T RefThreshold1; /* '/RefThreshold1' */ boolean_T Or; /* '/Or' */ boolean_T NotEngaged_e; /* '/NotEngaged' */ } B_rtwdemo_roll_T;

该文件定义了一个结构类型DWork结构,以表示块的状态,例如离散时间积分器块的状态。

rtwdemodbtype(文件,...'/*块状态(默认存储)'“}DW_rtwdemo_roll_T;”, 1, 1)
/*块状态(默认存储)系统'<根>' */ typedef struct {real32_T FixPtUnitDelay1_DSTATE;/* '/FixPt Unit Delay1' */ real32_T Integrator_DSTATE;/* '/Integrator' */ int8_T Integrator_PrevResetState;/* '/Integrator' */} DW_rtwdemo_roll_T;

该文件定义了一个结构类型来表示参数数据。模型中的每个可调块参数,例如获得增益块的参数,作为该结构的字段出现。如果块参数从MATLAB变量或金宝app仿真软件。参数对象时,变量或对象显示为字段,而不是块参数。

文件还定义了结构类型实时模型数据结构,其单个字段表示生成的代码在执行期间是否遇到错误的运行时指示。

rtwdemodbtype(文件,/*实时模型数据结构*/...'/*块参数(默认存储)*/', 1,0)
/*实时模型数据结构*/ struct tag_RTM_rtwdemo_roll_T {const char_T *errorStatus;};

对于表示实时模型数据结构的结构类型,为文件rtwdemo_roll_types.h创建一个别名,稍后生成的代码将使用该别名为结构分配内存。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll_types.h”);rtwdemodbtype(文件,'/* rtModel */'...“RT_MODEL_rtwdemo_roll_T;”, 1, 1)
/* rtModel的前向声明*/ typedef struct tag_RTM_rtwdemo_roll_T RT_MODEL_rtwdemo_roll_T;

使用这些结构类型,文件rtwdemo_roll.c定义全局结构变量(为其分配内存),为生成的算法存储内部数据。该文件还定义了表示实时模型数据结构的变量和指向该结构的指针。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.c”);rtwdemodbtype(文件,'/*块信号(默认存储)*/'...“= &rtwdemo_roll_M_;”, 1, 1)
/*块信号(默认存储)*/ B_rtwdemo_roll_T rtwdemo_roll_B;/*块状态(默认存储)*/ DW_rtwdemo_roll_T rtwdemo_roll_DW;/*外部输入(默认存储的根输入信号)*/ ExtU_rtwdemo_roll_T rtwdemo_roll_U;/*外部输出(根输出由默认存储的信号提供)*/ ExtY_rtwdemo_roll_T rtwdemo_roll_Y;/*实时模型*/ RT_MODEL_rtwdemo_roll_T rtwdemo_roll_M_;RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M = &rtwdemo_roll_M_;

该模型一步函数,表示主要模型算法,它使用空白空白接口(不带参数)。

rtwdemodbtype(文件,...'/*模型阶跃函数*/'“空白rtwdemo_roll_step(空白), 1, 1)
/* rtwdemo_roll_step(void)

在函数定义中,算法通过直接访问全局变量来执行计算并将中间结果存储在信号和状态结构中。该算法还从相应的全局变量中读取参数数据。例如,在BasicRollMode子系统生成的代码积分器块从结构中读取和写入信号、状态和参数数据。

rtwdemodbtype(文件,'/*离散积分器:" /积分器" *'...'/*离散积分终端:" /Integrator " */', 1, 1)
/ * DiscreteIntegrator:“< S1 > /集成商”如果(rtwdemo_roll_B * /。NotEngaged_e || (rtwdemo_roll_DW。积分器_PrevResetState != 0)) { rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC; } if (rtwdemo_roll_DW.Integrator_DSTATE >= rtwdemo_roll_P.intLim) { rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.intLim; } else { if (rtwdemo_roll_DW.Integrator_DSTATE <= rtwdemo_roll_P.Integrator_LowerSat) { rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_LowerSat; } } rtwdemo_roll_B.Integrator = rtwdemo_roll_DW.Integrator_DSTATE;

由于空白空白接口和数据直接访问,功能不可重入。如果在应用程序中多次调用该函数,则每次调用都将数据写入全局结构变量,后续调用可以读取该数据,从而导致调用之间的无意干扰。

模型初始化函数rtwdemo_roll_initialize将所有内部数据初始化为零。该函数还通过调用专门的宏函数初始化错误状态。初始化函数直接访问全局变量,这意味着该函数不可重入。

rtwdemodbtype(文件,/*模型初始化函数*/...”sizeof (DW_rtwdemo_roll_T)),“, 1, 1)
/*模型初始化函数*/ void rtwdemo_roll_initialize(void){/*注册码*/ /*初始化错误状态*/ rtmSetErrorStatus(rtwdemo_roll_M, (NULL));/* block I/O */ (void) memset(((void *) &rtwdemo_roll_B), 0, sizeof(B_rtwdemo_roll_T));/* states (dwork) */ (void) memset((void *)&rtwdemo_roll_DW, 0, sizeof(DW_rtwdemo_roll_T));

然后,该函数将DWork结构中的块状态初始化为模型中块参数指定的初始值。模型中的三个状态中有两个具有可调的初始值,因此代码通过从参数结构中读取数据来初始化它们。

rtwdemodbtype(文件,...'/* SystemInitialize for Atomic SubSystem: " /RollAngleReference " */'.../*模型终止函数*/, 1,0)
/* SystemInitialize for Atomic SubSystem: '/RollAngleReference' */ /* InitializeConditions for UnitDelay: '/FixPt Unit Delay1' */ rtwdemo_roll_DW. SystemInitialize for Atomic SubSystem: '/RollAngleReference'FixPtUnitDelay1_DSTATE = rtwdemo_roll_P.LatchPhi_vinit;/* SystemInitialize for SubSystem: '/RollAngleReference' */ /* SystemInitialize for Atomic SubSystem: '/BasicRollMode' */ /* InitializeConditions for DiscreteIntegrator: '/Integrator' */ rtwdemo_roll_DW. 'Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC;rtwdemo_roll_DW。积分器_PrevResetState = 0; /* End of SystemInitialize for SubSystem: '/BasicRollMode' */ }

生成可重用代码

您可以将生成的代码配置为可重入的,这意味着您可以在应用程序中多次调用入口点函数。使用这种配置,入口点函数不直接访问全局变量,而是通过正式参数(指针参数)接受内部数据。使用这些指针参数,每个调用都可以在一组单独的全局变量中维护内部数据,防止调用之间的无意交互。

在模型中,设置配置参数>代码生成>接口>代码接口封装可重用的功能

set_param (“rtwdemo_roll”“CodeInterfacePackaging”“可重用函数”

从模型生成代码。

rtwbuild (“rtwdemo_roll”
开始模型的构建过程:rtwdemo_roll成功完成模型的构建过程:rtwdemo_roll

现在,在rtwdemo_roll.h时,实时模型数据结构包含指向错误指示的指针、内部数据和主要输入输出数据的形式ExtUExtY子结构(其中的字段表示模型根级别的import和Outport块)。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.h”);rtwdemodbtype(文件,/*实时模型数据结构*/...'/*依赖源文件的外部数据声明*/', 1,0)
/*实时模型数据结构*/ struct tag_RTM_rtwdemo_roll_T {const char_T *errorStatus;B_rtwdemo_roll_T * blockIO;P_rtwdemo_roll_T * defaultParam;ExtU_rtwdemo_roll_T *输入;ExtY_rtwdemo_roll_T *输出;boolean_T paramIsMalloced;DW_rtwdemo_roll_T * dwork;};

要在应用程序中多次调用生成的代码,您的代码必须为每次调用分配实时模型数据结构的内存。该文件rtwdemo_roll.c定义一个专门的函数,该函数为新的实时模型数据结构分配内存并返回指向该结构的指针。该函数还为模型数据结构中的字段所指向的子结构分配内存,例如DWork结构。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.c”);rtwdemodbtype(文件,/*模型数据分配函数*/'...“RT_MODEL_rtwdemo_roll_T * rtwdemo_roll(空白), 1, 1)
/*模型数据分配函数*/ RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)

该模型一步函数接受表示实时模型数据结构的参数。

rtwdemodbtype(文件,'/*模型阶跃函数*/'“空白rtwdemo_roll_step”, 1, 1)
/* rtwdemo_roll_step(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

在函数定义中,算法首先从实时模型数据结构中提取每个指针到一个局部变量中。

rtwdemodbtype(文件,‘* rtwdemo_roll_P_e = '“rtwdemo_roll_M - >输出;”, 1, 1)
P_rtwdemo_roll_T *rtwdemo_roll_P_e = ((P_rtwdemo_roll_T *) rtwdemo_roll_M->defaultParam);B_rtwdemo_roll_T *rtwdemo_roll_B = ((B_rtwdemo_roll_T *) rtwdemo_roll_M->blockIO);DW_rtwdemo_roll_T *rtwdemo_roll_DW = ((DW_rtwdemo_roll_T *) rtwdemo_roll_M->dwork);ExtU_rtwdemo_roll_T *rtwdemo_roll_U = (ExtU_rtwdemo_roll_T *) rtwdemo_roll_M->输入;ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *) rtwdemo_roll_M->输出;

然后,为了访问存储在全局内存中的内部数据,算法与这些局部变量进行交互。

rtwdemodbtype(文件,'/*离散积分器:" /积分器" */'...'/*离散积分终端:" /Integrator " */', 1, 1)
/* Integrator: '/Integrator' */ if (rtwdemo_roll_B-> nottengaged_e || (rtwdemo_roll_DW->Integrator_PrevResetState != 0)) {rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P_e->Integrator_IC;} if (rtwdemo_roll_DW->Integrator_DSTATE >= rtwdemo_roll_P_e->intLim) {rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P_e->intLim;} else {if (rtwdemo_roll_DW->Integrator_DSTATE <= rtwdemo_roll_P_e->Integrator_LowerSat) {rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P_e->Integrator_LowerSat;rtwdemo_roll_B->Integrator = rtwdemo_roll_DW->Integrator_DSTATE;

类似地,模型初始化函数接受实时模型数据结构作为参数。

rtwdemodbtype(文件,.../*模型初始化函数*/“空白rtwdemo_roll_initialize”, 1, 1)
/*模型初始化函数*/ void rtwdemo_roll_initialize(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

由于对入口点函数的每个调用都与单独的实时模型数据结构交互,因此可以避免调用之间的无意交互。

使用代码生成优化消除内部数据

对于消耗更少内存的更高效的代码,请选择优化,例如默认参数行为这是你之前清除的。

set_param (“rtwdemo_roll”“DefaultParameterBehavior”“内联”...“OptimizeBlockIOStorage”“上”...“LocalBlockOutputs”“上”

在本例中,为了实现更简单的代码,请使用set代码接口打包那种一次性的功能

set_param (“rtwdemo_roll”“CodeInterfacePackaging”“那种一次性函数”

从模型生成代码。

rtwbuild (“rtwdemo_roll”
开始模型的构建过程:rtwdemo_roll成功完成模型的构建过程:rtwdemo_roll

现在,rtwdemo_roll.h不为块输入和输出定义结构。对于模型中的所有内部信号,优化要么消除存储,要么创建局部函数变量,而不是全局结构字段。

优化无法消除三个块状态的存储,因此文件继续定义DWork结构类型。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.h”);rtwdemodbtype(文件,...'/*块状态(默认存储)'“}DW_rtwdemo_roll_T;”, 1, 1)
/*块状态(默认存储)系统'<根>' */ typedef struct {real32_T FixPtUnitDelay1_DSTATE;/* '/FixPt Unit Delay1' */ real32_T Integrator_DSTATE;/* '/Integrator' */ int8_T Integrator_PrevResetState;/* '/Integrator' */} DW_rtwdemo_roll_T;

为离散时间积分器块生成的代码现在只在DWork结构中存储状态和输出数据。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.c”);rtwdemodbtype(文件,'/*更新离散Integrator: " /Integrator " '...'/*离散积分器的更新结束:" /积分器" */', 1, 1)
*增益:'/IntGain' */ rtwdemo_roll_DW.增益:'/Integrator' */ rtwdemo_roll_DW。Integrator_DSTATE += 0.5F * rtb_TKSwitch * 0.025F;如果(rtwdemo_roll_DW。积分器_DSTATE >= 5.0F) { rtwdemo_roll_DW.Integrator_DSTATE = 5.0F; } else { if (rtwdemo_roll_DW.Integrator_DSTATE <= -5.0F) { rtwdemo_roll_DW.Integrator_DSTATE = -5.0F; } } rtwdemo_roll_DW.Integrator_PrevResetState = (int8_T)rtb_NotEngaged_f;

优化还消除了模型中块参数的存储。例如,在离散时间积分器块中饱和上限饱和下限参数设置为intLim-intLimintLim是一个金宝app仿真软件。参数对象,用于存储该值5。在为离散时间积分器生成的代码中,这些块参数和intLim显示为内联文字数字5.0度-5.0度

如果模型包含代码生成器不能直接内联的参数(例如,数组参数),则代码定义表示数据的结构类型。这常数参数结构使用常量存储类型限定符,因此一些构建工具链可以进一步优化程序集代码。

生成代码中的局部变量

当你选择优化时配置参数>启用本地块输出,代码生成器试图通过将内部信号表示为局部变量而不是全局结构的字段来生成更有效的代码。如果局部变量所消耗的内存有超过目标硬件上可用堆栈空间的风险,请考虑通过设置指示最大堆栈大小配置参数>最大堆栈大小(字节)。有关更多信息,请参见最大堆栈大小(字节)

在生成的代码中出现测试点

一个测试点是存储在唯一内存位置中的信号。有关在模型中包含测试点的信息,请参见测试点(金宝app模型)。

当您为包含测试点的模型生成代码时,构建过程会为每个测试点分配一个单独的内存缓冲区。默认情况下,测试点存储为标准数据结构的成员,例如模型_B

如果你有嵌入式编码器®:

  • 控件的代码生成设置,可以控制测试点的默认表示形式内部数据在代码映射编辑器(请参阅配置数据的默认代码生成(嵌入式编码器))。

  • 属性,可以指定构建过程忽略模型中的测试点,从而允许最优的缓冲区分配忽略测试点信号参数。忽略测试点有助于从原型到部署的过渡,并避免由于工作流构件而导致的生成代码的意外退化。看到忽略测试点信号

即使与测试点相关联,虚拟总线也不会出现在生成的代码中。若要在生成的代码中显示总线,请使用非虚拟总线或由类转换为非虚拟总线的虚拟总线信号转换块。

在生成的代码中显示工作区变量

工作空间变量是用于在模型中指定块参数值的变量。工作区变量包括数值MATLAB®变量和金宝app仿真软件。参数存储在工作空间(例如基本工作空间)或数据字典中的对象。

当你设置默认参数行为可调,默认情况下,工作空间变量作为全局参数结构的可调字段出现在生成的代码中。如果使用这样的变量指定多个块参数值,则该变量将显示为全局参数结构的单个字段。代码没有创建多个字段来表示块参数。因此,在代码执行期间调优字段值将改变模型的数学行为,其方式与在仿真期间调优MATLAB变量或参数对象的值相同。

如果您有嵌入式编码器,您可以通过在代码映射编辑器中为参数数据类别指定代码生成设置来控制工作空间变量的默认表示形式(请参阅配置数据的默认代码生成(嵌入式编码器))。

  • 模型参数Category应用于存储在模型工作区中的变量。

  • 外部参数对象类别应用于存储在基本工作区或数据字典中的变量。

将内部数据提升到接口

默认情况下,代码生成器假定应用程序中的其他系统和组件不需要访问内部数据。例如,内部数据要经过优化,可以从生成的代码中消除它们。出于原型和测试的目的,您可以通过清除优化或配置测试点和应用存储类来访问内部数据(参见保留生成代码中的变量)。对于优化的产品代码,配置单个数据项,使其作为模型接口的一部分出现在生成的代码中。

你可以推广的数据

取决于所生成代码的可重入性,也就是您所选择的设置代码接口打包,您可以配置模型中的每个数据项,通过在代码中作为以下实体之一出现来参与接口:

  • 全局符号,如全局变量或对专门化函数的调用

  • 生成的入口点函数的形式参数(参数)

该表显示了每种数据类别可用于参与接口的机制。

数据类别 显示为全局符号 作为入口点函数的参数出现
根级轮廓尺寸外港 仅适用于不可重入模型。 是的。
连接两个街区的信号 仅适用于不可重入模型。

仅用于可重入模型,且仅作为结构的字段。

或者,将信号连接到根级外港块。

阻塞状态 仅适用于不可重入模型。 仅用于可重入模型,且仅作为结构的字段。
数据存储,例如a数据存储内存 是的。 仅用于可重入模型,且仅作为结构的字段。
块参数或参数对象,例如金宝app仿真软件。参数 是的。 只是作为一个结构的场。

单实例算法

对于单实例算法(您可以设置代码接口打包那种一次性的功能),使用模型数据编辑器或属性检查器将存储类直接应用到单个数据项。对于直接应用的存储类,数据项在代码中以全局符号(如全局变量)的形式出现。存储类还防止优化消除数据项的存储。

您可以将存储类应用于信号、块状态和块参数。(对于块参数,您可以通过参数对象间接应用存储类,例如金宝app仿真软件。参数)。然而,对于信号,考虑将信号连接到外港块在模型的根级别。然后,您可以选择将存储类应用到该块。在方框图中,外港块表示该信号代表一个系统输出。

有关存储类的详细信息,请参见将存储类应用于单个信号、状态和参数数据元素

可重入算法

对于可重入算法(您可以设置代码接口打包可重用的功能),使用不同的技术将数据项配置为生成的入口点函数的正式参数(参数)出现在代码中。

  • 对于内部信号,直接应用存储类模型的默认(见将存储类应用于单个信号、状态和参数数据元素)。如果您有嵌入式编码器,请在“代码映射编辑器”中内部数据类别,将默认存储类设置为默认的或到您在嵌入式编码器字典中定义的结构化存储类(请参阅创建用于默认代码生成设置的代码定义(嵌入式编码器))。或者,将信号配置为测试点(参见在生成的代码中出现测试点)。默认情况下,信号显示为标准数据结构之一的字段(请参阅生成的代码如何存储内部信号,状态和参数数据)。如果您不希望信号出现在产品代码中,请使用测试点,以便稍后可以选择模型配置参数忽略测试点信号

    或者,将信号连接到一个外港块在模型的根级别。将信号连接到根级外港块阻止优化从代码中消除信号。要帮助在大型模型中进行信号路由,请使用转到块。

  • 对于块参数,创建一个参数对象,例如金宝app仿真软件。参数并直接应用存储类以外的汽车对物体。存储类阻止优化内联代码中的参数值。

    使用存储类,该参数在模型实例之间共享,这些实例是对入口点函数的调用。函数直接访问形参数据,作为全局符号,而不是参数。您不能将参数配置为作为参数出现在代码中,因此您不能使模型的每个实例对参数使用不同的值。

    有关应用存储类的信息,请参见将存储类应用于单个信号、状态和参数数据元素

内部数据的控件默认表示形式(嵌入式编码器

默认情况下,代码生成器将优化不能消除的内部数据(如大多数状态数据)聚合到标准结构(如DWork结构)中。使用Embedded Coder,您可以控制生成的代码如何存储这些数据。

通过插入Pragmas控制数据在内存中的位置

使用“代码映射编辑器”为每一类数据(如状态和信号)指定默认内存段(内部数据)。在生成的代码中,您的自定义pragmas或其他装饰围绕着数据定义和声明。

您还可以根据模型中的原子子系统划分结构,以便您可以为子例程和其他算法子组件的数据指定不同的默认内存部分。

有关更多信息,请参见通过插入Pragmas控制数据和函数在内存中的位置(嵌入式编码)。

标准数据结构的类型、字段和全局变量的控件名称

您可以控制标准数据结构的一些特征。有关更多信息,请参见数据结构的控制特性(嵌入式编码器)

对于结构特征的其他控制,例如在生成的代码文件中的放置,请使用嵌入式Coder Dictionary创建自己的结构化存储类。然后,使用代码映射编辑器将存储类应用于数据类别。存储类从标准结构中删除数据,创建您可以更精细地控制的其他结构。有关将默认存储类应用于数据类别的详细信息,请参见配置数据的默认代码生成(嵌入式编码)。有关创建存储类的详细信息,请参见为软件架构定义存储类、内存段和功能模板(嵌入式编码)。

根据子组件将数据组织成结构

  • 在标准数据结构中,要创建包含单实例(不可重入)子例程或子组件数据的子结构,请使用原子子系统封装相应的块。在子系统参数中,设置函数包装可重用的功能。有关更多信息,请参见为非虚拟子系统生成模块化函数码(嵌入式编码)。

    或者,将这些块封装在一个模型中并使用模型块。在引用的模型中,set配置参数>模型参考>每个顶级模型允许的实例总数多个。有关更多信息,请参见参考模型的代码生成

  • 要在模型中创建包含多实例(可重入)子例程或子组件数据的独立结构,请使用原子子系统封装相应的块。在子系统参数中,设置函数包装那种一次性的功能并选择具有独立数据的函数。有关更多信息,请参见为非虚拟子系统生成模块化函数码(嵌入式编码)。

    或者,将这些块封装在一个模型中并使用模型块。在参考模型中,选择以下技术之一:

组织信号和参数数据为有意义的,自定义结构和子结构

要将任意信号和参数组织到自定义结构和子结构中,请创建非虚拟总线信号和参数结构。可选地,为了防止优化从代码中消除数据,将总线信号或参数结构的存储类设置为汽车(默认设置)。

在向模型中添加块时,必须显式地将每个新信号和参数放入总线或结构中。

有关更多信息,请参见在生成的代码中将数据组织成结构

创建单独的全局变量,而不是结构字段

若要使内部数据类别在生成的代码中显示为单独的非结构化全局变量,而不是标准数据结构的字段,请使用代码映射编辑器将非结构化存储类应用于数据类别。例如,应用存储类ExportedGlobal。但是,如果通过设置配置参数生成多实例可重入代码代码接口打包到一个值以外那种一次性的功能,对于某些类别的数据不能使用此技术(请参阅在可重入、多实例模型和组件中使用存储类)。

若要使用“代码映射编辑器”将默认存储类应用于数据类别,请参见配置数据的默认代码生成(嵌入式编码)。若要选择存储类,请参见选择在生成的代码中控制数据表示的存储类

相关的话题