To integrate the generated code with your own external code, you can configure data items in a model, such as signal lines and block parameters, to appear in the generated code as global variables. Use custom storage classes and data types to:
Export or import named numeric data types (typedef
).
Control placement of declarations and definitions in generated and external (exported and imported) files.
Package multiple data items into structures.
Apply the storage type qualifiers const
and volatile
.
Run the script prepare_rtwdemo_advsc
, which prepares the example model rtwdemo_advsc
for this example. Save the model to a writable folder.
run(fullfile(matlabroot,'examples','ecoder','main','prepare_rtwdemo_advsc'))
This data is configured for code generation:
Parameters UPPER
, LOWER
, LIMIT
, K1
, and K2
(Stateflow)
Lookup tables Object
, Table1
, and Table2
Signals Input1
, Input2
, Input3
, Input4
, and output
States X
(delay) and mode
(data store memory)
1. In the Simulink Editor, open the Embedded Coder app.
2. In the model, select the Gain block.
3. In the Property Inspector, next to the value of the Gain parameter, click the action button (the three vertical dots) and select K1 (Model Workspace) > Explore.
The Model Explorer shows the contents of the model workspace. The workspace contains Simulink.Parameter
and Simulink.LookupTable
objects that set parameter values, such as constant scalars and lookup table data, for the blocks in the model.
4. At the bottom of the Simulink Editor window, click the Model Data Editor tab.
5. In the Model Data Editor, click the Signals tab. Review the data types listed for the signals. Multiple signals use the custom data type MYTYPE
. In the base workspace, a Simulink.AliasType
object, MYTYPE
, acts as an alias for the double-precision, floating-point data type double
.
Suppose that you want to configure the generated code to:
Export the declaration of the output signal output
to a generated header file named outSigs.h
.
Import the definitions (memory allocation) and declarations of the input signals input1
through input4
from your external code. You provide the declarations in a header file named inputSigs.h
and the definitions in a source file named globalSigs.c
.
Export the parameters and lookup tables, such as K1
and Table1
, as const volatile
global variables defined in tunableParams.c
and declared in tunableParams.h
.
Apply the C storage type qualifier volatile
to block states, such as the Unit Delay state state_X
, and to data stores such as mode
.
To achieve these goals, apply storage classes to the data items.
1. Click the Code Mappings - C tab.
2. In the Code Mappings editor, click the Data Defaults tab.
3. For Inports, set Storage Class to ImportFromFile
.
3. In the Property Inspector, set HeaderFile to inputSigs.h
.
Alternatively, to configure the signals at the command prompt, use these commands:
coder.mapping.create('rtwdemo_advsc') coder.mapping.defaults.set('rtwdemo_advsc','Inports',... 'StorageClass','ImportFromFile',... 'HeaderFile','inputSigs.h')
To include the external source file globalSigs.c
when compiling and linking the generated code, use model configuration parameter Source files.
1. In the Code Mappings editor, for Outports, set Storage Class to ExportToFile
.
2. In the Property Inspector, set HeaderFile to outSigs.h
.
3. For Model parameters, set Storage Class to ConstVolatile
.
4. In the Property Inspector, set HeaderFile to tunableParams.h
and DefinitionFile to tunableParams.c
.
5. For Internal data, set Storage Class to Volatile
.
coder.mapping.defaults.set('rtwdemo_advsc','Outports',... 'StorageClass','ExportToFile',... 'HeaderFile','outSigs.h') coder.mapping.defaults.set('rtwdemo_advsc','LocalParameters',... 'StorageClass','ConstVolatile',... 'HeaderFile','tunableParams.h',... 'DefinitionFile','tunableParams.c') coder.mapping.defaults.set('rtwdemo_advsc','InternalData',... 'StorageClass','Volatile')
Configure parameters and lookup tables.
1. Click the Model Data Editor tab.
2. In the Model Data Editor, click the Parameters tab.
3. In the Filter contents box, enter model workspace
.
4. For each parameter and lookup table in the model workspace, click the table row. Then, in the Property Inspector, expand the Code section and and set Storage Class to Model default
. With this setting, the parameters and lookup tables acquire code generation settings that you specified as default code mappings for model parameters.
mdlwks = get_param('rtwdemo_advsc','ModelWorkspace'); paramNames = evalin(mdlwks,'whos'); paramNames = {paramNames.name}; for i = 1:length(paramNames) temp = getVariable(mdlwks,paramNames{i}); temp = copy(temp); temp.CoderInfo.StorageClass = 'Model default'; assignin(mdlwks,paramNames{i},copy(temp)) end
Configure data stores.
1. On the Data stores tab, for the data store mode
, set Storage Class to Model default
. The data store acquires the code generation settings that you specified for Internal data.
set_param('rtwdemo_advsc/Data Store Memory','StateStorageClass',... 'Model default')
2. Change the setting of model configuration parameter Global variables from $R$N$M
to $N$M
. With this setting, global variables in the generated code have names that match the corresponding data elements in the model. In this case, the token $R
represents the name of the model, rtwdemo_advsc
.
set_param('rtwdemo_advsc','CustomSymbolStrGlobalVar','$N$M')
To export the data type definition (typedef
) of MYTYPE
from the generated code, configure the DataScope
property of the data type object MYTYPE
by using the command prompt or the object property dialog box. Export the definition to a header file named myTypes.h
.
MYTYPE.DataScope = 'Exported'; MYTYPE.HeaderFile = 'myTypes.h';
You can include (#include
) this exported header file in the external source file globalSigs.c
in which you allocate memory for the input signals input1
through input4
.
1. Configure the model to generate code only.
2. Generate code.
set_param('rtwdemo_advsc','GenCodeOnly','on') rtwbuild('rtwdemo_advsc')
### Starting build procedure for: rtwdemo_advsc ### Successful completion of code generation for: rtwdemo_advsc
3. View the utility file myTypes.h
. The file uses typedef
statements to define the real and complex data types MYTYPE
and cMYTYPE
.
file = fullfile('rtwdemo_advsc_ert_rtw','myTypes.h'); rtwdemodbtype(file,'typedef real_T MYTYPE;','typedef creal_T cMYTYPE;',1,1)
typedef real_T MYTYPE; typedef creal_T cMYTYPE;
4. View the data file outSigs.h
. The file uses the extern
keyword to export the declaration of the output signal output
.
file = fullfile('rtwdemo_advsc_ert_rtw','outSigs.h'); rtwdemodbtype(file,'/* Exported data declaration */','extern MYTYPE output;',1,1)
/* Exported data declaration */ /* Declaration for custom storage class: ExportToFile */ extern MYTYPE output; /* '<Root>/Out1' */
5. View the file rtwdemo_advsc_private.h
. The file uses a #include
statement to include the imported header file inputSigs.h
.
6. View the data file tunableParams.c
. The file defines global variables that correspond to the parameter objects and lookup table objects in the model workspace. The lookup table objects appear as structures, whose type definitions are in rtwdemo_advsc_types.h.
file = fullfile('rtwdemo_advsc_ert_rtw','tunableParams.c'); rtwdemodbtype(file,'/* Definition for custom storage class: ConstVolatile */',... '* File trailer for generated code.',1,0)
/* Definition for custom storage class: ConstVolatile */ const volatile int8_T K1 = 2; /* Referenced by: '<Root>/Gain' */ const volatile int8_T K2 = 3; /* Referenced by: '<Root>/Stateflow Chart' */ const volatile MYTYPE LOWER = -10.0; /* Referenced by: '<Root>/Constant2' */ const volatile Table1_Type Table1 = { { -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 }, { -1.0, -0.99, -0.98, -0.96, -0.76, 0.0, 0.76, 0.96, 0.98, 0.99, 1.0 } } ; /* Referenced by: '<Root>/Table1' */ const volatile Table2_Type Table2 = { { 1.0, 2.0, 3.0 }, { 1.0, 2.0, 3.0 }, { 4.0, 16.0, 10.0, 5.0, 19.0, 18.0, 6.0, 20.0, 23.0 } } ; /* Referenced by: '<Root>/Table2' */ const volatile MYTYPE UPPER = 10.0; /* Referenced by: '<Root>/Constant1' */ /*
7. View the file rtwdemo_advsc.c
. The file allocates memory for the exported signal output
, the state state_X
, and the data store mode
. The definitions of the state and the data store use the qualifier volatile
.
file = fullfile('rtwdemo_advsc_ert_rtw','rtwdemo_advsc.c'); rtwdemodbtype(file,'/* Exported data definition */','volatile MYTYPE state_X;',1,1)
/* Exported data definition */ /* Definition for custom storage class: ExportToFile */ MYTYPE output; /* '<Root>/Out1' */ /* Volatile memory section */ /* Definition for custom storage class: Volatile */ volatile boolean_T mode; /* '<Root>/Data Store Memory' */ volatile MYTYPE state_X; /* '<Root>/Delay' */
When you end your MATLAB session, variables and objects that you create in the base workspace, such as MYTYPE
, do not persist. To permanently store these variables and objects, consider linking the model to a data dictionary.
In the Simulink® Editor Modeling tab, in the Design gallery, select Data Dictionary.
In the Model Properties dialog box, click New.
In the Create a New Data Dictionary dialog box, set File name to myDict
and click Save.
In the Model Properties dialog box, click Apply.
Click Migrate data.
Click Migrate in response to message about copying referenced variables.
Click OK.
Alternatively, to manually migrate the data into a data dictionary, you can use programmatic commands:
1. Create a list of the variables and objects that your model uses. In this case, the only member of the list is MYTYPE.
usedVars = {Simulink.findVars('rtwdemo_advsc','SourceType','base workspace').Name};
2. Create a new data dictionary in your current folder. Link the model to this new dictionary.
myDictObj = Simulink.data.dictionary.create('myDict.sldd'); set_param('rtwdemo_advsc','DataDictionary','myDict.sldd')
3. Import only the variables of interest (in this case, MYTYPE) from the base workspace to the data dictionary.
importFromBaseWorkspace(myDictObj,'clearWorkspaceVars',true,'varList',usedVars); saveChanges(myDictObj);
The data dictionary permanently stores MYTYPE
. To view the contents of the dictionary, click the data dictionary badge in the lower-left corner of the model and select Data Dictionary. Then, in the Model Explorer Model Hierarchy pane, select the Design Data node.
For more information about applying storage classes to data items, see Apply Built-In and Customized Storage Classes to Data Elements.