Introduction
This article gives you an idea of how to implement a timer routine for firmware development without using the Operating System. Timer is a very important tool in programming, and it makes life simple. For high level programming languages, we can use multiple timers depending on the capabilities of the system.
For some small and medium applications, porting the Operating System into a device will increase the cost significantly as its requires complex hardware. For most small and medium applications, the hardware does not support porting of Operating Systems. So in this article, I will try to give the basic concepts to create multiple independent timers from a single timer interrupt routine using C as the programming language.
All processors support at least one timer interrupt as a low priority interrupt, and it is generally used as a time base of the application.
Audience
This article is useful for those who want their binary output (.bin) file to directly execute on the hardware. Firmware development without Operating System is popular today for small and medium footprint hardware.
Code for the Timer Routine
Consider a linked-list having two elements, the timer ID and the corresponding time period, as shown below:
typedef struct Timer
{
unsigned short TimerId;
unsigned short Period;
struct Timer *pNext;
}tTimer;
static tTimer *mpTimerList = NULL;
static unsigned short gTimer;
where TimerID
is a 16-bit variable for identification, and Period
is the interval in milliseconds. Here, we can create a maximum of 16 timers, and they can be defined in the following way:
#define TIMER_1 (unsigned short)0x0001
#define TIMER_2 (unsigned short)0x0002
#define TIMER_3 (unsigned short)0x0004
..........
#define TIMER_16 (unsigned short)0x8000
Now, write a function AddTimer()
to populate the linked-list. Note that the timer is valid only if Period
> 0.
bool AddTimer(unsigned short TimerId, unsigned short Period)
{
tTimer *pTimer;
tTimer *pNewTimer = NULL;
bool ReturnValue = FALSE;
pTimer = FindTimer(TimerId);
if((pTimer == NULL) || (pTimer->TimerId != TimerId))
{
pNewTimer = malloc(sizeof(tTimer));
if(pNewTimer != NULL)
{
pNewTimer->TimerId = TimerId;
pNewTimer->pNext = NULL;
if(pTimer == NULL)
{
mpTimerList = pNewTimer;
}
else
{
pTimer = pNewTimer;
}
}
pTimer = pNewTimer;
}
if(pTimer != NULL)
{
pTimer->Period = Period;
ReturnValue = TRUE;
}
return ReturnValue;
}
In the above code, the function FindTimer
is useful to avoid the repetition of TimerID
in the linked-list. Its return NULL
only when the list is blank, else it returns the last node in case the TimerID
is not found within the list. If the TimerID
already exists, then it return the pointers of the corresponding node. The body of the function is shown below:
static tTimer * FindTimer(unsigned short TimerId)
{
tTimer *pTimer;
pTimer = mpTimerList;
if(pTimer != NULL)
{
while((pTimer->Next != NULL) && (pTimer->TimerId != TimerId))
{
pTimer = pTimer->Next;
}
}
return (pTimer);
}
Now, configuring the interrupt level 0, i.e., the timer interrupt such that the interrupt occurs every millisecond. The value of the corresponding register depends on the processor clock speed. So, put the proper value as per the instruction.
#pragma interrupt_level 0
void interrupt TimerBase(void)
{
if(TMRFLAG == 1)
{
TMRFLAG = 0;
RELOAD_TIMER0();
SystemTickEvent();
......
}
}
In the above case, the compiler takes care of the stack related activity. The SystemTickEvent()
function is responsible to generate the timer event by decrementing the period for each TimerID
. Here, the function is inline to minimize the execution time as possible.
#pragma inline SystemTickEvent
void SystemTickEvent(void)
{
tTimer *pTimer;
pTimer = mpTimerList;
while(pTimer != NULL)
{
if(pTimer->Period != 0)
{
pTimer->Period--;
if(pTimer->Period == 0)
{
gTimer = gTimer | pTimer->TimerID;
}
}
pTimer = pTimer->pNext;
}
}
The main routine should have the CheckTimerEvent()
function call within the infinite loop, along with other tasks.
void main(void)
{
InitMain ();
........
gTimer = 0;
AddTimer(TIMER_1, 1000);
AddTimer(TIMER_1, 500);
........
while(1)
{
CheckTimerEvent();
.......
}
}
CheckTimerEvent()
always checks if any timer completes the interval and calls the corresponding routine.
void CheckTimerEvent()
{
undigned short nTimer;
DisableInterrupt()
nTimer = gTimer;
gTimer = 0;
EnableInterrupt()
if( nTimer != 0)
{
if(nTimer & TIMER_1)
{
Timer1Function();
}
if(TimerID & TIMER_2)
{
Timer2Function();
}
........
}
}
This is a simple example to create multiple independent timers from a single time base. Hope it will help programmers. For any suggestions, please drop me a mail.