Generate Component Source Code for Export to External Code Base

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.

Modeling Options

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.

Requirements

  • 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.

Export Functions That Use Absolute or Elapsed Time

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:

  1. In the function-call subsystem, right-click the Trigger block and choose Block Parameters from the context menu.

  2. Set parameter Sample time type to periodic.

  3. Set Sample time to the same granularity specified (directly or by inheritance) in the function-call initiator.

  4. Click OK or Apply.

For more information, see Absolute and Elapsed Time Computation.

Limitations for Export-Function Subsystems

  • 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.

Workflow

To generate code for an exported function, iterate through the tasks listed in this table.

TaskActionMore Information
1Review your assessment of external code characteristics and integration requirements.Choose an External Code Integration Workflow
2Verify that the model or subsystem that you are exporting satisfies function exporting requirements.Requirements
3Address data interface requirements by modifying the model or subsystem. Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
4If 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
5If necessary , update the model to place external application-specific code in generated system functions. Place External C/C++ Code in Generated Code
6Verify 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)
7Configure the model or subsystem for code generation.Generate Code Using Embedded Coder®, Generate Code That Matches Appearance of External Code, andModel Configuration
8Generate code and a code generation report.Code Generation
9Review the generated code interface and static code metrics.Analyze the Generated Code Interface and Static Code Metrics
10Build an executable program that includes the exported function code.Build Integrated Code Outside the Simulink Environment
11Verify that executable program behaves and performs as expected. 

Choose an Integration Approach

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 RequirementUseMore Information
  • Traceability between modeling elements and generated code

  • Local inputs (Inport block) and outputs (Outport block)

Function-call subsystem
  • Control over generated function prototype

  • Formal input arguments (Argument Inport blocks) and output arguments (Argument Outport blocks)

  • Local inputs (Inport block) and outputs (Outport block)

Simulink Function block
Code responds to an initialization eventInitialize Function block
Code responds to a reset eventReset Function block
Code includes entry-point functions beyond what the code generator produces by default (model_initialize, model_step, and model_terminate)S-functionS-Functions and Code Generation
Single-model execution framework to use as test harness and to export code generated for portions of a modelExport-function subsystem

Generate C Function Code for Export-Function Model

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:

  1. Create a model that contains the functions for export.

  2. Create a test harness model that schedules execution of the functions during simulation.

  3. Simulate the model that contains the functions by using the test harness model.

  4. 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.

  1. Include the generated header files by adding directives #include rtwdemo_functions.h, #include f3.h, and #include rtwtypes.h.

  2. Write input data to the generated code for model Inport blocks.

  3. Call the generated entry-point functions.

  4. 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')

Generate C++ Function and Class Code for Export-Function Model

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:

  1. Create a model that contains the functions for export.

  2. Create a test harness model that schedules execution of the functions during simulation.

  3. Simulate the model that contains the functions by using the test harness model.

  4. 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.

  1. Include the generated header files by adding directives #include rtwdemo_cppclass_functions.h and #include rtwtypes.h.

  2. Write input data to the generated code for model Inport blocks.

  3. Call the generated entry-point functions.

  4. 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')

Generate Code for Export-Function Subsystems

To generate code for an export-function subsystem:

  1. Verify that the subsystem for which you are generating code satisfies exporting requirements.

  2. In the Configuration Parameters dialog box:

    1. Set the parameter System target file to an ERT-based system target file, such as ert.tlc.

    2. If you want a SIL block with the generated code, for verification purposes, set model configuration parameter Create block to SIL.

    3. Click OK or Apply.

  3. Right-click the subsystem block and select C/C++ Code > Export Functions from the context menu.

    The operation creates a new model, subsystem.slx, that contains the content of the original subsystem and creates a ScratchModel that contains a Model block. This block references the newly created subsystem.slx model.

    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.

  4. Click Build to build the newly created subsystem.slx model.

    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.

Specify a Custom Initialize Function Name

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')

fcnname specifies the function name. For example, if you specify the name 'myinitfcn', the build process emits code similar to:

/* Model initialize function */
void myinitfcn(void){
...
}

Specify a Custom Description

You can enter a custom description for an exported function by using the Block Properties dialog box of an Inport block.

  1. Right-click the Inport block that drives the control port of the subsystem for which you are exporting code.

  2. Select Properties.

  3. 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)
{
...
}

Optimize Code Generated for Export-Function Subsystems

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:

  1. Right-click the subsystem.

  2. From the context menu, choose Block Parameters (Subsystem).

  3. Select the Code Generation tab.

  4. Set Function packaging to Auto.

  5. Click OK or Apply.

Related Topics