To use code that you generate from a model, you call generated entry-point functions. The calling environment and generated functions exchange input and output data, for example, as global variables or function arguments. Root-level Inport blocks (inports) constitute the input data of the interface. To integrate and deploy the generated code into applications, you can customize how the code generator produces the interface code, including how input data is declared and handled. Customizations can:
Minimize the modifications that you must make to existing code.
Generate stable interfaces that do not change or minimally change when you make changes to your model.
Generate code that exchanges data more efficiently (for example, by using pointers and pass-by-reference arguments for nonscalar data).
For code generation, examples show how to customize the inport interface for model
rtwdemo_configrpinterface
. You can configure code
mappings by using the Code
Mappings Editor or code mappings API (coder.mapping.api.CodeMapping
).
By default, root-level inports in a model appear in generated code as fields of a
global data structure named
.
Based on your code interface requirements, decide whether to customize generation of
root-level inport data. If you do not configure customizations, the code generator
determines whether to eliminate or change the representation of inports in generated
code for optimization purposes. If you configure customizations, decide:model
_ExtU
Whether to set up a default configuration
If a model includes a significant number (for example, more than 10) of root-level inports, it is more efficient to configure the inports with a default setting, and then override that setting for special cases. If the model includes a few root-level inports that have unique source, naming, or placement requirements, consider configuring the inports individually.
How to declare and handle root-level inport data in the generated interface
As separate global variables
To read input data from global variables defined in external code
For referenced model inports, as global variables
(void-void
)
As calls to access functions. Requires Embedded Coder®
As entry-point function arguments. Requires Embedded Coder
For more information about these options, see Control Data and Function Interface in Generated Code.
Other considerations include whether to:
Name inports in the generated code by using Inport block labels that appear in the model or by using unique code identifiers.
Include the volatile
type qualifier in global variable
definitions and declarations. Requires Embedded Coder. See Protect Global Data with const and volatile Type Qualifiers (Embedded Coder).
Place data read into a specific area of memory. Requires Embedded Coder. See Control Data and Function Placement in Memory by Inserting Pragmas (Embedded Coder).
For a list of interface requirements that are relevant to inports with corresponding storage classes and storage class properties, see Choose Storage Class for Controlling Data Representation in Generated Code.
For example model rtwdemo_configrpinterface
, inport interface requirements are:
Get data for root-level inports In1
,
In2
, In3
, and In4
from
an external header file. The data read with In1
is used for
computing a value that is stored in memory, and then used in an if-else
condition of code generated for the Switch block. Data read from
the other three inports is used in lookup tables Table1
and
Table2
.
Data for inport In1
must be passed by value.
Data for inports In2
, In3
, and
In4
must be passed by reference.
Variables representing the inports in the generated code must be named
input1
, input2
,
input3
, and input4
.
For this example, configure inports in rtwdemo_configrpinterface
to meet these code generation
requirements.
A default code generation setting for root-level inports can reduce the effort of preparing a model for code generation, especially if a model has a significant number of inports. Choose configuration settings once, and the code generator applies those settings to the inports across the model. Simulink® stores the default configuration as part of the model.
Consider configuring default code generation settings for model root-level inports if your model uses multiple root-level inports that do not have unique requirements.
This example shows how to use the Code Mappings Editor to configure default settings for root-level inports for model rtwdemo_configrpinterface. Specify that the inports read input from variables declared in an external header file.
Open example model rtwdemo_configrpinterface
. Save a copy of the model to a writable
location.
Open the Simulink Coder app.
In the C Code tab, select Code Interface > Default Code Mappings.
In the Code Mappings editor, under Inports and Outports,
select category Inports. Set the default storage class to
ImportedExternPointer
.
Save the model.
You can configure individual root-level inports for code generation. For example, if a model has two root-level inports that have unique code generation requirements, configure the inports individually. Or, if you configure default settings for inports, configure individual inports to use the default settings or unique settings.
If your model meets at least one of these criteria, consider configuring code generation settings for root-level inports individually:
Uses multiple inports that have unique requirements.
Uses few inports.
Has a default configuration for inports and you need to override the configuration for some specific inports.
This example shows how to use the Code Mappings editor to override the default code
generation configuration for one of the inports in model rtwdemo_configrpinterface
. In the preceding example, you set the default
storage class for inports to ImportedExternPointer
.
The example also shows how to configure identifiers that the code generator uses for naming the four inports in the generated code. You can specify code generation identifiers, for example for integration, without having to modify the model design.
If you have not already done so, complete the steps in Configure Default Code Generation Settings for Root-Level Inports.
In the Code Mappings editor, click the Inports tab. The
editor lists the names of Inport blocks and bus elements that are
in the model. If a port resolves to a signal object, a resolve-to-signal-object
icon appears to the right of the element name. The storage class for each inport
is set to Auto
, which means that the code generator might
eliminate or change the representation of relevant code for optimization
purposes. If optimizations are not possible, the code generator applies the
model default configuration. For this example, the model default configuration
specifies storage class ImportedExternPointer
.
To avoid optimizations and force the code generator to use the default
configuration, set the storage class to Model
default
.
To override the default configuration, specify the storage class that meets the code generation requirements for that inport.
Configure the code generator to apply the default storage class setting to
inports In2
, In3
, and
In4
. Select the rows for the three inports. Then, for one
of the selected inports, set the storage class to Model default:
ImportedExternPointer
.
The storage class for the three selected inports changes to Model default:
ImportedExternPointer
.
For inport In1
, override the default storage class setting.
Set the storage class to ImportedExtern
.
Configure code identifiers for the inports so that the interface argument names in the generated code match the interface names in the external header and definition files. In the Code Mappings editor, select the row for each inport. In the Property Inspector, set the Identifier property to these values.
Inport | Code Identifier |
---|---|
In1 | input1 |
In2 | input2 |
In3 | input3 |
In4 | input4 |
Save the model.
Generate and view the code. For example, in rtwdemo_configrpinterface.c
find where variables
input1
, input2
,
input3
, and input4
are used in the
step entry-point function.
void rtwdemo_configrpinterface_step(void) { mode = ((input1 > rtwdemo_configrpinterface_UPPER) || (input1 < rtwdemo_configrpinterface_LOWER)); dout_Table1 = look1_binlc((*input2), (&(mp_Table1.BP[0])), (&(mp_Table1.Table[0])), 10U); . . . dout_Table2 = look2_binlc((*input3), (*input4), (&(mp_Table2.BP1[0])), (&(mp_Table2.BP2[0])), (&(mp_Table2.Table[0])), (&(rtwdemo_configr_Table2_maxIndex[0])), 3U); dstate_X = dout_Table2; } }
To automate configuration of root-level inports for code generation, use the programming interface for code mappings. For example, when creating custom block libraries or part of an application test environment, use the programming interface to automate data configuration.
This example shows how to use the programming interface to configure default settings
for root-level inports for model rtwdemo_configrpinterface. Three of the four
inports read input from global pointer variables defined in an external file. You
configure the generated code for inports to read input from global pointer variables
by default. Then, override the default code generation configuration for
In1
, which requires that input data be passed by
value.
In addition, you configure code identifiers for the inports so that global variable names in the generated code match the variable names defined in an external file.
Open the example model.
open_system('rtwdemo_configrpinterface')
Create object cm
by calling function
coder.mapping.api.get
. The object stores the data
code generation
configuration for model rtwdemo_configrpinterface
.
cm = coder.mapping.api.get('rtwdemo_configrpinterface');
Configure default settings for inports by calling function
setDataDefault
. For the arguments, specify these values:
The object returned by
coder.mapping.api.get
Inports
for the default category
Property name StorageClass
with property value
ImportedExternPointer
setDataDefault(cm,'Inports','StorageClass','ImportedExternPointer')
Verify your default configuration for inports. Issue a call to getDataDefault
that specifies the
object returned by coder.mapping.api.get
, category
Inports
, and
StorageClass
.
getDataDefault(cm,'Inports','StorageClass') ans = 'ImportedExternPointer'
Override the default inport configuration for inport In1
.
The requirements for that inport differ from requirements of the other three
inports.
By default, Simulink sets the storage class for individual inports to
Auto
. When the storage class is Auto
,
the code generator:
Determines whether to eliminate the data from the generated code for optimization purposes.
If retaining the data, determines how to efficiently represent the data in the generated code, taking into account default configuration settings.
To control the storage class configuration for an inport,
configure settings for the inport with function setInport
.
Configure code generated for inport In1
to read input data
from global variables defined in an external file, as specified in the
requirements. Issue a call to function setInport
that
specifies the object returned by coder.mapping.api.get
,
Inport block named In1
, property name
StorageClass
, and property value
ImportedExtern
.
setInport(cm,'In1','StorageClass','ImportedExtern')
Verify your configuration for inport In1
by calling
function getInport
.
getInport(cm,'In1','StorageClass') ans = 'ImportedExtern'
Configure the code generator to apply your default inport settings to inports
In2
, In3
, and In4
.
For each inport, call function setInport
. Specify the
object returned by coder.mapping.api.get
, the
Inport block name, property name
StorageClass
, and property value Model
default
.
setInport(cm,'In2','StorageClass','Model default') setInport(cm,'In3','StorageClass','Model default') setInport(cm,'In4','StorageClass','Model default')
Verify your configuration changes for inports In2
,
In3
, and In4
with calls to function
getInport
.
getInport(cm,'In2','StorageClass') ans = 'Model default' getInport(cm,'In3','StorageClass') ans = 'Model default' getInport(cm,'In4','StorageClass') ans = 'Model default'
Configure code identifiers for the inports so that the global variables that
represent inports in the generated code match the variable names in the external
definition file. For each inport, call function setInport
.
Specify the object returned by coder.mapping.api.get
, the
Inport block name, property name
Identifier
, and one of these property values.
Inport | Code Identifier |
---|---|
In1 | input1 |
In2 | input2 |
In3 | input3 |
In4 | input4 |
setInport(cm,'In1','Identifier','input1'); setInport(cm,'In2','Identifier','input2'); setInport(cm,'In3','Identifier','input3'); setInport(cm,'In4','Identifier','input4');
Verify your configuration changes for the inports by using calls to function
getInport
.
getInport(cm,'In1','Identifier') ans = 'input1' getInport(cm,'In2','Identifier') ans = 'input2' getInport(cm,'In3','Identifier') ans = 'input3' getInport(cm,'In4','Identifier') ans = 'input4'
Save the model.
Generate and view the code. For example, in rtwdemo_configrpinterface.c
find where variables
input1
, input2
,
input3
, and input4
are used in the
step entry-point function.
void rtwdemo_configrpinterface_step(void) { mode = ((input1 > rtwdemo_configrpinterface_UPPER) || (input1 < rtwdemo_configrpinterface_LOWER)); dout_Table1 = look1_binlc((*input2), (&(mp_Table1.BP[0])), (&(mp_Table1.Table[0])), 10U); . . . dout_Table2 = look2_binlc((*input3), (*input4), (&(mp_Table2.BP1[0])), (&(mp_Table2.BP2[0])), (&(mp_Table2.Table[0])), (&(rtwdemo_configr_Table2_maxIndex[0])), 3U); dstate_X = dout_Table2; } }
Depending on your code generation requirements, choose from these storage classes to configure code generation for root-level inports.
Requirements | Storage Class |
---|---|
Enable optimizations, potentially generating more efficient code. | Auto (Individual mappings only) |
For data elements that cannot be optimized, represent data as a field of a standard data structure. | Default (Default mapping only) |
Prevent optimizations from eliminating storage for a data element and use the default mapping for the data element category. | Model Default (Individual mappings only) ,
Dictionary Default (Individual mappings
only) |
Generate a global variable definition and declaration. | ExportedGlobal |
Generate code that reads from and writes to a global variable or global variable pointer defined by your external code. | ImportedExtern, ImportedExternPointer |
The list of available storage classes might include other project-specific storage classes defined in an Embedded Coder Dictionary. If you have special requirements that are not met by the listed storage classes and you have Embedded Coder software, you can define a storage class. See Define Storage Classes, Memory Sections, and Function Templates for Software Architecture (Embedded Coder).
For an individual inport, use the Identifier storage class property to configure a name for the variable representing the inport in the generated code.
Code
Mappings Editor | coder.mapping.api.CodeMapping