The scheduler should have an interface to register task-independent software timers. the software timer shall be decremented down to zero during the scheduler tick and should have the possibility to call a pre-registered callback function. Once its count reaches zero the timer decrement must stop, to later be restarted again by the application in case necessary. The scheduler main function shall be the one in charge of decrement each registered Timer.
- The init function shall accept parameter to manage timers
void Scheduler_Init( SchedulerType *Scheduler, uint32_t TickBase, uint8_t Tasks, TaskType *TasksBuffer, uint8_t Timers, TimerType *TimerBuffer );
Two new parameter are added to init functions, the number of timer to be manage by the scheduler and a pointer where we store the TCB for the timers
- The scheduler should have an interface to register the timer to run
uint8_t Scheduler_RegisterTimer( SchedulerType *Scheduler, uint32_t timeout, void (*CallbackPtr)(void) );
The function will register a new software timer to be updated on every tick, the timer shall count from a timeout value down to zero, and once its count ended the timer will stop and execute the function callback registered (the third parameter is optional in case no callback is needed a NULL shall be passed). To successfully register a timer the time in milliseconds should be larger than the actual tick and multiple. The function returns an ID which is a value from 1 to the number of timer registers in the scheduler, otherwise, it will return zero indicating the timer couldn't be registered.
- The scheduler should provide an interface to get the current timer time
uint32_t Scheduler_GetTimer( SchedulerType *Scheduler, uint8_t Timer );
The function will return the current timer pending time in milliseconds, in case the timer does not been registered the function returns a zero value
- The scheduler should provide an interface to reload a timer with a new period value
uint8_t Scheduler_ReloadTimer( SchedulerType *Scheduler, uint8_t Timer, uint32_t Timeout );
The timer will be reloaded with a new value in milliseconds it will also start the timer, the function does not require the timer to stop first, but if the timer to reload has not been registered no action will be taken and it will return a zero, otherwise return one as an indication of success.
- The scheduler should provide an interface to start the timer count
uint8_t Scheduler_StartTimer( SchedulerType *Scheduler, uint8_t Timer );
By default the timer count does not start when the timer is registered, it is necessary to call this function, the actual timer decrement count is carried out during each tick occurrence. The function will also serve as a mechanism of restart the timer from its timeout. If the timer to start has not been registered no action will be taken and it will return a zero, otherwise return one as an indication of success.
- The scheduler should provide an interface to start the timer count
uint8_t Scheduler_StopTimer( SchedulerType *Scheduler, uint8_t Timer );
The function will indicate the timer should not be decremented during each tick occurrence. If the timer to stop has not been registered no action will be taken and it will return a zero, otherwise return one as an indication of success.
- The timer control structure should have the following elements
typedef struct _TimerType
{
uint32_t Timeout; /*!< timer timeout to decrement and reload when the timer is re-started */
uint8_t Count; /*!< actual timer decrement count */
uint8_t StartFlag; /*!< flag to start timer count */
void(*CallbackPtr)(void); /*!< pointer to callback function function */
} TimerType;
- The scheduler control structure shall have the following elements
typedef struct _SchedulerType
{
uint8_t Tasks; /*number of task to handle*/
uint32_t Tick; /*the time base in ms*/
uint8_t TasksCount; /*internal task counter*/
TaskType *TaskPtr; /*Pointer to buffer for the TCB tasks*/
uint8_t Timers; /*number of software timer to use*/
TimerType *TimerPtr; /*Pointer to buffer timer array*/
uint8_t TimerCount; /*!< internal timer counter*/
} SchedulerType;
This is an example of how to call a function after 1000ms using a timer
#include <stdio.h>
#include "scheduler.h"
#define TASKS_N 1
#defines TIMERS_N 1
#define TICK_VAL 100
static TaskType tasks[ TASKS_N ];
static TimerType timers[ N_TIMERS ];
static SchedulerType Sche;
static unsigned char TimerID;
void Init_500ms(void);
void Task_500ms(void);
void Callback(void);
int main( void )
{
unsigned char TaskID;
/*init the scheduler with two tasks and a tick time of 100ms and run for 10 seconds only*/
Scheduler_InitScheduler( &Sche, TICK_VAL, TASKS_N, &tasks,TIMERS_N, &timers );
/*register two task with thier corresponding init fucntions and their periodicyt, 100ms and 500ms*/
TaskID = Scheduler_RegisterTask( &Sche, Init_500ms, Task_500ms, 500 );
TimerID = Scheduler_RegisterTimer( &Sche, 1000u, Callback );
Scheduler_StartTimer( &Sche, TimerID );
/*run the scheduler forever*/
Scheduler_MainFunction( &Sche );
return 0;
}
void Init_500ms(void)
{
printf("Init task 500 millisecond");
}
void Task_500ms(void)
{
static int loop = 0;
printf("This is a counter from task 500ms: %d", loop++);
}
void Callback(void)
{
static int loop = 0;
printf("This is a counter from timer callback: %d", loop++);
Scheduler_StartTimer( TimerID );
}
Another way of using the software timer without requiring callback functions is asking if the timer is ready decremented to zero
/*Set the timer to expire after 1000ms, in this case we do not need a callback function*/
TimerID = Scheduler_RegisterTimer( &Sche, 1000u, NULL );
...
/*start the timer for the first time*/
Scheduler_StartTimer( &Sche, TimerID );
...
if( Scheduler_GetTimer( &Sche, TimerID ) == 0u )
{
/*start the timer again*/
Scheduler_StartTimer( &Sche, TimerID );
printf("This is a counter from timer decremented");
}