TNeo  v1.08
Data Structures | Typedefs | Functions
tn_timer.h File Reference

Detailed Description

Timer is a kernel object that is used to ask the kernel to call some user-provided function at a particular time in the future, based on the system timer tick.

If you need to repeatedly wake up particular task, you can create semaphore which you should wait for in the task, and signal in the timer callback (remember that you should use tn_sem_isignal() in this callback, since it is called from an ISR).

If you need to perform rather fast action (such as toggle some pin, or the like), consider doing that right in the timer callback, in order to avoid context switch overhead.

The timer callback approach provides ultimate flexibility.

In the spirit of TNeo, timers are as lightweight as possible. That's why there is only one type of timer: the single-shot timer. If you need your timer to fire repeatedly, you can easily restart it from the timer function by the tn_timer_start(), so it's not a problem.

When timer fires, the user-provided function is called. Be aware of the following:

Consequently:

See TN_TimerFunc for the prototype of the function that could be scheduled.

TNeo offers two implementations of timers: static and dynamic. Refer to the page Time ticks for details.

Implementation of static timers

Although you don't have to understand the implementation of timers to use them, it is probably worth knowing, particularly because the kernel have an option TN_TICK_LISTS_CNT to customize the balance between performance of tn_tick_int_processing() and memory occupied by timers.

The easiest implementation of timers could be something like this: we have just a single list with all active timers, and at every system tick we should walk through all the timers in this list, and do the following with each timer:

This approach has drawbacks:

The latter is probably not so critical in the embedded world since large amount of timers is unlikely there; whereas the former is actually notable.

So, different approach was applied. The main idea is taken from the mainline Linux kernel source, but the implementation was simplified much because (1) embedded systems have much less resources, and (2) the kernel doesn't need to scale as well as Linux does. You can read about Linux timers implementation in the book "Linux Device Drivers", 3rd edition:

This book is freely available at http://lwn.net/Kernel/LDD3/ .

So, TNeo's implementation:

We have configurable value N that is a power of two, typical values are 4, 8 or 16.

If the timer expires in the next 1 to (N - 1) system ticks, it is added to one of the N lists (the so-called "tick" lists) devoted to short-range timers using the least significant bits of the timeout value. If it expires farther in the future, it is added to the "generic" list.

Each N-th system tick, all the timers from "generic" list are walked through, and the following is performed with each timer:

At every system tick, all the timers from current "tick" list are fired unconditionally. This is an efficient and nice solution.

The attentive reader may want to ask why do we use (N - 1) "tick" lists if we actually have N lists. That's because, again, we want to be able to modify timers from the timer function. If we use N lists, and user wants to add new timer with timeout equal to N, then new timer will be added to the same list which is iterated through at the moment, and things will be mixed up.

If we use (N - 1) lists, we are guaranteed that new timers can't be added to the current "tick" list while we are iterating through it. (although timer can be deleted from that list, but it's ok)

The N in the TNeo is configured by the compile-time option TN_TICK_LISTS_CNT.

Definition in file tn_timer.h.

Go to the source code of this file.

Data Structures

struct  TN_Timer
 Timer. More...
 

Typedefs

typedef void() TN_TimerFunc(struct TN_Timer *timer, void *p_user_data)
 Prototype of the function that should be called by timer. More...
 
typedef void() TN_CBTickSchedule(TN_TickCnt timeout)
 Available if only TN_DYNAMIC_TICK is set. More...
 
typedef TN_TickCnt() TN_CBTickCntGet(void)
 Available if only TN_DYNAMIC_TICK is set. More...
 

Functions

enum TN_RCode tn_timer_create (struct TN_Timer *timer, TN_TimerFunc *func, void *p_user_data)
 Construct the timer. More...
 
enum TN_RCode tn_timer_delete (struct TN_Timer *timer)
 Destruct the timer. More...
 
enum TN_RCode tn_timer_start (struct TN_Timer *timer, TN_TickCnt timeout)
 Start or restart the timer: that is, schedule the timer's function (given to tn_timer_create()) to be called later by the kernel. More...
 
enum TN_RCode tn_timer_cancel (struct TN_Timer *timer)
 If timer is active, cancel it. More...
 
enum TN_RCode tn_timer_set_func (struct TN_Timer *timer, TN_TimerFunc *func, void *p_user_data)
 Set user-provided function and pointer to user data for the timer. More...
 
enum TN_RCode tn_timer_is_active (struct TN_Timer *timer, TN_BOOL *p_is_active)
 Returns whether given timer is active or inactive. More...
 
enum TN_RCode tn_timer_time_left (struct TN_Timer *timer, TN_TickCnt *p_time_left)
 Returns how many system timer ticks (at most) is left for the timer to expire. More...
 

Typedef Documentation

◆ TN_TimerFunc

typedef void() TN_TimerFunc(struct TN_Timer *timer, void *p_user_data)

Prototype of the function that should be called by timer.

When timer fires, the user-provided function is called. Be aware of the following:

Consequently:

  • It's legal to call interrupt services from this function;
  • The function should be as fast as possible.
Parameters
timerTimer that caused function to be called
p_user_dataThe user-provided pointer given to tn_timer_create().

Definition at line 198 of file tn_timer.h.

◆ TN_CBTickSchedule

typedef void() TN_CBTickSchedule(TN_TickCnt timeout)

Available if only TN_DYNAMIC_TICK is set.

Prototype of callback function that should schedule next time to call tn_tick_int_processing().

See tn_callback_dyn_tick_set()

Parameters
timeoutTimeout after which tn_tick_int_processing() should be called next time. Note the following:
  • It might be TN_WAIT_INFINITE, which means that there are no active timeouts, and so, there's no need for tick interrupt at all.
  • It might be 0; in this case, it's already time to call tn_tick_int_processing(). You might want to set interrupt request bit then, in order to get to it as soon as possible.
  • In other cases, the function should schedule next call to tn_tick_int_processing() in the timeout tick periods.

Definition at line 268 of file tn_timer.h.

◆ TN_CBTickCntGet

typedef TN_TickCnt() TN_CBTickCntGet(void)

Available if only TN_DYNAMIC_TICK is set.

Prototype of callback function that should return current system tick counter value.

See tn_callback_dyn_tick_set()

Returns
current system tick counter value.

Definition at line 280 of file tn_timer.h.

Function Documentation

◆ tn_timer_create()

enum TN_RCode tn_timer_create ( struct TN_Timer timer,
TN_TimerFunc func,
void *  p_user_data 
)

Construct the timer.

id_timer field should not contain TN_ID_TIMER, otherwise, TN_RC_WPARAM is returned.

attr_call_task.png
attr_call_int.png
(refer to Legend for details)

Parameters
timerPointer to already allocated struct TN_Timer
funcFunction to be called by timer, can't be TN_NULL. See TN_TimerFunc()
p_user_dataUser data pointer that is given to user-provided func.
Returns

◆ tn_timer_delete()

enum TN_RCode tn_timer_delete ( struct TN_Timer timer)

Destruct the timer.

If the timer is active, it is cancelled first.

attr_call_task.png
attr_call_int.png
(refer to Legend for details)

Parameters
timertimer to destruct
Returns

◆ tn_timer_start()

enum TN_RCode tn_timer_start ( struct TN_Timer timer,
TN_TickCnt  timeout 
)

Start or restart the timer: that is, schedule the timer's function (given to tn_timer_create()) to be called later by the kernel.

See TN_TimerFunc().

It is legal to restart already active timer. In this case, the timer will be cancelled first.

attr_call_task.png
attr_call_int.png
(refer to Legend for details)

Parameters
timerTimer to start
timeoutNumber of system ticks after which timer should fire (i.e. function should be called). Note that timeout can't be TN_WAIT_INFINITE or 0.
Returns

◆ tn_timer_cancel()

enum TN_RCode tn_timer_cancel ( struct TN_Timer timer)

If timer is active, cancel it.

If timer is already inactive, nothing is changed.

attr_call_task.png
attr_call_int.png
(refer to Legend for details)

Parameters
timerTimer to cancel
Returns

◆ tn_timer_set_func()

enum TN_RCode tn_timer_set_func ( struct TN_Timer timer,
TN_TimerFunc func,
void *  p_user_data 
)

Set user-provided function and pointer to user data for the timer.

Can be called if timer is either active or inactive.

attr_call_task.png
attr_call_int.png
(refer to Legend for details)

Parameters
timerPointer to timer
funcFunction to be called by timer, can't be TN_NULL. See TN_TimerFunc()
p_user_dataUser data pointer that is given to user-provided func.
Returns

◆ tn_timer_is_active()

enum TN_RCode tn_timer_is_active ( struct TN_Timer timer,
TN_BOOL p_is_active 
)

Returns whether given timer is active or inactive.

attr_call_task.png
attr_call_int.png
(refer to Legend for details)

Parameters
timerPointer to timer
p_is_activePointer to TN_BOOL variable in which resulting value should be stored
Returns

◆ tn_timer_time_left()

enum TN_RCode tn_timer_time_left ( struct TN_Timer timer,
TN_TickCnt p_time_left 
)

Returns how many system timer ticks (at most) is left for the timer to expire.

If timer is inactive, 0 is returned.

attr_call_task.png
attr_call_int.png
(refer to Legend for details)

Parameters
timerPointer to timer
p_time_leftPointer to TN_TickCnt variable in which resulting value should be stored
Returns