Techniques that you can use to combine code, which the code generator produces for multiple models or multiple instances of a model, into one executable program include:
Referenced models. See Model Reference Basics (Simulink) and Generate Code for Referenced Models.
If you have Embedded Coder® software,
interface the code for multiple models to a common harness program.
From the harness program, call the entry-point functions generated
for each model. The ert.tlc
system target file
has restrictions, relating to embedded processing, that could be incompatible
with your application.
Generate reusable, multi-instance code that is reentrant. See Combine Code Generated for Multiple Models or Multiple Instances of a Model.
The S-function system target (rtwsfcn.tlc
)
does not support combining code generated for multiple models.
Consider using model referencing to combine models for simulation and code generation. Model referencing helps with:
Symbol naming consistency
Required scheduling of the overall algorithm
Model configuration consistency
If you combine code generated for different models (that is, without using referenced models), consider:
Data is global. Symbol (name) clashes can result.
Configuration parameter settings for the models must match, including settings such as hardware word sizes.
Reuse and sharing of code can be suboptimal (for example, duplicate code for shared utility functions, scheduling, and solvers).
Scheduling can be more complex (for example, models can have periodic sample times that are not multiples of each other, making scheduling from a common timer interrupt more complicated)
For plant models that use continuous time and state, the continuous time signals connecting models are not handled by a single solver like continuous time signals within a model. This can lead to subtle numeric differences.
If you have Embedded
Coder software, you can specify an owner for
individual data items such as signals, parameters, and states. The owner of a data
item generates the definition (memory allocation and initialization) for the data
item. For example, if you apply a custom storage class to a Simulink.Signal
object so that it appears as a global variable in the
generated code, specify one of the combined models as the owner of the object. The
code generated for that model defines the variable.
If you use model referencing, you can modularize the generated code and establish clear ownership of data when you work in a team.
If you do not use model referencing, you can prevent generation
of duplicate definitions for a data item. For example, suppose you
store a Simulink.Parameter
object in the base workspace
and apply the storage class ExportedGlobal
. If
you generate code from two separate models that use the object, each
model generates a definition for the corresponding global variable.
Instead, you can specify an owner for the object so that only the
owner generates a definition.
To specify an owner for a data item:
Apply a custom storage class to the data item. See Apply Built-In and Customized Storage Classes to Data Elements.
Configure the owner of the data item by specifying a value for the Owner property.
Select model configuration parameter Use owner from data object for data definition placement.
For more information about controlling ownership and file placement of data definitions and declarations, see Control Placement of Global Data Definitions and Declarations in Generated Files.
For each model for which you are combining code, generate the code.
Set the system target file to a GRT- or ERT-based system target file. The system target file for the models you combine, must be the same.
If you intend to have multiple instances of that model in the application,
set model configuration parameter Code interface
packaging to Reusable function
. If
you specified an ERT-based system target file, optionally, you can set model
configuration parameter Use dynamic memory allocation for model
initialization, depending on whether you want to statically
or dynamically allocate the memory for each instance of the model.
Generate source code. The code generator includes
an allocation function in the generated file
.
The allocation function dynamically allocates model data for each
instance of the model.model
.c
After generating source code for each model:
Compile the code for each model that you are combining.
Combine the makefiles generated for the models into one makefile.
Create a combined simulation engine by
modifying a main program, such as rt_malloc_main.c
.
The main program initializes and calls the code generated for each
model.
Run the makefile. The makefile links the object files and the main program into an executable program.
Use unidirectional signal connections between models. This affects
the order in which models are called. For example, if you use an output
signal from modelA
as input to modelB
,
the modelA
output computation should be called
first.
When combining code generated for multiple models or multiple instances of a model:
Configure the models with the same solver mode (single-tasking or multitasking).
If the models use continuous states, configure the models with the same solver.
If the base rates for the models differ, the main program (such
as rt_malloc_main.c
) must set up the timer interrupt
to occur at the greatest common divisor rate of the models. The main
program calls each model at a time interval.
A multiple-model program can log data to separate MAT-files for each model.
Only one of the models in a multiple-model program can use external mode.