Products & Services Solutions Academia Support User Community Company

Learn more about Real-Time Workshop   

Laying Out the Model Architecture

Model Execution

Introduction

Before looking at the two styles of generated code, you need to have a high-level understanding of how the generated model code is executed. The Real-Time Workshop software generates algorithmic code as defined by your model. You can include your own code in your model by using S-functions. S-functions can range from high-level signal manipulation algorithms to low-level device drivers.

The Real-Time Workshop product also provides a run-time interface that executes the generated model code. The run-time interface and model code are compiled together to create the model executable. The next figure shows a high-level object-oriented view of the executable.

The Object-Oriented View of a Real-Time Program

In general, the conceptual design of the model execution driver does not change between the rapid prototyping and embedded style of generated code. The following sections describe model execution for single-tasking and multitasking environments both for simulation (non-real-time) and for real time. For most models, the multitasking environment will provide the most efficient model execution (that is, fastest sample rate).

The following concepts are useful in describing how models execute. Function names used in ERT and GRT targets are shown, followed by the comparable GRT-compatible calls in parentheses.

The identifying names in the preceding list (ModelOutputs, and so on) identify functions in pseudocode examples shown in the following sections.

For a complete set of correspondences between GRT and ERT function identifiers, see the table Identifiers for Real-Time Model Data Structure Variants.

Models for Non-Real-Time Single-Tasking Systems

The pseudocode below shows the execution of a model for a non-real-time single-tasking system.

main()
{
  Initialization
  While (time < final time)
    ModelOutputs     -- Major time step.
    LogTXY           -- Log time, states and root outports.
    ModelUpdate      -- Major time step.
    Integrate        -- Integration in minor time step for 
                     -- models with continuous states.
      ModelDerivatives
      Do 0 or more
        ModelOutputs
        ModelDerivatives
      EndDo -- Number of iterations depends upon the solver
      Integrate derivatives to update continuous states.
    EndIntegrate
  EndWhile
  Termination
}

The initialization phase begins first. This consists of initializing model states and setting up the execution engine. The model then executes, one step at a time. First ModelOutputs executes at time t, then the workspace I/O data is logged, and then ModelUpdate updates the discrete states. Next, if your model has any continuous states, ModelDerivatives integrates the continuous states' derivatives to generate the states for time , where h is the step size. Time then moves forward to and the process repeats.

During the ModelOutputs and ModelUpdate phases of model execution, only blocks that reach the current point in time execute.

Models for Non-Real-Time Multitasking Systems

The pseudocode below shows the execution of a model for a non-real-time multitasking system.

main()
{
  Initialization
  While (time < final time)
    ModelOutputs(tid=0)   -- Major time step.
    LogTXY                -- Log time, states, and root 
                          -- outports.
    ModelUpdate(tid=0)    -- Major time step.
    Integrate       -- Integration in minor time step for 
                    -- models with continuous states.
      ModelDerivatives
      Do 0 or more
        ModelOutputs(tid=0)
        ModelDerivatives
      EndDo (Number of iterations depends upon the solver.)
      Integrate derivatives to update continuous states.
    EndIntegrate
    For i=1:NumTids
      ModelOutputs(tid=i) -- Major time step.
      ModelUpdate(tid=i)  -- Major time step.
    EndFor
  EndWhile
  Termination
  }

Multitasking operation is more complex than single-tasking execution because the output and update functions are subdivided by the task identifier (tid) that is passed into these functions. This allows for multiple invocations of these functions with different task identifiers using overlapped interrupts, or for multiple tasks when using a real-time operating system. In simulation, multiple tasks are emulated by executing the code in the order that would occur if there were no preemption in a real-time system.

Multitasking execution assumes that all tasks are multiples of the base rate. The Simulink product enforces this when you create a fixed-step multitasking model. The multitasking execution loop is very similar to that of single-tasking, except for the use of the task identifier (tid) argument to ModelOutputs and ModelUpdate.

Models for Real-Time Single-Tasking Systems

The pseudocode below shows the execution of a model in a real-time single-tasking system where the model is run at interrupt level.

rtOneStep()
{
  Check for interrupt overflow
  Enable "rtOneStep" interrupt
  ModelOutputs    -- Major time step.
  LogTXY          -- Log time, states and root outports.
  ModelUpdate     -- Major time step.
  Integrate       -- Integration in minor time step for models 
                  -- with continuous states.
     ModelDerivatives
     Do 0 or more 
       ModelOutputs
       ModelDerivatives
     EndDo (Number of iterations depends upon the solver.)
     Integrate derivatives to update continuous states.
  EndIntegrate
}

main()
{
  Initialization (including installation of rtOneStep as an 
  interrupt service routine, ISR, for a real-time clock).
  While(time < final time)
    Background task.
  EndWhile
  Mask interrupts (Disable rtOneStep from executing.)
  Complete any background tasks.
  Shutdown
}

Real-time single-tasking execution is very similar to non-real-time single-tasking execution, except that instead of free-running the code, the rt_OneStep function is driven by a periodic timer interrupt.

At the interval specified by the program's base sample rate, the interrupt service routine (ISR) preempts the background task to execute the model code. The base sample rate is the fastest in the model. If the model has continuous blocks, then the integration step size determines the base sample rate.

For example, if the model code is a controller operating at 100 Hz, then every 0.01 seconds the background task is interrupted. During this interrupt, the controller reads its inputs from the analog-to-digital converter (ADC), calculates its outputs, writes these outputs to the digital-to-analog converter (DAC), and updates its states. Program control then returns to the background task. All these steps must occur before the next interrupt.

Models for Real-Time Multitasking Systems

The following pseudocode shows how a model executes in a real-time multitasking system where the model is run at interrupt level.

rtOneStep()
{
  Check for interrupt overflow
  Enable "rtOneStep" interrupt
  ModelOutputs(tid=0)     -- Major time step.
  LogTXY                  -- Log time, states and root outports.
  ModelUpdate(tid=0)      -- Major time step.
  Integrate               -- Integration in minor time step for 
                          -- models with continuous states.
     ModelDerivatives
     Do 0 or more
       ModelOutputs(tid=0)
       ModelDerivatives
     EndDo (Number of iterations depends upon the solver.)
     Integrate derivatives and update continuous states.
  EndIntegrate
  For i=1:NumTasks
    If (hit in task i)
      ModelOutputs(tid=i)
      ModelUpdate(tid=i)
    EndIf
  EndFor
}

main()
{
  Initialization (including installation of rtOneStep as an 
    interrupt service routine, ISR, for a real-time clock).
  While(time < final time)
    Background task.
  EndWhile
  Mask interrupts (Disable rtOneStep from executing.) 
  Complete any background tasks.
  Shutdown
}

Running models at interrupt level in a real-time multitasking environment is very similar to the previous single-tasking environment, except that overlapped interrupts are employed for concurrent execution of the tasks.

The execution of a model in a single-tasking or multitasking environment when using real-time operating system tasking primitives is very similar to the interrupt-level examples discussed above. The pseudocode below is for a single-tasking model using real-time tasking primitives.

tSingleRate()
{
  MainLoop:
    If clockSem already "given", then error out due to overflow.
    Wait on clockSem
    ModelOutputs            -- Major time step.
    LogTXY                  -- Log time, states and root 
                            -- outports
    ModelUpdate             -- Major time step
    Integrate               -- Integration in minor time step 
                            -- for models with continuous 
                            -- states.
      ModelDeriviatives
      Do 0 or more
        ModelOutputs
        ModelDerivatives
      EndDo (Number of iterations depends upon the solver.)
      Integrate derivatives to update continuous states.
    EndIntegrate
  EndMainLoop
}

main()
{
  Initialization
  Start/spawn task "tSingleRate".
  Start clock that does a "semGive" on a clockSem semaphore.
  Wait on "model-running" semaphore.
  Shutdown
}

In this single-tasking environment, the model executes as real-time operating system tasking primitives. In this environment, create a single task (tSingleRate) to run the model code. This task is invoked when a clock tick occurs. The clock tick gives a clockSem (clock semaphore) to the model task (tSingleRate). The model task waits for the semaphore before executing. The clock ticks occur at the fundamental step size (base rate) for your model.

Models for Multitasking Systems that Use Real-Time Tasking Primitives

The pseudocode below is for a multitasking model using real-time tasking primitives.

tSubRate(subTaskSem,i)
{
  Loop:
    Wait on semaphore subTaskSem.
    ModelOutputs(tid=i)
    ModelUpdate(tid=i)
  EndLoop
}
tBaseRate()
{
  MainLoop:
    If clockSem already "given", then error out due to overflow.
    Wait on clockSem
    For i=1:NumTasks
      If (hit in task i)
        If task i is currently executing, then error out due to 
          overflow.
        Do a "semGive" on subTaskSem for task i.
      EndIf
    EndFor
    ModelOutputs(tid=0)    -- major time step.
    LogTXY                 -- Log time, states and root outports.
    ModelUpdate(tid=0)     -- major time step.
    Loop:                  -- Integration in minor time step for 
                           -- models with continuous states.
      ModelDeriviatives
      Do 0 or more
        ModelOutputs(tid=0)
        ModelDerivatives
      EndDo (number of iterations depends upon the solver).
      Integrate derivatives to update continuous states.
    EndLoop
  EndMainLoop
}
main()
{
  Initialization
  Start/spawn task "tSubRate".
  Start/spawn task "tBaseRate".

  Start clock that does a "semGive" on a clockSem semaphore.
  Wait on "model-running" semaphore.
  Shutdown
}

In this multitasking environment, the model is executed using real-time operating system tasking primitives. Such environments require several model tasks (tBaseRate and several tSubRate tasks) to run the model code. The base rate task (tBaseRate) has a higher priority than the subrate tasks. The subrate task for tid=1 has a higher priority than the subrate task for tid=2, and so on. The base rate task is invoked when a clock tick occurs. The clock tick gives a clockSem to tBaseRate. The first thing tBaseRate does is give semaphores to the subtasks that have a hit at the current point in time. Because the base rate task has a higher priority, it continues to execute. Next it executes the fastest task (tid=0), consisting of blocks in your model that have the fastest sample time. After this execution, it resumes waiting for the clock semaphore. The clock ticks are configured to occur at the fundamental step size for your model.

Program Timing

Real-time programs require careful timing of the task invocations (either by using an interrupt or a real-time operating system tasking primitive) to ensure that the model code executes to completion before another task invocation occurs. This includes time to read and write data to and from external hardware.

The next figure illustrates interrupt timing.

Task Timing

The sample interval must be long enough to allow model code execution between task invocations.

In the figure above, the time between two adjacent vertical arrows is the sample interval. The empty boxes in the upper diagram show an example of a program that can complete one step within the interval and still allow time for the background task. The gray box in the lower diagram indicates what happens if the sample interval is too short. Another task invocation occurs before the task is complete. Such timing results in an execution error.

Note also that, if the real-time program is designed to run forever (that is, the final time is 0 or infinite so the while loop never exits), then the shutdown code never executes.

For more information on how the timing engine works, see Using Timers.

Program Execution

As the previous section indicates, a real-time program cannot require 100% of the CPU's time. This provides an opportunity to run background tasks during the free time.

Background tasks include operations such as writing data to a buffer or file, allowing access to program data by third-party data monitoring tools, or using Simulink external mode to update program parameters.

It is important, however, that the program be able to preempt the background task at the appropriate time to ensure real-time execution of the model code.

The way the program manages tasks depends on capabilities of the environment in which it operates.

External Mode Communication

External mode allows communication between the Simulink block diagram and the standalone program that is built from the generated code. In this mode, the real-time program functions as an interprocess communication server, responding to requests from the Simulink engine.

Data Logging in Single-Tasking and Multitasking Model Execution

The Real-Time Workshop data-logging features, described in Enabling Instrumentation for Debugging, enable you to save system states, outputs, and time to a MAT-file at the completion of the model execution. The LogTXY function, which performs data logging, operates differently in single-tasking and multitasking environments.

If you examine how LogTXY is called in the single-tasking and multitasking environments, you will notice that for single-tasking LogTXY is called after ModelOutputs. During this ModelOutputs call, all blocks that have a hit at time t execute, whereas in multitasking, LogTXY is called after ModelOutputs(tid=0), which executes only the blocks that have a hit at time t and that have a task identifier of 0. This results in differences in the logged values between single-tasking and multitasking logging. Specifically, consider a model with two sample times, the faster sample time having a period of 1.0 second and the slower sample time having a period of 10.0 seconds. At time t = k*10, k=0,1,2... both the fast (tid=0) and slow (tid=1) blocks execute. When executing in multitasking mode, when LogTXY is called, the slow blocks execute, but the previous value is logged, whereas in single-tasking the current value is logged.

Another difference occurs when logging data in an enabled subsystem. Consider an enabled subsystem that has a slow signal driving the enable port and fast blocks within the enabled subsystem. In this case, the evaluation of the enable signal occurs in a slow task, and the fast blocks see a delay of one sample period; thus the logged values will show these differences.

To summarize differences in logged data between single-tasking and multitasking, differences will be seen when

For the first two cases, even though the logged values are different between single-tasking and multitasking, the model results are not different. The only real difference is where (at what point in time) the logging is done. The third (enabled subsystem) case results in a delay that can be seen in a real-time environment.

Rapid Prototyping and Embedded Model Execution Differences

The rapid prototyping program framework provides a common application programming interface (API) that does not change between model definitions.

The Real-Time Workshop Embedded Coder product provides a different framework called the embedded program framework. The embedded program framework provides an optimized API that is tailored to your model. When you use the embedded style of generated code, you are modeling how you would like your code to execute in your embedded system. Therefore, the definitions defined in your model should be specific to your embedded targets. Items such as the model name, parameter, and signal storage class are included as part of the API for the embedded style of code.

One major difference between the rapid prototyping and embedded style of generated code is that the latter contains fewer entry-point functions. The embedded style of code can be configured to have only one run-time function, model_step.

Thus, when you look again at the model execution pseudocode presented earlier in this chapter, you can eliminate the Loop...EndLoop statements, and group ModelOutputs, LogTXY, and ModelUpdate into a single statement, model_step.

For a detailed discussion of how generated embedded code executes, see the Real-Time Workshop Embedded Coder documentation.

Rapid Prototyping Model Functions

The rapid prototyping code defines the following functions that interface with the run-time interface:

The contents of the above functions are directly related to the blocks in your model. A Simulink block can be generalized to the following set of equations.

Output y is a function of continuous state xc, discrete state xd, and input u. Each block writes its specific equation in the appropriate section of MdlOutput.

The discrete states xd are a function of the current state and input. Each block that has a discrete state updates its state in MdlUpdate.

The derivatives x are a function of the current input. Each block that has continuous states provides its derivatives to the solver (for example, ode5) in model_Derivatives. The derivatives are used by the solver to integrate the continuous state to produce the next value.

The output, y, is generally written to the block I/O structure. Root-level Outport blocks write to the external outputs structure. The continuous and discrete states are stored in the states structure. The input, u, can originate from another block's output, which is located in the block I/O structure, an external input (located in the external inputs structure), or a state. These structures are defined in the model.h file that the Real-Time Workshop software generates.

The next example shows the general contents of the rapid prototyping style of C code written to the model.c file.

The next figure shows a flow chart describing the execution of the rapid prototyping generated code.

Rapid Prototyping Execution Flow Chart

Each block places code in specific Mdl routines according to the algorithm that it is implementing. Blocks have input, output, parameters, and states, as well as other general items. For example, in general, block inputs and outputs are written to a block I/O structure (model_B). Block inputs can also come from the external input structure (model_U) or the state structure when connected to a state port of an integrator (model_X), or ground (rtGround) if unconnected or grounded. Block outputs can also go to the external output structure (model_Y). The next figure shows the general mapping between these items.

Data View of the Generated Code

The following list defines the structures shown in the preceding figure:

Embedded Model Functions

The Real-Time Workshop Embedded Coder target generates the following functions:

See Model Entry Points in the Real-Time Workshop Embedded Coder documentation for complete descriptions of these functions.

Rapid Prototyping Program Framework

Introduction

The code modules generated from a Simulink model—model.c (or .cpp), model.h, and other files — implement the model's system equations, contain block parameters, and perform initialization.

The Real-Time Workshop program framework provides the additional source code necessary to build the model code into a complete, standalone program. The program framework consists of application modules (files containing source code to implement required functions) designed for a number of different programming environments.

The automatic program builder ensures that the program is created with the proper modules once you have configured your template makefile. The application modules and the code generated for a Simulink model are implemented using a common API. This API defines a data structure (called a real-time model, sometimes abbreviated as rtM) that encapsulates all data for your model.

This API is similar to that of S-functions, with one major exception: the API assumes that there is only one instance of the model, whereas S-functions can have multiple instances. The function prototypes also differ from S-functions.

Rapid Prototyping Program Architecture

The structure of a real-time program consists of three components. Each component has a dependency on a different part of the environment in which the program executes. The next figure shows this structure.

The Real-Time Workshop architecture consists of three parts, the first two of which include system-dependent components and system-independent components. Together these two parts form the run-time interface.

This architecture adapts readily to a wide variety of environments by isolating the dependencies of each program component. The following sections discuss each component in more detail and include descriptions of the application modules that implement the functions carried out by the system-dependent components, system-independent components, and application components.

Rapid Prototyping System-Dependent Components

These components contain the program's main function, which controls program timing, creates tasks, installs interrupt handlers, enables data logging, and performs error checking.

The way in which application modules implement these operations depends on the type of computer. This means that, for example, the components used for a PC-based program perform the same operations, but differ in method of implementation from components designed to run on a VME target.

The main Function.   The main function in a C/C++ program is the point where execution begins. In Real-Time Workshop application programs, the main function must perform certain operations. These operations can be grouped into three categories: initialization, model execution, and program termination.

Initialization.  

Model Execution.  

Program Termination.  

Rapid Prototyping Application Modules for System-Dependent Components.   The application modules contained in the system-dependent components generally include a main module such as rt_main.c, containing the main entry point for C. There can also be additional application modules for such things as I/O support and timer handling.

Rapid Prototyping System-Independent Components

These components are collectively called system independent because all environments use the same application modules to implement these operations. This section steps through the model code (and if the model has continuous states, calls one of the numerical integration routines). This section also includes the code that defines, creates, and destroys the real-time model data structure (rtM). The model code and all S-functions included in the program define their own SimStructs.

The model code execution driver calls the functions in the model code to compute the model outputs, update the discrete states, integrate the continuous states (if applicable), and update time. These functions then write their calculated data to the real-time model.

Model Execution.   At each sample interval, the main program passes control to the model execution function, which executes one step though the model. This step reads inputs from the external hardware, calculates the model outputs, writes outputs to the external hardware, and then updates the states.

The next figure shows these steps.

Executing the Model

This scheme writes the system outputs to the hardware before the states are updated. Separating the state update from the output calculation minimizes the time between the input and output operations.

Integration of Continuous States.   The real-time program calculates the next values for the continuous states based on the derivative vector, dx/dt, for the current values of the inputs and the state vector.

These derivatives are then used to calculate the next values of the states using a state-update equation. This is the state-update equation for the first-order Euler method (ode1)

where h is the step size of the simulation, x represents the state vector, and dx/dt is the vector of derivatives. Other algorithms can make several calls to the output and derivative routines to produce more accurate estimates.

Note, however, that real-time programs use a fixed-step size because it is necessary to guarantee the completion of all tasks within a given amount of time. This means that, while you should use higher order integration methods for models with widely varying dynamics, the higher order methods require additional computation time. In turn, the additional computation time might force you to use a larger step size, which can diminish the improvement of accuracy initially sought from the higher order integration method.

Generally, the stiffer the equations, (that is, the more dynamics in the system with widely varying time constants), the higher the order of the method that you must use.

In practice, the simulation of very stiff equations is impractical for real-time purposes except at very low sample rates. You should test fixed-step size integration in the Simulink environment to check stability and accuracy before implementing the model for use in real-time programs.

For linear systems, it is more practical to convert the model that you are simulating to a discrete time version, for instance, using the c2d function in the Control System Toolbox™ product.

Application Modules for System-Independent Components.   The system-independent components include these modules:

The system-independent components also include code that defines, creates, and destroys the real-time model data structure. All S-functions included in the program define their own SimStructs.

The SimStruct data structure encapsulates all the data relating to an S-function, including block parameters and outputs. See The SimStruct in the Writing S-Functions documentation for more information about SimStruct.

Rapid Prototyping Application Components

The application components contain the generated code for the Simulink model, including the code for any S-functions in the model. This code is referred to as the model code because these functions implement the Simulink model.

However, the generated code contains more than just functions to execute the model (as described in the previous section). There are also functions to perform initialization, facilitate data access, and complete tasks before program termination. To perform these operations, the generated code must define functions that

The Real-Time Model Data Structure.   The real-time model data structure encapsulates model data and associated information necessary to fully describe the model. Its contents include

The required information is stored in fields in the real-time model structure, which is defined in model.h as

/* Real-time Model Data Structure */
struct _rtModel_model_Tag {
  const char *path;
  const char *modelName;
  struct SimStruct_tag * *childSfunctions;
  const char *errorStatus;
  SS_SimMode simMode;
  RTWLogInfo *rtwLogInfo;
  RTWExtModeInfo *extModeInfo;
  RTWSolverInfo solverInfo;
  RTWSolverInfo *solverInfoPtr;
  void *sfcnInfo;

  /*
   * ModelData:
   * The following substructure contains information regarding
   * the data used in the model.
   */
    .
    .
}

The (possibly mangled) name of the model replaces model in the above tag. The individual substructures have been omitted, as they can vary.

For GRT targets, model.h also includes aliases to map global identifiers to identifiers used in prior versions (rtB, rtP, rtY, and so on). The following table lists the structure identifiers used in the generated code for these variants of the real-time model data structure. The column GRT Symbol contains the old-style (pre-Version 6) GRT identifiers, which are still used by the GRT calling interface, but not within the generated code.

Identifiers for Real-Time Model Data Structure Variants

Identifier

GRT Symbol

Data

model_B

rtB

Block IO

model_U

rtU

External inputs

model_X

rtX

Continuous states

model_Xdot

rtXdot

State derivatives

model_Xdix

rtXdis

Continuous state disabled

model_Y

rtY

External outputs

model_P

rtP

Parameters

rts

rts

Child Simstruct

model_DWork

rtDWork

DWork

model_ConstB

rtC

Constant block IO define, structure

model_ConstP

rtcP

Constant parameter Structure

model_PrevZCSigState

rtPrevZCSigState

Previous zero-crossing signal states

model_NonsampledZC

rtNonsampledZC

Nonsampled zero-crossings

Real-Time Workshop Embedded Coder users can tailor identifiers, and can make them look like the GRT symbols listed above, should they desire such a coding style. The above GRT-ERT identifier equivalences (or at least as many of them as are required to build a given model) are established by using a set of #define macros in model.h, under the comment /* Backward compatible GRT Identifiers */.

The real-time model data structure is used for all targets. Prior to Version 5, the ERT target used the rtObject data structure, and other targets used the Simstruct data structure for encapsulating model data. Now all targets are treated the same, except for the fact that the real-time model data structure is pruned for ERT targets to save space in executables. Even when not pruned, the real-time model data structure is more space efficient than the root Simstruct used by earlier releases for non-ERT targets, as it only contains fields for child (S-function) Simstructs that are actually used in a model.

Rapid Prototyping Model Code Functions.   The functions defined by the model code are called at various stages of program execution (that is, initialization, model execution, or program termination).

The next figure shows the functions defined in the generated code and shows what part of the program executes each function.

The Model Registration Function.   The model registration function has the same name as the Simulink model from which it is generated. It is called directly by the main program during initialization. Its purpose is to initialize and return a pointer to the real-time model data structure.

Models Containing S-Functions.   A noninlined S-function is any C or C++ MEX S-function that is not implemented using a customized TLC file. If you create a C or C++ MEX S-function as part of a Simulink model, it is by default noninlined unless you write your own TLC file that inlines it within the body of the model.c or model.cpp code. The Real-Time Workshop code generator automatically incorporates your noninlined C or C++ S-functions into the program if they adhere to the S-function API described in the Simulink documentation.

This format defines functions and a SimStruct that are local to the S-function. This allows you to have multiple instances of the S-function in the model. The model's real-time model data structure contains a pointer to each S-function's SimStruct.

Code Generation and S-Functions.   If a model contains S-functions, the source code for the S-function must be on the search path the make utility uses to find other source files. The directories that are searched are specified in the template makefile that is used to build the program.

S-functions are implemented in a way that is directly analogous to the model code. They contain their own public registration functions (called by the top model code) that initialize static function pointers in their SimStructs. When the top model needs to execute the S-function, it does so by using the function pointers in the S-function's SimStruct. There can be more than one S-function with the same name in your model. This is accomplished by having function pointers to static functions.

Inlining S-Functions.   You can incorporate C/C++ MEX S-functions, along with the generated code, into the program executable. You can also write a target file for your C/C++ MEX S-function to inline the S-function, thus improving performance by eliminating function calls to the S-function itself. For more information on inlining S-functions, see the Target Language Compiler documentation.

Application Modules for Application Components.   When the Real-Time Workshop software generates code, it produces the following files:

These files are named for the Simulink model from which they are generated.

In addition, a dummy include file always named rtmodel.h is generated, which includes the above model-specific data structures and entry points. This enables the (static) target-specific main programs to reference files generated by the Real-Time Workshop code generator without needing to know the names of the models involved.

Another dummy file, rtwtypes.h, is generated, which simply includes simstruc_types.h (only for GRT and GRT malloc targets).

If you have created custom blocks using C/C++ MEX S-functions, you need the source code for these S-functions available during the build process.

Embedded Program Framework

The Real-Time Workshop Embedded Coder product provides a framework for embedded programs. Its architecture is outlined in the next figure.

Note the similarity between this architecture and the rapid prototyping architecture in the figure Rapid Prototyping Program Architecture. The main difference is the use of the rtModel data structure in place of the SimStruct data structure.

Using the previous figure, you can compare the embedded style of generated code, used in the Real-Time Workshop Embedded Coder product, with the rapid prototyping style of generated code of the previous section. Most of the rapid prototyping explanations in the previous section hold for the Real-Time Workshop Embedded Coder target. The Real-Time Workshop Embedded Coder target simplifies the process of using the generated code in your custom-embedded applications by providing a model-specific API and eliminating the SimStruct. This target contains the same conceptual layering as the rapid prototyping target, but each layer has been simplified.

For a discussion of the structure of embedded real-time code, see the Real-Time Workshop Embedded Coder documentation.

  


Related Products & Applications

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