If you have Embedded Coder® software, you can generate function source code from modeling components to use in an external code base. The generated code does not include supporting scheduling code (for example, a step function). Controlling logic outside of the Simulink® environment invokes the generated function code.
You can generate function code to export for these modeling components:
Export-function models (model containing functional blocks that consist exclusively of function-call subsystems, function-call model blocks, or other export-function models, as described in Export-Function Models Overview)
Export-function subsystems (virtual subsystem that contains function-call subsystems)
To export code that the code generator produces for these modeling components, the modeling components must meet specific requirements.
For models designed in earlier releases, the code generator can export functions from triggered subsystems. The requirements stated for export-function subsystems also apply to exporting functions from triggered subsystems, with the following exceptions:
Encapsulate triggered subsystems from which you intend to export functions in a top-level virtual subsystem.
Triggered subsystems do not have to meet requirements and limitations identified for virtual subsystems that contain function-call subsystem.
Export Functions That Use Absolute or Elapsed Time does not apply to exporting functions from triggered subsystems.
Model solver must be a fixed-step discrete solver.
You must configure each root-level Inport block that triggers a function-call subsystem to output a function-call trigger. These Inport blocks cannot connect to an Asynchronous Task Specification block.
Model or subsystem, must contain only the following blocks at the root level:
Function-call blocks (such as Function-Call Subsystem, Simulink
Function, S-Functions, and Function-Call Model blocks at the root
level if the solver model configuration parameter Tasking and sample time options > Periodic sample time constraint is set to Ensure sample time
independent
)
Inport and Outport blocks (ports)
Constant blocks (including blocks that resolve to constants, such as Add)
Blocks with a sample time of Inf
Merge and data store memory blocks
Virtual connection blocks (such as, Function-Call Split, Mux, Demux, Bus Creator, Bus Selector, Signal Specification, and virtual subsystems that contain these blocks)
Signal-viewer blocks, such as Scope blocks (export-function subsystems only)
When a constant block appears at the top level of the model or subsystem,
you must set the model configuration parameter Optimization > Default parameter behavior for the model or containing model to
Inlined
.
Blocks inside the model or subsystem must support code generation.
Blocks that use absolute or elapsed time must be inside a periodic function-call subsystem with a discrete sample time specified on the corresponding function-call root-level Inport block. See Export Functions That Use Absolute or Elapsed Time.
Data signals that cross the boundary of an exported system cannot be a virtual bus and cannot be implemented as a Goto-From connection. Data signals that cross the export boundary must be scalar, muxed, or a nonvirtual bus.
In addition, for export-function models, you cannot generate code for a rate-based model that includes multiple instances of an export-function model. For example, you cannot generate code for a test harness model that you use for scheduling reusable export-function models during simulation.
For export-function subsystems, the following additional requirements apply:
A trigger signal that crosses the boundary of an export-function subsystem must be scalar. Input and output data signals that do not act as triggers do not have to be scalar.
When a constant signal drives an output port of an export-function subsystem, the signal must specify a storage class.
If you want to export function code for a modeling component with blocks that use absolute or elapsed time, those blocks must be inside a function-call subsystem that:
You configure for periodic execution
You configure the root-level Inport block with a discrete sample time
To configure a function-call subsystem for periodic execution:
In the function-call subsystem, right-click the Trigger block and choose Block Parameters from the context menu.
Set parameter Sample time type to
periodic
.
Set Sample time to the same granularity specified (directly or by inheritance) in the function-call initiator.
Click OK or Apply.
For more information, see Absolute and Elapsed Time Computation.
Subsystem block parameters do not control the names of the files containing the generated code. The file names begin with the name of the exported subsystem.
Subsystem block parameters do not control the names of top-level functions in the generated code. Each function name reflects the name of the signal that triggers the function or (for an unnamed signal) reflects the block from which the signal originates.
You can export function-call systems for the C++ class code interface packaging only when its function specification is set to Default step method. See Customize Generated C++ Class Interfaces. The exported function is compatible with single-threaded execution. To avoid potential data race conditions for shared signals, invoke all members for the class from the same execution thread.
The code generator supports a SIL or PIL block in accelerator mode only if its function-call initiator is noninlined in accelerator mode. Examples of noninlined initiators include Stateflow® charts.
A Level-2 S-function initiator block, such as a Stateflow chart or the built-in Function-Call Generator block, must drive a SIL block.
You can export an asynchronous (sample-time) function-call system, but the software does not support the SIL or PIL block for an asynchronous system.
The use of the TLC function LibIsFirstInit
has been
removed for export-function subsystems.
To generate code for an exported function, iterate through the tasks listed in this table.
Task | Action | More Information |
---|---|---|
1 | Review your assessment of external code characteristics and integration requirements. | Choose an External Code Integration Workflow |
2 | Verify that the model or subsystem that you are exporting satisfies function exporting requirements. | Requirements |
3 | Address data interface requirements by modifying the model or subsystem. | Exchange Data Between External C/C++ Code and Simulink Model or Generated Code |
4 | If necessary, configure function prototype. | Configure Entry-Point Function Interfaces for Simulink Function and Function Caller Blocks and, for fixed-step rate-based models, Configure C Code Generation for Model Entry-Point Functions or Customize Generated C++ Class Interfaces |
5 | If necessary , update the model to place external application-specific code in generated system functions. | Place External C/C++ Code in Generated Code |
6 | Verify that the functions behave and perform as expected during simulation by creating and using a test harness model. The test harness model schedules execution of the functions during simulation. | Configure Model, Generate Code, and Simulate and, if you have Simulink Test™ software, Test Authoring (Simulink Test) |
7 | Configure the model or subsystem for code generation. | Generate Code Using Embedded Coder®, Generate Code That Matches Appearance of External Code, andModel Configuration |
8 | Generate code and a code generation report. | Code Generation |
9 | Review the generated code interface and static code metrics. | Analyze the Generated Code Interface and Static Code Metrics |
10 | Build an executable program that includes the exported function code. | Build Integrated Code Outside the Simulink Environment |
11 | Verify that executable program behaves and performs as expected. |
Multiple approaches are available for generating function code for export to an external development environment. The following table compares approaches. Choose the approach that aligns best with your integration requirements. For more information on how to create export-function models, see Export-Function Models Overview. For more information on generating code for function call subsystems, see Generate Component Source Code for Export to External Code Base.
Condition or Requirement | Use | More Information |
---|---|---|
| Function-call subsystem | |
| Simulink Function block | |
Code responds to an initialization event | Initialize Function block | |
Code responds to a reset event | Reset Function block | |
Code includes entry-point functions beyond what the code
generator produces by default
( ,
,
and
) | S-function | S-Functions and Code Generation |
Single-model execution framework to use as test harness and to export code generated for portions of a model | Export-function subsystem |
This example shows how to generate function code for individual Simulink function blocks and function-call subsystems in a model without generating scheduling code.
To generate function code for export:
Create a model that contains the functions for export.
Create a test harness model that schedules execution of the functions during simulation.
Simulate the model that contains the functions by using the test harness model.
Generate code for the model that contains the functions.
Create Model That Contains Functions for Export
The model with functions for export must satisfy architectural constraints at the model root level. At the root level, valid blocks are:
Inport
Outport
Function-Call Subsystem
Simulink Function
Goto
From
Merge
The code generator produces function code for Function-Call Subsystem, Simulink Function, Initialize Function, and Reset Function blocks. For a Function-call Subsystem block, you connect the block input ports to root Inport blocks that assert function-call signals. The subsystem is executed based on the function-call signal that it receives. A Simulink Function block is executed in response to the execution of a corresponding Function Caller block or Stateflow chart. An Initialize Function block is executed on a model initialize event and a Reset Function block is executed on a user-defined reset event.
For exporting functions, model rtwdemo_functions
contains two function-call subsystems (f1_alg
and f2_alg
) and a Simulink Function block (f3
) for exporting functions. The model also contains an Initialize Function block (Initialize Function
) and a Reset Function block (Reset Function
). To calculate initial conditions for blocks with state in other parts of the model, State Writer blocks are used inside the Initialize Function and Reset Function blocks.
open_system('rtwdemo_functions')
Create Model That Contains Function Caller Block
Use a Function Caller block to invoke a Simulink Function block. The Function Caller block can be in the same model or in a different model as the Simulink Function block.
Multiple Function Caller blocks can invoke a Simulink Function block. You can place the Function Caller block inside a function-call subsystem. During code generation, the code generator exports a function from the function-call subsystem.
The model rtwdemo_caller
exports a function-call subsystem that contains a Function Caller block.
open_system('rtwdemo_caller')
Create Test Harness Model for Simulation
When you export functions, the generated code does not include a scheduler. Create a test harness model to handle scheduling during simulation. Do not use the test harness model to generate code that you deploy.
Model rtwdemo_export_functions
is a test harness. The model:
Schedules the Simulink Function block with the Function Caller block in rtwdemo_caller
.
Provides function-call signals to other models in this example to schedule the model contents, including the model initialize and reset events.
open_system('rtwdemo_export_functions')
Simulate the Test Harness Model
Verify that the model containing the functions that you want to export is executed as you expect by simulating the test harness model. For example, simulate rtwdemo_export_functions
.
sim('rtwdemo_export_functions')
Generate Function Code
Open the Embedded Coder app. Then, generate code for the functions that you want to export. For example, generate code for rtwdemo_functions
.
rtwbuild('rtwdemo_functions')
### Starting build procedure for: rtwdemo_functions ### Successful completion of code generation for: rtwdemo_functions Build Summary Top model targets built: Model Action Rebuild Reason ===================================================================================== rtwdemo_functions Code generated Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.2888s
Review Generated Code
Review the generated code.
ert_main.c
is an example main program (execution framework) for the model. This code shows how to call the exported functions. The code also shows how to initialize and execute the generated code.
rtwdemo_functions.c
calls the initialization function, including Initialize Function
, and exported functions for model components f1_alg
, f2_alg
, and f3
.
rtwdemo_functions.h
declares model data structures and a public interface to the exported entry-point functions and data structures.
f3.h
is a shared file that declares the call interface for the Simulink function f3
.
rtwtypes.h
defines data types, structures, and macros that the generated code requires.
Write Interface Code
Open and review the Code Interface Report. To write the interface code for your execution framework, use the information in that report.
Include the generated header files by adding directives #include rtwdemo_functions.h
, #include f3.h
, and #include rtwtypes.h
.
Write input data to the generated code for model Inport blocks.
Call the generated entry-point functions.
Read data from the generated code for model Outport blocks.
Input ports:
rtU.U1
of type real_T
with dimension 1
rtU.U2
of type real_T
with dimension 1
Entry-point functions:
Initialize entry-point function, void rtwdemo_functions_initialize(void)
. At startup, call this function once.
Reset entry-point function, void rtwdemo_functions_reset(void)
. Call this function as needed.
Exported function, void f1(void)
. Call this function as needed.
Exported function, void f2(void)
. Call this function as needed.
Simulink function, void f3(real_T rtu_u, real_T
*
rty_y)
. Call this function as needed.
Output ports:
rtY.Accumulator1
of type int8_T
with dimension [2]
rtY.Accumulator2
of type int8_T
with dimension [2]
rtY.TicToc10
of type int8_T
with dimension 1
More About
Close Example Models
bdclose('rtwdemo_export_functions') bdclose('rtwdemo_functions') bdclose('rtwdemo_caller')
This example shows how to generate function code for an export-function model that includes a function-call subsystem. The code generator produces function and class code that does not include scheduling code.
To generate function code for export:
Create a model that contains the functions for export.
Create a test harness model that schedules execution of the functions during simulation.
Simulate the model that contains the functions by using the test harness model.
Generate code for the model that contains the functions.
Create Model That Contains Functions and C++ Class Interface for Export
The model with functions for export with a C++ model class interface must satisfy architectural constraints at the model root level. For C++ class generation, blocks that are valid at the root level are:
Inport
Outport
Function-Call Subsystem
Goto
From
Merge
Note: Export Function-Call Subsystem with C++ class interface does not support Simulink Function blocks.
The code generator produces function code for the Function-Call Subsystem block. For a Function-call Subsystem block, you connect the block input ports to root Inport blocks that assert function-call signals. The subsystem is executed based on the function-call signal that it receives.
Model rtwdemo_cppclass_functions
contains function-call subsystems f1
, f2
, and f3
for exporting functions.
open_system('rtwdemo_cppclass_functions')
Create Test Harness Model for Simulation
When you export functions, the generated code does not include a scheduler. Create a test harness model to handle scheduling during simulation. Do not use the test harness model to generate code that you deploy.
Model rtwdemo_cppclass_export_functions
is a test harness. The model provides function-call signals to other models in this example to schedule the model contents.
open_system('rtwdemo_cppclass_export_functions')
Simulate the Test Harness Model
Verify that the model containing the functions that you want to export is executed as you expect by simulating the test harness model. For example, simulate rtwdemo_cppclass_export_functions
.
sim('rtwdemo_cppclass_export_functions')
Generate Function Code and Report
Generate code and a code generation report for the functions that you want to export. For example, generate code for rtwdemo_cppclass_functions
.
rtwbuild('rtwdemo_cppclass_functions')
### Starting build procedure for: rtwdemo_cppclass_functions ### Successful completion of build procedure for: rtwdemo_cppclass_functions Build Summary Top model targets built: Model Action Rebuild Reason =========================================================================================================== rtwdemo_cppclass_functions Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 19.341s
Review Generated Code
From the code generation report, review the generated code.
ert_main.cpp
is an example main program (execution framework) for the model. This code shows how to call the exported functions. The code also shows how to initialize and execute the generated code.
rtwdemo_cppclass_functions.cpp
calls the initialization function, including Initialize Function
, and exported functions for model subsystem components f1
, f2
, and f3
.
rtwdemo_cppclass_functions.h
declares model data structures and a public interface to the exported entry-point functions and data structures.
rtwtypes.h
defines data types, structures, and macros that the generated code requires.
Write Interface Code
Open and review the Code Interface Report. To write the interface code for your execution framework, use the information in that report.
Include the generated header files by adding directives #include rtwdemo_cppclass_functions.h
and #include rtwtypes.h
.
Write input data to the generated code for model Inport blocks.
Call the generated entry-point functions.
Read data from the generated code for model Outport blocks.
Input ports:
rtU.U1
of type real_T
with dimension 1
rtU.U2
of type real_T
with dimension 1
rtU.U3
of type real_T
with dimension 1
Entry-point functions:
Initialize entry-point function, void initialize(void)
. At startup, call this function once.
Exported function, void t_1tic_A(void)
. Call this function as needed.
Exported function, void t_1tic_B(void)
. Call this function as needed.
Exported function, void t_1tic_C(void)
. Call this function as needed.
Output ports:
rtY.TicToc1
of type int8_T
with dimension [2]
rtY.TicToc2
of type int8_T
with dimension [2]
rtY.TicToc10
of type int8_T
with dimension 1
More About
Close Example Models
bdclose('rtwdemo_cppclass_export_functions') bdclose('rtwdemo_cppclass_functions')
To generate code for an export-function subsystem:
Verify that the subsystem for which you are generating code satisfies exporting requirements.
In the Configuration Parameters dialog box:
Set the parameter System target file to an
ERT-based system target file, such as
ert.tlc
.
If you want a SIL block with the generated code, for verification
purposes, set model configuration parameter Create
block to SIL
.
Click OK or Apply.
Right-click the subsystem block and select C/C++ Code > Export Functions from the context menu.
The operation creates a new model,
, that
contains the content of the original subsystem and creates a
subsystem
.slxScratchModel
that contains a Model block. This block
references the newly created
model.subsystem
.slx
The Build code for subsystem:
Subsystem
dialog box opens.
This dialog box is not specific to export-function subsystems. Generating
code does not require entering information in the dialog box.
Click Build to build the newly created
model.subsystem
.slx
The code generator produces code and places it in the working folder.
If you set Create block to
SIL
in step 2b, Simulink opens a new window that contains an S-function block that
represents the generated code. This block has the same size, shape, and
connectors as the original subsystem.
Code generation and optional block creation are now complete. You can test and use the code and optional block as you do for generated ERT code and S-function block. For optional workflow tasks, see Specify a Custom Initialize Function Name and Specify a Custom Description.
You can specify a custom name for the initialize function of your exported
function as an argument to the rtwbuild
command. The command takes
the following form:
blockHandle = rtwbuild('subsystem', 'Mode', 'ExportFunctionCalls',.. 'ExportFunctionInitializeFunctionName', 'fcnname')
specifies the function
name. For example, if you specify the name fcnname
'myinitfcn'
, the
build process emits code similar to:
/* Model initialize function */ void myinitfcn(void){ ... }
You can enter a custom description for an exported function by using the Block Properties dialog box of an Inport block.
Right-click the Inport block that drives the control port of the subsystem for which you are exporting code.
Select Properties.
In the General tab, in the Description field, enter your descriptive text.
During function export, the text you enter is emitted to the generated code in
the header for the Inport block. For example, if you open the example program
rtwdemo_exporting_functions
and enter a description in
the Block Properties dialog box for port t_1tic_A
, the code
generator produces code that is similar to:
/* * Output and update for exported function: t_1tic_A * * My custom description of the exported function */ void t_1tic_A(void) { ... }
To optimize the code generated for an export-function subsystem, specify a separate storage class for each input signal and output signal that crosses the boundary of the subsystem.
For each function-call subsystem that you are exporting:
Right-click the subsystem.
From the context menu, choose Block Parameters (Subsystem).
Select the Code Generation tab.
Set Function packaging to
Auto
.
Click OK or Apply.