A storage class is a code generation setting that you apply to a data item (signal, block parameter, or state) in a model. When you directly apply it to a data item, a storage class:
Causes the data item to appear in the generated code as a global symbol, typically a global variable.
Prevents optimizations such as Default parameter behavior and Signal storage reuse from eliminating the data item from the generated code.
With Embedded
Coder®, you can configure the format in which the generated code stores or
otherwise defines the data item. For example, you can apply the storage type qualifiers
const
or volatile
or configure a parameter data
item to appear as a macro (#define
).
Directly apply storage classes to individual data items to:
Tune parameters and monitor signals and states during execution.
Configure data placement in memory through memory sections.
Generate code that exchanges data (for example, global variables) with your external code.
For information about applying storage classes to categories of data by default, by using the Code Mapping Editor, see Configure Default Code Generation for Data.
This example shows how to apply storage classes to a signal, a block state, and a block parameter in a model.
Explore Example Model
Open the example model rtwdemo_roll
.
open_system('rtwdemo_roll')
Navigate into the BasicRollMode
subsystem.
open_system('rtwdemo_roll/BasicRollMode')
The subsystem contains an Integrator block, which maintains a piece of state data.
From the root level of the model, navigate into the RollAngleReference
subsystem.
open_system('rtwdemo_roll/RollAngleReference')
The subsystem contains a Constant block labeled UpThr.
In this example, you configure the state and output signal of the Integrator block and the Constant value parameter of the Constant block to appear in the generated code as separate global variables.
Apply Storage Classes
Navigate to the root level of the model.
Open the Simulink Coder app. When prompted, change the system target file to grt.tlc
.
Click the Model Data Editor tab.
In the Model Data Editor, click the Change scope button. This expands the lists of data elements to include in the subsystems.
Select the Signals tab.
Set the Change view drop-down list to Code
.
In the Filter contents box, enter integrator
.
Optionally, use the Name column to specify a name for the output signal of the Integrator block, such as mySignal
.
Use the Storage Class column to apply storage class ExportedGlobal
.
Select the States tab.
Optionally, use the Name column to specify a name for the state, such as myState
.
Use the Storage Class column to apply storage class ExportedGlobal
.
Select the Parameters tab. You cannot apply a storage class directly to a block parameter. You must create a parameter object, such as Simulink.Parameter
, use the object to set the value of the block parameter, and apply the storage class to the object.
Set the Change view drop-down list to Design
.
In the Filter contents box, enter UpThr
.
Use the Value column to change the parameter value from 6
to UpThr
.
While editing the parameter value, next to UpThr
, click the action button (with three vertical dots) and select Create.
In the Create New Data dialog box, set Value to Simulink.Parameter
and Location to Base Workspace
. Click Create. A Simulink.Parameter
object named UpThr
appears in the base workspace.
In the UpThr
property dialog box, set Value to 6
and Storage class to ExportedGlobal
. Click OK.
Alternatively, you can use these commands at the command prompt to configure the signal, state, and parameter data.
% Configure signal portHandles = get_param('rtwdemo_roll/BasicRollMode/Integrator',... 'PortHandles'); outportHandle = portHandles.Outport; set_param(outportHandle,'Name','mySignal') set_param(outportHandle,'StorageClass','ExportedGlobal') % Configure state set_param('rtwdemo_roll/BasicRollMode/Integrator',... 'StateName','myState') set_param('rtwdemo_roll/BasicRollMode/Integrator',... 'StateStorageClass','ExportedGlobal') % Configure parameter set_param('rtwdemo_roll/RollAngleReference/UpThr','Value','UpThr') UpThr = Simulink.Parameter(6); UpThr.StorageClass = 'ExportedGlobal';
Generate and Inspect Code
Generate code from the model.
set_param('rtwdemo_roll','SystemTargetFile','grt.tlc') rtwbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll ### Generated code for 'rtwdemo_roll' is up to date because no structural, parameter or code replacement library changes were found. ### Successful completion of build procedure for: rtwdemo_roll
Inspect the file rtwdemo_roll.c
. The file defines the global variables.
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c'); rtwdemodbtype(file,'/* Exported block signals */','real32_T myState;',1,1)
/* Exported block signals */ real32_T mySignal; /* '<S1>/Integrator' */ /* Exported block parameters */ real32_T UpThr = 6.0F; /* Variable: UpThr * Referenced by: '<S3>/UpThr' */ /* Exported block states */ real32_T myState; /* '<S1>/Integrator' */
The file rtwdemo_roll.h
declares the variables. To access these variables, your external code can include (#include
) this header file.
In rtwdemo_roll.c
, search the file for the names of the variables, such as UpThr
. The model algorithm in the rtwdemo_roll_step
function reads and writes to the variables.
The default storage class setting for a data item is Auto
, which
means the code generator determines how the item appears in the code. For a list of built-in
storage classes that you can choose, see Choose Storage Class for Controlling Data Representation in Generated Code (Simulink Coder).
For each individual signal or state data item (including Data Store
Memory blocks) to which you directly apply a storage class, Simulink®stores your storage class specification either in the model file or in the
properties of a signal data object (Simulink.Signal
), which you create in
the base workspace, a model workspace, or a data dictionary. To apply a storage class to a
block parameter, you must create a parameter data object (such as
Simulink.Parameter
) and specify the storage class in the object.
When you apply a storage class to a signal or state in a model, for example, by using the Model Data Editor or the Property Inspector, you store the storage class specification in the model file.
If you use this technique, you cannot control other characteristics of the data item, such as data type, by using an external signal data object.
When you create a signal or parameter data object, you apply the storage class by
using the CoderInfo
property of the object. The value of the
property is a Simulink.CoderInfo
object, whose
StorageClass
property you use to specify the storage class.
After you associate the data item in the model with the object, the data item acquires
the storage class from the object.
For signals, states, and Data Store Memory blocks, to decide whether to store the storage class specification in the model or in a data object, see Store Design Attributes of Signals and States (Simulink).
You can use the Model Data Editor to apply a storage class directly to a root-level Outport block or to the input signal that drives the block.
To store the storage class specification in the Outport block, use the Inports/Outports tab in the Model Data Editor. When you use this technique, the specification remains after you delete the input signal that drives the block. Use this technique to configure the model interface before you develop the internal algorithm.
To store the specification in the input signal that drives the block, use the Signals tab in the Model Data Editor.
To apply storage classes to multiple data items in a list that you can search, sort, and filter, use the Model Data Editor (on the Modeling tab, click Model Data Editor) as shown in Apply Storage Classes to Data Items.
To apply a storage class while focusing on a single signal, block state, or parameter, use the Property Inspector (on the Modeling tab, under Design, click Property Inspector), the Signal Properties dialog box (for a signal), or the block dialog box (for a state or parameter). Under Code Generation, apply the storage class.
For a parameter, first set the value of the parameter to the name that you want to use for the required parameter object. Then, create and configure the parameter object as shown in Create Tunable Calibration Parameter in the Generated Code.
For a signal, state, or Data Store Memory block, first give the signal or state a name, which the code generator uses as the name of the corresponding global symbol. Then, either specify a storage class using Storage class (in which case the model file stores the specification) or create a signal data object as shown in Use Data Objects in Simulink Models (Simulink) and apply a storage class to the object.
For a block parameter, use set_param
to set the value of the
parameter. Use other commands to create and configure the properties of the required
parameter object. For an example, see Create Tunable Calibration Parameter in the Generated Code.
For a signal, use get_param
or find_system
to return a handle to the block port that generates the signal. Use the parameters of
the handle to name the signal, then apply the storage class directly (see Apply Storage Class Directly to Signal Line (Simulink Coder)) or configure the
signal to acquire settings, including the storage class, from a signal object (see
Use Data Objects in Simulink Models (Simulink)).
For an Inport block, configure the signal line that exits the block. For an Outport block, configure the block or the signal line that enters the block. For an example, see Design Data Interface by Configuring Inport and Outport Blocks.
For a block state, use set_param
to interact with the block.
Name the state, then apply the storage class directly (see Apply Storage Class Directly to Block State (Simulink Coder)) or configure the
state to acquire the storage class from a signal object (see Use Data Objects in Simulink Models (Simulink)).
For a Data Store Memory block, use set_param
to
interact with the block. Because the data store already has a name, you do not need to
specify a name. Apply the storage class directly by using the
StateStorageClass
parameter or configure the data store to
acquire the storage class from a signal object.
To interact with a signal or parameter data object that you store in a model workspace or data dictionary, use the programmatic interface of the workspace or dictionary. See Interact With Variables Programmatically (Simulink).
This example shows how to programmatically apply a storage class directly to a signal line.
Open the example model rtwdemo_secondOrderSystem
.
rtwdemo_secondOrderSystem
Get a handle to the output of the block named Force: f(t).
portHandles = ... get_param('rtwdemo_secondOrderSystem/Force: f(t)','PortHandles'); outportHandle = portHandles.Outport;
Set the name of the corresponding signal to
ForceSignal
.
set_param(outportHandle,'Name','ForceSignal')
Set the storage class of the signal to ExportedGlobal
.
set_param(outportHandle,'StorageClass','ExportedGlobal')
Generate code from the model. The code declares and defines a global variable
ForceSignal
to represent the signal.
This example shows how to programmatically apply a storage class to a block state.
Open the example model rtwdemo_basicsc
.
rtwdemo_basicsc
Name the state of the Delay block as
myState
.
set_param('rtwdemo_basicsc/Delay','StateName','myState')
Set the storage class of the state to ExportedGlobal
.
set_param('rtwdemo_basicsc/Delay',... 'StateStorageClass','ExportedGlobal')
Generate code from the model. The code declares and defines a global variable
myState
to represent the state.
This diagram shows the code generation and storage class options that control the representation of parameter objects in the generated code.