| Products & Services | Solutions | Academia | Support | User Community | Company |
| Download Product Updates | | | Get Pricing | | | Trial Software |
| Documentation → Real-Time Workshop |
| Contents | Index |
| Learn more about Real-Time Workshop |
Certain blocks require the value of either absolute time (that is, the time from the start of program execution to the present time) or elapsed time (for example, the time elapsed between two trigger events). All targets that support the real-time model (rtModel) data structure provide efficient time computation services to blocks that request absolute or elapsed time. Absolute and elapsed timer features include
Timers are implemented as unsigned integers in generated code.
In multirate models, at most one timer is allocated per rate, on an as-needed basis. If no blocks executing at a given rate require a timer, no timer is allocated to that rate. This minimizes memory allocated for timers and significantly reduces overhead involved in maintaining timers.
Allocation of elapsed time counters for use of blocks within triggered subsystems is minimized, further reducing memory usage and overhead.
The Real-Time Workshop product provides S-function and TLC APIs that let your S-functions access timers, in both simulation and code generation.
For ERT and ERT-derived targets, the word size of the timers is determined by a user-specified maximum counter value. Correct specification of this value ensures that timers will not overflow. See the description of the parameter Controlling Memory Allocation for Time Counters. See also the Real-Time Workshop Embedded Coder documentation for information on restrictions on its use.
See Limitations on the Use of Absolute Time and Blocks that Depend on Absolute Time for more information about absolute time and the restrictions that it imposes.
This chapter discusses timing services provided for blocks executing within periodic tasks (that is, tasks running at the model's base rate or subrates).
The Real-Time Workshop product also provides timer support for blocks whose execution is asynchronous with respect to the periodic timing source of the model. See the following sections of the Asynchronous Support chapter:
If you create or maintain an S-Function block that requires absolute or elapsed time data, it must register the requirement (see APIs for Accessing Timers). In multirate models, timers are allocated on a per-rate basis. For example, consider a model structured as follows:
There are three rates, A, B, and C, in the model.
No blocks running at rate B require absolute or elapsed time.
Two blocks running at rate C register a requirement for absolute time.
One block running at rate A registers a requirement for absolute time.
In this case, two timers are generated, running at rates A and C respectively. The timing engine updates the timers as the tasks associated with rates A and C execute. Blocks executing at rates A and C obtain time data from the timers associated with rates A and C.
In the generated code, timers for absolute and elapsed time are implemented as unsigned integers. The default size is 64 bits. This is the amount of memory allocated for a timer if you specify a value of inf for the Application lifespan (days) parameter. For an application with a sample rate of 1000 MHz, a 64-bit counter will not overflow for more than 500 years. See Using Timers in Asynchronous Tasks and Controlling Memory Allocation for Time Counters for more information.
Some blocks, such as the Discrete-Time Integrator block, perform computations requiring the elapsed time (delta T) since the previous block execution. Blocks requiring elapsed time data must register the requirement (see APIs for Accessing Timers). A triggered subsystem then allocates and maintains a single elapsed time counter if required. This timer functions at the subsystem level, not at the individual block level. The timer is generated if the triggered subsystem (or any unconditionally executed subsystem within the triggered subsystem) contains one or more blocks requiring elapsed time data.
Note If you are using simplified initialization mode, elapsed time is always reset on first execution after becoming enabled, whether or not the subsystem is configured to reset on enable. For more information, see Underspecified initialization detection in the Simulink documentation. |
This section describes APIs that let your S-functions take advantage of the efficiencies offered by the absolute and elapsed timers. SimStruct macros are provided for use in simulation, and TLC functions are provided for inlined code generation. Note that
To generate and use the new timers as described above, your S-functions must register the need to use an absolute or elapsed timer by calling ssSetNeedAbsoluteTime or ssSetNeedElapseTime in mdlInitializeSampleTime.
Existing S-functions that read absolute time but do not register by using these macros will continue to operate correctly, but will generate old-style, less efficient code.
The SimStruct macros described in this section provide access to absolute and elapsed timers for S-functions during simulation.
In the functions below, the SimStruct *S argument is a pointer to the simstruct of the calling S-function.
void ssSetNeedAbsoluteTime(SimStruct *S, boolean b): if b is TRUE, registers that the calling S-function requires absolute time data, and allocates an absolute time counter for the rate at which the S-function executes (if such a counter has not already been allocated).
int ssGetNeedAbsoluteTime(SimStruct *S): returns 1 if the S-function has registered that it requires absolute time.
double ssGetTaskTime(SimStruct *S, tid): read absolute time for a given task with task identifier tid. ssGetTaskTime operates transparently, regardless of whether or not you use the new timer features. ssGetTaskTime is documented in the SimStruct Functions chapter of the Simulink Writing S-Functions documentation.
void ssSetNeedElapseTime(SimStruct *S, boolean b): if b is TRUE, registers that the calling S-function requires elapsed time data, and allocates an elapsed time counter for the triggered subsystem in which the S-function executes (if such a counter has not already been allocated). See also Elapsed Time Counters in Triggered Subsystems.
int ssGetNeedElapseTime(SimStruct *S): returns 1 if the S-function has registered that it requires elapsed time.
void ssGetElapseTime(SimStruct *S, (double *)elapseTime): returns, to the location pointed to by elapseTime, the value (as a double) of the elapsed time counter associated with the S-function.
void ssGetElapseTimeCounterDtype(SimStruct *S, (int *)dtype): returns the data type of the elapsed time counter associated with the S-function to the location pointed to by dtype. This function is intended for use with the ssGetElapseTimeCounter function (see below).
void ssGetElapseResolution(SimStruct *S, (double *)resolution): returns the resolution (that is, the sample time) of the elapsed time counter associated with the S-function to the location pointed to by resolution. This function is intended for use with the ssGetElapseTimeCounter function (see below).
void ssGetElapseTimeCounter(SimStruct *S, (void *)elapseTime): This function is provided for the use of blocks that require the elapsed time values for fixed-point computations. ssGetElapseTimeCounter returns, to the location pointed to by elapseTime, the integer value of the elapsed time counter associated with the S-function. If the counter size is 64 bits, the value is returned as an array of two 32-bit words, with the low-order word stored at the lower address.
To determine how to access the returned counter value, obtain the data type of the counter by calling ssGetElapseTimeCounterDtype, as in the following code:
int *y_dtype;
ssGetElapseTimeCounterDtype(S, y_dtype);
switch(*y_dtype) {
case SS_DOUBLE_UINT32:
{
uint32_T dataPtr[2];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_UINT32:
{
uint32_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_UINT16:
{
uint16_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_UINT8:
{
uint8_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
case SS_DOUBLE:
{
real_T dataPtr[1];
ssGetElapseTimeCounter(S, dataPtr);
}
break;
default:
ssSetErrorStatus(S, "Invalid data type for elaspe time
counter");
break;
}
If you want to use the actual elapsed time, issue a call to the ssGetElapseTime function to access the elapsed time directly. You do not need to get the counter value and then calculate the elapsed time.
double *y_elapseTime; . . . ssGetElapseTime(S, elapseTime)
The following TLC functions support elapsed time counters in generated code when you inline S-functions by writing TLC scripts for them.
LibGetTaskTimeFromTID(block): Generates code to read the absolute time for the task in which block executes.
LibGetTaskTimeFromTID is documented with other sample time functions in the TLC Function Library Reference pages of the Target Language Compiler documentation.
LibGetElapseTime(system): Generates code to read the elapsed time counter for system. (system is the parent system of the calling block.) See Elapsed Timer Code Generation Example for an example of code generated by this function.
LibGetElapseTimeCounter(system): Generates code to read the integer value of the elapsed time counter for system. (system is the parent system of the calling block.) This function should be used in conjunction with LibGetElapseTimeCounterDtypeId and LibGetElapseTimeResolution. (See the discussion of ssGetElapseTimeCounter above.)
LibGetElapseTimeCounterDtypeId(system): Generates code that returns the data type of the elapsed time counter for system. (system is the parent system of the calling block.)
LibGetElapseTimeResolution(system): Generates code that returns the resolution of the elapsed time counter for system. (system is the parent system of the calling block.)
This section shows a simple model illustrating how an elapsed time counter is generated and used by a Discrete-Time Integrator block within a triggered subsystem. The following block diagrams show the model elapseTime_exp, which contains subsystem Amplifier, which includes a Discrete-Time Integrator block.
elapseTime_exp Model

Amplifier Subsystem

A 32-bit timer for the base rate (the only rate in this model) is defined within the rtModel structure, as follows, in model.h.
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
time_T stepSize;
uint32_T clockTick0;
uint32_T clockTickH0;
time_T stepSize0;
time_T tStart;
time_T tFinal;
time_T timeOfLastOutput;
void *timingData;
real_T *varNextHitTimesList;
SimTimeStep simTimeStep;
boolean_T stopRequestedFlag;
time_T *sampleTimes;
time_T *offsetTimes;
int_T *sampleTimeTaskIDPtr;
int_T *sampleHits;
int_T *perTaskSampleHits;
time_T *t;
time_T sampleTimesArray[1];
time_T offsetTimesArray[1];
int_T sampleTimeTaskIDArray[1];
int_T sampleHitArray[1];
int_T perTaskSampleHitsArray[1];
time_T tArray[1];
} Timing;
Had the target been ERT instead of GRT, the Timing structure would have been pruned to contain only the data required by the model, as follows:
/* Real-time Model Data Structure */ (for ERT!)
struct _RT_MODEL_elapseTime_exp_Tag {
/*
* Timing:
* The following substructure contains information regarding
* the timing information for the model.
*/
struct {
uint32_T clockTick0;
} Timing;
};
Storage for the previous-time value of the Amplifier subsystem (Amplifier_PREV_T) is allocated in the D_Work(states) structure in model.h.
typedef struct D_Work_elapseTime_exp_tag {
real_T DiscreteTimeIntegrator_DSTATE; /* '<S1>/Discrete-Time
Integrator' */
int32_T clockTickCounter; /* '<Root>/Pulse Generator' */
uint32_T Amplifier_PREV_T; /* '<Root>/Amplifier' */
} D_Work_elapseTime_exp;
These structures are declared in model.c:
/* Block states (auto storage) */ D_Work_elapseTime_exp elapseTime_exp_DWork; . . . /* Real-time model */ rtModel_elapseTime_exp elapseTime_exp_M_; rtModel_elapseTime_exp *elapseTime_exp_M = &elapseTime_exp_M_;
The elapsed time computation is performed as follows within the model_step function:
/* Output and update for trigger system: '<Root>/Amplifier' */
uint32_T rt_currentTime =
((uint32_T)elapseTime_exp_M->Timing.clockTick0);
uint32_T rt_elapseTime = rt_currentTime -
elapseTime_exp_DWork.Amplifier_PREV_T;
elapseTime_exp_DWork.Amplifier_PREV_T = rt_currentTime;
As shown above, the elapsed time is maintained as a state of the triggered subsystem. The Discrete-Time Integrator block finally performs its output and update computations using the elapsed time.
/* DiscreteIntegrator: '<S1>/Discrete-Time Integrator' */ OUTPUT = elapseTime_exp_DWork.DiscreteTimeIntegrator_DSTATE; /* Update for DiscreteIntegrator: '<S1>/Discrete-Time Integrator'*/ elapseTime_exp_DWork.DiscreteTimeIntegrator_DSTATE += 0.3 * (real_T)rt_elapseTime * 1.5 ;
Because the triggered subsystem maintains the elapsed time, the TLC implementation of the Discrete-Time Integrator block needs only a single call to LibGetElapseTime to access the elapsed time value.
Absolute time is the time that has elapsed from the beginning of program execution to the present time, as distinct from elapsed time, the interval between two events. See Absolute and Elapsed Time Computation for more information.
When you design an application that is intended to run indefinitely, you must take care when logging time values, or using charts or blocks that depend on absolute time. If the value of time reaches the largest value that can be represented by the data type used by the timer to store time, the timer overflows and the logged time or block output is no longer correct.
If your target uses rtModel, you can avoid timer overflow by setting an appropriate Application life span option. See Integer Timers in Generated Code for more information.
If you log time values by enabling Configuration Parameters > Data Import/Export > Save to workspace > Time your model uses absolute time.
Every Stateflow chart that uses time is dependent on absolute time. The only way to eliminate the dependency is to change the Stateflow chart to not use time.
The following Simulink blocks depend on absolute time:
Discrete-Time Integrator (only when used in triggered subsystems)
Sine Wave (only when the Sine type parameter is set to Time-based)
To Workspace (only when logging to StructureWithTime format)
In addition to the Simulink blocks above, blocks in other blocksets may depend on absolute time. See the documentation for the blocksets that you use.
![]() | Handling Asynchronous Events | Configuring Scheduling | ![]() |

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 |