Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Next »

Timer States

The figures below show the state diagrams for One-Shot and Periodic timers.

Tasks can call OSTmrStateGet() to find out the state of a timer. Also, at any time during the countdown process, the application code can call OSTmrRemainGet() to find out how much time remains before the timer reaches zero (0). The value returned is expressed in “timer ticks.” If timers are decremented at a rate of 10 Hz then a count of 50 corresponds to 5 seconds. If the timer is in the stop state, the time remaining will correspond to either the initial delay (one shot or periodic with initial delay), or the period if the timer is configured for periodic without initial delay.

One-Shot Timers

Periodic Timers

 

OS_TMR

A timer is a kernel object as defined by the OS_TMR data type (see os.h) as shown in the listing below:

The services provided by µC/OS-III to manage timers are implemented in the file os_tmr.c. Timer services are enabled at compile time by setting the configuration constant OS_CFG_TMR_EN to DEF_ENABLED in os_cfg.h.

Even if the internals of the OS_TMR data type are understood, the application code should never access any of the fields in this data structure directly. Instead, you should always use the Application Programming Interfaces (APIs) provided with µC/OS-III.

Timer Task

OS_TmrTask() is a task created by µC/OS-III (assumes setting OS_CFG_TMR_EN to DEF_ENABLED in os_cfg.h) and its priority is configurable by the user through µC/OS-III’s configuration file os_cfg_app.h (see OS_CFG_TMR_TASK_PRIO). OS_TmrTask() is typically set to a medium priority.

OS_TmrTask() is a periodic task and uses the same interrupt source used to generate clock ticks. However, timers are generally updated at a slower rate (i.e., typically 10 Hz or so) and thus, the timer tick rate is divided down in software. If the tick rate is 1000 Hz and the desired timer rate is 10 Hz then the timer task will be signaled every 100th tick interrupt as shown in the figure below.

The figure below shows timing diagram associated with the timer management task.

There are a few interesting things to notice:

  • Execution of the callback functions is performed within the context of the timer task. This means that the application code will need to make sure there is sufficient stack space for the timer task to handle these callbacks.
  • The callback functions are executed one after the other based on the order they are found in the timer list.
  • The execution time of the timer task greatly depends on how many timers expire and how long each of the callback functions takes to execute. Since the callbacks are provided by the application code they have a large influence on the execution time of the timer task.
  • The timer callback functions must never wait on events because this would delay the timer task for excessive amounts of time, if not forever.
  • Callbacks should execute as quickly as possible.

Timer List

µC/OS-III applications may require many timers. The timer manager implements a simple linear list where each timer is linked in a doubly linked list as shown in the figure below.

Timers are inserted in the timer list by calling OSTmrStart() and, a timer must be created before it can be used. Newly created timers are always inserted at the beginning of the list as shown in the figure following the code listing below  and the code listing itself.

Since this is the first timer inserted in the timer list, the .NextPtr and .PrevPtr both point to NULL.

The code below shows creating and starting another timer. This is performed “before” the timer task is signaled.

The “second timer” is inserted at the head of the list as shown in the figure below.

When the timer task executes (see OS_TmrTask() in os_tmr.c), it starts by incrementing OSTmrTickCtr and goes through the list (linearly) and decrements each of the .Remain field. When the .Remain field reaches zero, the timer manager executes the callback function associated with the timer and, if the timer is set to periodic, reloads the .Remain field with the time remaining to expiration. If the timer is configured as a one-shot timer then the timer is removed from the list upon expiration.

Timer management occurs at the task level. The list is protected using an internal mutual exclusion semaphore (mutex) when OS_CFG_MUTEX_EN is set to DEF_ENABLED  in os_cfg.h or, by locking the scheduler if mutexes are not enabled. It’s highly recommend that you use (and thus enable) mutexes because locking the scheduler impacts task responsiveness of other, higher priority tasks in your application.

  • No labels