%% Partition Functions in Generated Code
% This example shows how to associate subsystems in a model with function names and files.
% Learn how to:
% Specify function and file names in the generated code.
% Identify the parts of the generated code that are required for integration.
% Generate code for atomic subsystems.
% Identify data that are required to execute a generated function.
% For information about the example model and other examples in this series, see Generate C Code from a Control Algorithm for an Embedded System.
%% Atomic and Virtual Subsystems
% The example models in Generate C Code from a Control Algorithm for an Embedded System and Configure Data Interface in the Generated Code use virtual subsystems. Virtual subsystems visually organize blocks but do not affect the model functionality. Atomic subsystems evaluate the blocks included in a model as a unit. With atomic subsystems, you can specify additional function partitioning information. In a model, atomic subsystems appear with a bold border.
%% View Changes in Model Architecture
% Open the example model rtwdemo_PCG_Eval_P3.
% Save a copy of the model to a writable folder.
% This example shows how to replace the virtual subsystems with function-call subsystems. Function-call subsystems:
% Are atomic subsystems
% Enable you to control subsystem execution order
% Execute when a function call signal triggers
% By controlling the execution order of the subsystems, you can match the model with an existing system that has a specific execution order.
% The figure identifies the function call subsystems (1) PI_ctrl_1,  PI_ctrl_2, and Pos_Command_Arbitration.
%
% This version of the model contains the new subsystem Execution_Order_Control (2), which contains a Stateflow® chart that models the calling functionality of a scheduler. The subsystem controls the execution order of the function call subsystems through function call signals (3). Later in this example, you examine how changing the execution order can change the simulation results.
% This version of the model contains new Signal Conversion blocks (4) at the outputs of the PI controllers. With these additional blocks in place, the code generator can generate a single reentrant function for the PI controllers.
%% Control Function Location and File Placement in the Generated Code
% In Generate C Code from a Control Algorithm for an Embedded System and Configure Data Interface in the Generated Code, the code generator creates a single model_step function that contains the control algorithm code. However, many applications require a greater level of control over the file placement of functions. By modifying the parameters of atomic subsystems, you can specify multiple functions within a single model.
% The figure shows the subsystem parameters for PI_ctrl_1.
%
% Treat as atomic unit
% Enables other submenus. For atomic subsystems, this parameter is automatically selected and disabled.
% Sample time
% Specifies a sample time for execution. Not available for function-call subsystems.
% Function packaging options
% Auto -- Determines how the subsystem appears in the generated code. This value is the default.
% Inline -- Places the subsystem code inline with the rest of the model code.
% Function -- Generates the code for the subsystem as a function.
% Reusable function -- Generates a reusable (reentrant) function from the subsystem. The function passes all input and output data through formal parameters. The function does not directly access global variables.
% Function name options
% Selecting Function or Reusable function for Function packaging enables function name options.
% Auto -- Determines the function.
% Use subsystem name -- Bases the function on the subsystem name.
% User specified -- Applies the specified file name.
% File name options
% Selecting Function or Reusable function for Function packaging enables file name options.
% Auto -- Places the function definition in the module generated for the parent system, or, if the model root is the parent, in model.c.
% Use subsystem name -- Generates a separate file. The name of the file is the name of the subsystem or library block.
% Use function name -- Generates a separate file. The name of the file is the name that you specify with Function name options.
% User specified -- Applies the specified, unique file name.
% Function with separate data
% Enabled when you set Function packaging to Function. When selected, the code generator separates the internal data of the subsystem (for example, signals) from the data of the parent model. The subsystem owns this separate data.
%% Generate Reentrant Code
% Embedded Coder® supports reentrant code. Reentrant code is a reusable programming routine that multiple programs can use simultaneously. Reentrant code is used in operating systems and other system software that uses multithreading to handle concurrent events. Reentrant code does not maintain state data, so there are no persistent variables in the function. Calling programs maintain state variables and must pass the state data into the function. Multiple users or processes can share one copy of a reentrant function.
% To generate reentrant code, you must first specify the subsystem as reusable by configuring the subsystem parameter Function packaging.
%
% In some cases, the configuration of the model prevents reusable code. The table lists common issues.
% Cause                                     Solution
% Subsystem output feeds global signal      Add a Signal Conversion block between the
% data                                      subsystem and the global signal.
% Generated function receives data          Select Configuration Parameters >
% (formal parameters) through pointers      Model Referencing > Pass fixed-size scalar root
%                                           inputs by value for code generation.
% Subsystem uses global signal data         Use a port to pass the global data in and out
% in internal algorithm                     of the subsystem.
%% Use a Mask to Pass Parameter Values into Library Subsystem
% To define algorithmic parameter data (such as a gain or coefficient) outside the scope of a reusable library block or subsystem, you can apply a mask to the block or subsystem and create a mask parameter. You can then specify a different parameter value for each instance of the block or subsystem. Each mask parameter appears in the generated code as a formal parameter of the reentrant function.
% In this version of the model, the subsystems PI_ctrl_1 and PI_ctrl_2 are masked. In each mask, the values of the P and I gains are set by data objects such as I_Gain_2 and P_Gain_2.
%
%% Generate Code for Atomic Subsystem
% In Generate C Code from a Control Algorithm for an Embedded System and Configure Data Interface in the Generated Code, you generate code at the root level of the model. Alternatively, you can build a specific subsystem.
%
% To initiate a subsystem build, use the context menu. You can choose from these options:
% Build This Subsystem: Treats the subsystem as a separate mode and creates the full set of source C files and header files. This option does not support function-call subsystems.
% Generate S-Function: Generates C code for the subsystem and creates an S-Function wrapper. You can then simulate the code in the original model. This option does not support function-call subsystems.
% Export Functions: Generates C code without the scheduling code that comes with the Build This Subsystem option. Use this option to build subsystems that use triggers, such as function-call subsystems.
% Alternatively, open the Embedded Coder app, select the subsystem and on the C Code tab, click Build.
%% Examine Generated Code
% This example compares the files that are generated for the full system build with the files that are generated for exported functions. You also examine how the masked data appears in the code.
% Run the build script for the three options. Then, examine the generated files by clicking the hyperlinks.
% Generate code from the entire model.
% Export the function PI_ctrl_1.
% Export the function Pos_Command_Arbitration.
% rtwdemo_PCG_Eval_P3.c
% Full Build: Yes, Step function
% PI_ctrl_1: No
% Pos_Command_Arbitration: No
% PI_ctrl_1.c
% Full Build: No
% PI_ctrl_1: Yes, Trigger function
% Pos_Command_Arbitration: No
% Pos_Command_Arbitration.c
% Full Build: No
% PI_ctrl_1: No
% Pos_Command_Arbitration: Yes, Init and Function
% PI_Ctrl_Reusable.c
% Full Build: Yes
% PI_ctrl_1: Yes
% Pos_Command_Arbitration: No
% ert_main.c
% Full Build: Yes
% PI_ctrl_1: Yes
% Pos_Command_Arbitration: Yes
% eval_data.c
% Full Build: Yes(1)
% PI_ctrl_1: Yes(1)
% Pos_Command_Arbitration: No, Eval data not used in diagram
% (1) eval_data.c has different content in the full and export function builds. The full build includes all of the parameters that the model uses. The export function contains only the variables that the subsystem uses.
% Masked Data in the Generated Code
% In the file rtwdemo_PCG_Eval_P3.c, the call sites of the reentrant function use the data objects P_Gain, I_Gain, P_Gain_2, and I_Gain_2 as arguments.
%
%% Effect of Execution Order on Simulation Results
% By default, Simulink® executes the subsystems in this order:
% PI_ctrl_1
% PI_ctrl_2
% Pos_Command_Arbitration
% For this example, you can specify one of two alternative orders of execution. You can then use the test harness to observe the effect of the execution order on the simulation results. The subsystem Execution_Order_Control has two configurations that control the execution order. To choose a configuration, use the subsystem context menu.
% Change the execution order and observe the results.
% Set the execution order to PI_ctrl_1,  PI_ctrl_2, Pos_Command_Arbitration.
% Open the test harness.
% Run the test harness.
% Change the execution order to Pos_Command_Arbitration, PI_ctrl_1, PI_ctrl_2.
% Run the test harness.
% The simulation results (throttle position over time) vary slightly depending on the order of execution. You can see the difference most clearly when the throttle request changes.
%
% For the next example in this series, see Call External C Code from Model and Generated Code.
% Copyright 2007-2019 The MathWorks, Inc.