Periodic Tick Mode

Periodic Tick Mode is the default configuration of µC/OS-III. It is the simpler of the two modes which enable use of the time services. The mode relies on the use of a hardware timer, or some other timing source, which generates interrupts at a set frequency. Each interrupt advances the system time by one Tick.

Benefits

  • Easy to support.
  • The full set of timing services is available for use.
  • Round-Robin scheduling is fully supported.

Implications

  • The fixed-frequency interrupt forces the system out of low-power modes, even if there is nothing to do.

System Behavior

Figure - Tick ISR and Tick Task relationship

(1) Each tick interrupt represents the elapse of a single tick. 

(2) The interrupts prevent our system from sleeping continuously through it's idle period. Each wake-up potentially brings us out of a deep low-power state, wasting power needlessly. An interesting consequence of this tick mode is that power consumption changes with the tick rate. An application which might be able to squeeze by with a tick rate of 10, could potentially blow its power budget if the tick rate were 100 or 1000.

Periodic Tick

A hardware timer configured to generate an interrupt at a rate between 10 and 1000 Hz provides the clock tick. A tick source may also be obtained by generating an interrupt from an AC power line (typically 50 or 60 Hz). In fact, you can easily derive 100 or 120 Hz by detecting zero crossings of the power line. That being said, if your product is subject to be used in regions that use both power line frequencies then you may need to have the user specify which frequency to use or, have the product automatically detect which region it’s in.

The clock tick interrupt can be viewed as the system’s heartbeat. The rate is application specific and depends on the desired resolution of this time source. However, the faster the tick rate, the higher the overhead imposed on the system.

The clock tick interrupt allows µC/OS-III to delay tasks for an integral number of clock ticks and provide timeouts when tasks are waiting for events to occur.

The clock tick interrupt must call OSTimeTick(). The pseudocode for OSTimeTick() is shown in the listing below.

Listing - OSTimeTick() pseudocode
void  OSTimeTick (void)
{
    OSTimeTickHook();                                       (1)

    Run the round-robin scheduling algorithm;               (2)
    Update the tick list by processing 1 tick;              (3)
}

(1) The time tick ISR starts by calling a hook function, OSTimeTickHook(). The hook function allows the implementer of the µC/OS-III port to perform additional processing when a tick interrupt occurs. In turn, the tick hook can call a user-defined tick hook if its corresponding pointer, OS_AppTimeTickHookPtr, is non-NULL. The reason the hook is called first is to give the application immediate access to this periodic time source. This can be useful to read sensors at a regular interval (not as subject to jitter), update Pulse Width Modulation (PWM) registers, and more.

(2) µC/OS-III runs the round-robin scheduling algorithm to determine whether the time slot for the current task has expired.

(3) µC/OS-III calls OS_TickUpdate() to process 1 tick. The tick list is updated, and any tasks whose timeouts or delays expire on this tick are made ready to run.


Figure - Tick ISR and Tick Task relationship

(1)  A hardware timer is generally used and configured to generate an interrupt at a rate between 10 and 1000 Hz (see OS_CFG_TICK_RATE_HZ in os_cfg_app.h). This timer is generally called the Tick Timer. The actual rate to use depends on such factors as: processor speed, desired time resolution, and amount of allowable overhead to handle the tick timer, etc.

The tick interrupt does not have to be generated by a timer and, in fact, it can come from other regular time sources such as the power-line frequency (50 or 60 Hz), which are known to be fairly accurate over long periods of time.

(2) Assuming CPU interrupts are enabled, the CPU accepts the tick interrupt, preempts the current task, and vectors to the tick ISR. The tick ISR must call OSTimeTick() (see os_time.c), which accomplishes most of the work needed by µC/OS-III. The tick ISR then clears the timer interrupt (and possibly reloads the timer for the next interrupt). However, some timers may need to be taken care of prior to calling OSTimeTick() instead of after as shown below.

Listing - Handle timer source after OSTimeTick()
          void  TickISR (void)
          {
              OSTimeTick();
              /* Clear tick interrupt source             */
              /* Reload the timer for the next interrupt */
          }

or,

Listing - Handle timer source before OSTimeTick()
          void  TickISR (void)
          {
              /* Clear tick interrupt source             */
              /* Reload the timer for the next interrupt */
              OSTimeTick();
          }

(3) OSTimeTick() calls OSTimeTickHook() before any other function to give the opportunity to the µC/OS-III port developer to react as soon as possible upon servicing the tick interrupt. In other words, you may have your own code that needs to be serviced as soon as you get the tick interrupt. Afterwards, it calls a service, OS_TickUpdate(), provided by µC/OS-III to update the list of tasks that are waiting for time to expire or are waiting on a kernel object with a timeout. From this point forward, this will be called the tick list.

(4) OS_TickUpdate() is the function responsible for updating the tick list whenever time has passed. It takes the number of ticks which have elapsed as its argument. In periodic tick mode, where each interrupt reflects a single tick of time, OSTimeTick() always passes an argument of 1 to OS_TickUpdate().