Products & Services Solutions Academia Support User Community Company

Learn more about Real-Time Workshop   

Using Timers

Absolute and Elapsed Time Computation

Introduction

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

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.

Timers for Periodic and Asynchronous Tasks

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:

Allocation of Timers

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:

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.

Integer Timers in Generated Code

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.

Elapsed Time Counters in Triggered Subsystems

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.

APIs for Accessing Timers

Introduction

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

C API for S-Functions

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.

TLC API for Code Generation

The following TLC functions support elapsed time counters in generated code when you inline S-functions by writing TLC scripts for them.

Elapsed Timer Code Generation Example

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.

Limitations on the Use of Absolute Time

About Absolute Time Limitations

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.

Logging Absolute Time

If you log time values by enabling Configuration Parameters > Data Import/Export > Save to workspace > Time your model uses absolute time.

Absolute Time in Stateflow Charts

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.

Blocks that Depend on Absolute Time

The following Simulink blocks depend on absolute time:

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.

  


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