Timer Management
Timer Services
µC/OS-III provides timer services to the application programmer and code to handle timers is found in os_tmr.c
. Timer services are enabled when setting OS_CFG_TMR_EN
to DEF_ENABLED
in os_cfg.h
.
Timers are down counters that perform an action when the counter reaches zero. The user provides the action through a callback function (or simply callback). A callback is a user-declared function that will be called when the timer expires. The callback can be used to turn a light on or off, start a motor, or perform other actions. However, it is important to never make blocking calls within a callback function (i.e., call OSTimeDly()
, OSTimeDlyHMSM()
, OS???Pend()
, or anything that causes the timer task to block or be deleted).
Timers are useful in protocol stacks (retransmission timers, for example), and can also be used to poll I/O devices at predefined intervals.
An application can have any number of timers (limited only by the amount of RAM available). Timer services (i.e. functions) in µC/OS-III start with the OSTmr???()
prefix, and the services available to the application programmer are described in µC-OS-III API Reference.
The resolution of all the timers managed by µC/OS-III is determined by the configuration constant: OS_CFG_TMR_TASK_RATE_HZ
, which is expressed in Hertz (Hz). So, if the timer task (described later) rate is set to 10, all timers have a resolution of 1/10th of a second (ticks in the diagrams to follow). In fact, this is the typical recommended value for the timer task. Timers are to be used with “coarse” granularity.
µC/OS-III provides a number of services to manage timers as summarized in the table below.
Function Name | Operation |
---|---|
OSTmrCreate() | Create and specify the operating mode of the timer. |
OSTmrDel() | Delete a timer. |
OSTmrRemainGet() | Obtain the remaining time left before the timer expires. |
OSTmrStart() | Start (or restart) a timer. |
OSTmrStateGet() | Obtain the current state of a timer. |
OSTmrStop() | Stop the countdown process of a timer. |
A timer needs to be created before it can be used. You create a timer by calling OSTmrCreate()
and specify a number of arguments to this function based on how the timer is to operate. Once the timer operation is specified, its operating mode cannot be changed unless the timer is deleted and recreated. The function prototype for OSTmrCreate()
is shown below as a quick reference:
void OSTmrCreate (OS_TMR *p_tmr, /* Pointer to timer */ CPU_CHAR *p_name, /* Name of timer, ASCII */ OS_TICK dly, /* Initial delay */ OS_TICK period, /* Repeat period */ OS_OPT opt, /* Options */ OS_TMR_CALLBACK_PTR p_callback, /* Fnct to call at 0 */ void *p_callback_arg, /* Arg. to callback */ OS_ERR *p_err)
Once created, a timer can be started (or restarted) and stopped as often as is necessary. Timers can be created to operate in one of three modes: One-shot, Periodic (no initial delay), and Periodic (with initial delay).
One-Shot Timers
As its name implies, a one-shot timer will countdown from its initial value, call the callback function when it reaches zero, and stop. The figure below shows a timing diagram of this operation. The countdown is initiated by calling OSTmrStart()
. At the completion of the time delay, the callback function is called, assuming a callback function was provided when the timer was created. Once completed, the timer does not do anything unless restarted by calling OSTmrStart()
, at which point the process starts over.
You terminate the countdown process of a timer (before it reaches zero) by calling OSTmrStop()
. In this case, you can specify that the callback function be called or not.
As shown in the figure below, a one-shot timer can be retriggered by calling OSTmrStart()
before the timer reaches zero. This feature can be used to implement watchdogs and similar safeguards.
Periodic (no initial delay)
As indicated in the figure below, timers can be configured for periodic mode. When the countdown expires, the callback function is called, the timer is automatically reloaded, and the process is repeated. If specifying a delay of zero (i.e., dly == 0
) when the timer is created and, when started, the timer immediately uses the “period
” as the reload value. You can call OSTmrStart()
at any point in the countdown to restart the process.
Periodic (with initial delay)
As shown in the figure below, timers can be configured for periodic mode with an initial delay that is different than its period. The first countdown count comes from the “dly
” argument passed in the OSTmrCreate()
call, and the reload value is the “period
”. You can call OSTmrStart()
to restart the process including the initial delay.