| Products & Services | Industries | Academia | Support | User Community | Company |
| Download Product Updates | | | Get Pricing | | | Trial Software |
| Documentation → Simulink |
| Contents | Index |
| Learn more about Simulink |
| On this page… |
|---|
This section examines how the Simulink engine interacts with S-functions from two perspectives:
Process perspective, i.e., at which points in a simulation the engine invokes the S-function.
Data perspective, i.e., how the engine and the S-function exchange information during a simulation.
The following figures show the order in which the Simulink engine invokes the callback methods in an S-function. Solid rectangles indicate callbacks that always occur during model initialization or at every time step. Dotted rectangles indicate callbacks that may occur during initialization and/or at some or all time steps during the simulation loop. See the documentation for each callback method in S-Function Callback Methods — Alphabetical List to determine the exact circumstances under which the engine invokes the callback.
Note The process view diagram represents the execution of S-functions that contain continuous and discrete states, enable zero-crossing detection, and reside in a model that uses a variable-step solver. Different solvers omit certain steps in the diagram. For a better understanding of how the Simulink engine executes your particular S-function, run the model containing the S-function using the Simulink debugger. See Simulink Debugger in Using Simulink for more information. |
In the following model initialization loop, the Simulink engine configures the S-function for an upcoming simulation. The engine always makes the required calls to mdlInitializeSizes and mdlInitializeSampleTime to set up the fundamental attributes of the S-function, including input and output ports, S-function dialog parameters, work vectors, sample times, etc.
The engine calls additional methods, as needed, to complete the S-function initialization. For example, if the S-function uses work vectors, the engine calls mdlSetWorkWidths. Also, if the mdlInitializeSizes method deferred setting up input and output port attributes, the engine calls any methods necessary to complete the port initialization, such as mdlSetInputPortWidth, during signal propagation. The mdlStart method calls the mdlCheckParameters and mdlProcessParameters methods if the S-function uses dialog parameters.

Note The mdlInitializeSizes callback method also runs when you enter the name of a compiled S-function into the S-Function Block Parameters dialog box. |
After initialization, the Simulink engine executes the following simulation loop. If the simulation loop is interrupted, either manually or when an error occurs, the engine jumps directly to the mdlTerminate method. If the simulation was manually halted, the engine first completes the current time step before invoking mdlTerminate.

If your model contains multiple S-Function blocks, the engine invokes a particular methods for every S-function before proceeding to the next method. For example, the engine calls all the mdlInitializeSizes methods before calling any mdlInitializeSampleTimes methods. The engine uses the block sorted order to determine the order to execute the S-functions. See What Is Sorted Order? in Using Simulink to learn more about how the engine determines the block sorted order.
If you use the Real-Time Workshop product to generate code for a model containing S-functions, the Simulink engine does not execute the entire calling sequence outlined above. Initialization proceeds as outlined above until the engine reaches the mdlStart method. The engine then calls the S-function methods show in the following figure, where the mdlRTW method is unique to the Real-Time Workshop product.

If the S-function resides in a conditionally executed subsystems, it is possible for the generated code to interleave calls to mdlInitializeConditions and mdlStart. Consider the following Simulink model sfcndemo_enablesub.mdl.

The model contains two nonvirtual subsystems, the conditionally executed enabled subsystem named Reset and the atomic subsystem named Atomic. Each subsystem contains an S-Function block that calls the S-function dsfunc.c, which models a discrete state-space system with two states. The enabled subsystem Reset resets the state values when the subsystem is enabled, and the output values when the subsystem is disabled.
Using the generic real-time (GRT) target, the generated code for the model-wide Start function calls the Start functions of the two subsystems before calling the model-wide MdlInitialize function, as shown in the following code:
void MdlStart(void)
{
/* snip */
/* Start for enabled SubSystem: '<Root>/Reset' */
sfcndemo_enablesub_Reset_Start();
/* end of Start for SubSystem: '<Root>/Reset' */
/* Start for atomic SubSystem: '<Root>/Atomic' */
sfcndemo_enablesub_Atomic_Start();
/* end of Start for SubSystem: '<Root>/Atomic' */
MdlInitialize();The Start function for the enabled subsystem calls the subsystem's InitializeConditions function:
void sfcndemo_enablesub_Reset_Start(void)
{
sfcndemo_enablesub_Reset_Init();
/* snip */
}The MdlInitialize function, called in MdlStart, contains a call to the InitializeConditions function for the atomic subsystem:
void MdlInitialize(void)
{
/* InitializeConditions for atomic SubSystem:
'<Root>/Atomic' */
sfcndemo_enablesub_Atomic_Init();
}Therefore, the model-wide Start function interleaves calls to the Start and InitializeConditions functions for the two subsystems and the S-functions they contain.
For more information about the Real-Time Workshop product and how it interacts with S-functions, see Integrating External Code With Generated C and C++ Code in the Real-Time Workshop User's Guide and the Real-Time Workshop Target Language Compiler documentation.
When you are running a Simulink model in external mode, the calling sequence for S-function routines changes as shown in the following figure.

The engine calls mdlRTW once when it enters external mode and again each time a parameter changes or when you select Update Diagram under your model's Edit menu.
Note Running a Simulink model in external mode requires the Real-Time Workshop product. For more information about external mode, see the Real-Time Workshop documentation. |
S-function blocks have input and output signals, parameters, and internal states, plus other general work areas. In general, block inputs and outputs are written to, and read from, a block I/O vector. Inputs can also come from
External inputs via the root Inport blocks
Ground if the input signal is unconnected or grounded
Block outputs can also go to the external outputs via the root Outport blocks. In addition to input and output signals, S-functions can have
Continuous states
Discrete states
Other working areas such as real, integer, or pointer work vectors
You can parameterize S-function blocks by passing parameters to them using the S-Function Block Parameters dialog box.
The following figure shows the general mapping between these various types of data.

An S-function's mdlInitializeSizes routine sets the sizes of the various signals and vectors. S-function methods called during the simulation loop can determine the sizes and values of the signals.
An S-function method can access input signals in two ways:
Via pointers
Using contiguous inputs
During the simulation loop, access the input signals using
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,portIndex)
This returns an array of pointers for the input port with index portIndex, where portIndex starts at 0. There is one array of pointers for each input port. To access an element of this array you must use
*uPtrs[element]
The following figure describes how to access the input signals of an S-function with two inputs.

As shown in the previous figure, the input array pointers can point at noncontiguous places in memory.
You can retrieve the output signal by using this code.
real_T *y = ssGetOutputPortSignal(S,outputPortIndex);
An S-function's mdlInitializeSizes method can specify that the elements of its input signals must occupy contiguous areas of memory, using ssSetInputPortRequiredContiguous. If the inputs are contiguous, other methods can use ssGetInputPortSignal to access the inputs.
This section describes how to access all input signals of a particular port and write them to the output port. The preceding figure shows that the input array of pointers can point to noncontiguous entries in the block I/O vector. The output signals of a particular port form a contiguous vector. Therefore, the correct way to access input elements and write them to the output elements (assuming the input and output ports have equal widths) is to use this code.
int_T element;
int_T portWidth = ssGetInputPortWidth(S,inputPortIndex);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,inputPortIndex);
real_T *y = ssGetOutputPortSignal(S,outputPortIdx);
for (element=0; element<portWidth; element++) {
y[element] = *uPtrs[element];
}
A common mistake is to try to access the input signals via pointer arithmetic. For example, if you were to place
real_T *u = *uPtrs; /* Incorrect */
just below the initialization of uPtrs and replace the inner part of the above loop with
*y++ = *u++; /* Incorrect */
the code compiles, but the MEX-file might crash the Simulink software. This is because it is possible to access invalid memory (which depends on how you build your model). When accessing the input signals incorrectly, a crash occurs when the signals entering your S-function block are not contiguous. Noncontiguous signal data occurs when signals pass through virtual connection blocks such as the Mux or Selector blocks.
To verify that your S-function correctly accesses wide input signals, pass a replicated signal to each input port of your S-function. To do this, create a Mux block with the number of input ports equal to the width of the desired signal entering your S-function. Then, connect the driving source to each S-function input port, as shown in the following figure. Finally, run your S-function using this input signal to verify that it does not crash and produces expected results.

![]() | Integrating Existing C Functions into Simulink Models with the Legacy Code Tool | Writing Callback Methods | ![]() |

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.
| © 1984-2009- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |