To replace the direct access to data in the generated code with your own or legacy functions that read and write data in a customized way, you can enable function access on your storage classes. You create these storage classes in the Embedded Coder® Dictionary. Root-level inports, root-level outports, and model parameters that use your storage class appear in the generated code as calls to specified functions. You provide the function declarations and definitions in separate header and source files pointed to by the storage class.
You can define and apply a storage class to root-level inports, root-level outports, and
model parameters so they can be accessed by customizable get
and
set
functions. Such customization can be useful, for example, to
abstract layers of software, gain access to data from an external file or to control access
to critical sections of code.
This example shows how to set up a storage class in the Embedded Coder Dictionary and map the storage class to root-level inports/outports and model parameters in the Code Mappings editor.
Open example model rtwdemo_roll
. In the MATLAB command window, run this
command:
addpath(fullfile(docroot,'toolbox','ecoder','examples'))
get
and set
functions:
Save these files to your local path.
In the Apps gallery, under Code Generation, click Embedded Coder.
To open the Embedded Coder Dictionary, on the C Code tab, click Code Interface > Embedded Coder Dictionary.
The rtwdemo_roll
model has two storage classes:
SignalStruct
and ParamStruct
. They are already
created by using the Add button. This example uses these
storage classes. You can perform the following steps for a storage class that you
create as well.
For the SignalStruct
storage class, in the Property
Inspector pane, update these property values:
Data Access to
Function
Header File to
$R_Value.h
Make sure that Access Mode is set to
Value
. Data Scope is set to
Imported
by default and cannot be changed.
For the ParamStruct
storage class, in the Property
Inspector pane, update these property values:
Data Access to
Function
Header File to
$R_Value.h
These properties are already set:
Access Mode to Value
Data Initialization to
Static
Storage classes used for parameters can have only Data
Initialization set to
Static
.
Open the Configuration Parameters dialog box. Select Code Generation > Custom Code > Additional build information > Source files and specify:
rtwdemo_roll_Value.c
In the Embedded Coder app, open the Code Mappings editor. On the Data Defaults tab, map these model element categories:
Inports to
SignalStruct
Outports to
SignalStruct
Model parameters to
ParamStruct
Build the model and generate code.
In the generated code, view the file rtwdemo_roll.c
. The model
step
function uses the specified get
and
set
functions to execute the algorithm. The generated code accesses the
legacy data by calling the custom, handwritten get
and
set
functions. For example, here is the code snippet for the HDG_Ref
inport:
if (get_HDG_Mode()) { /* Outputs for Atomic SubSystem: '<Root>/HeadingMode' */ rtb_Sum1 = (get_HDG_Ref() - get_Psi()) * 0.015F * get_TAS(); /* End of Outputs for SubSystem: '<Root>/HeadingMode' */ } else { /* Outputs for Atomic SubSystem: '<Root>/RollAngleReference' */ if ((real32_T)fabs(get_Turn_Knob()) >= 3.0F) { rtb_Sum1 = get_Turn_Knob(); }
get
and set
functions if the functions that you write accept and return the expected values.To access data using a pointer, follow all the preceding steps but make these changes:
In the Embedded Coder Dictionary, for storage classes SignalStruct
and
ParamStruct
, specify:
Access Mode to
Pointer
Header File to
$R_Pointer.h
Select Configuration Parameters > Code Generation > Custom Code > Additional build information > Source files and replace rtwdemo_roll_Value.c
with:
rtwdemo_roll_Pointer.c
With the pointer access, a get
function now returns a pointer whose
value must be dereferenced with the *
before use. For example, the
generated code for the HDG_Ref inport now looks like this
code:
if (*get_HDG_Mode()) { /* Outputs for Atomic SubSystem: '<Root>/HeadingMode' */ rtb_Sum1 = (*get_HDG_Ref() - *get_Psi()) * 0.015F * *get_TAS(); /* End of Outputs for SubSystem: '<Root>/HeadingMode' */ } else { /* Outputs for Atomic SubSystem: '<Root>/RollAngleReference' */ if ((real32_T)fabs(tmp_1) >= 3.0F) { rtb_Sum1 = tmp_1; }
Creating your own storage class in Embedded Coder Dictionary gives you the flexibility of customizing function names and return
types. You can also use the storage class GetSet
to access data through
get
and set
functions. For more information, see
Access Data Through Functions with Storage Class GetSet.