As you should know a software timer is a mechanism that allows the code to call a function after certain time established by us. Software Timers in embOS allow functions to be executed at regular intervals or after a specified time without the need for hardware timers. They are managed by the RTOS kernel and are useful for scheduling timed events without blocking task execution.

Here are some examples of how you can use the software timers.

struct OS_TIMER_STRUCT 
{
  OS_TIMER*        pNext;             //* Timer control structure pointer
  OS_ROUTINE_VOID* pfTimerRoutine;    //* Pointer to the callback funtion
  OS_TIME          Time;              
  OS_TIME          Period;            //* timeout value
  OS_BOOL          Active;            //* Active flag
#if (OS_DEBUG != 0)
  OS_U8            Id;
#endif
};

First of all to create a timer we have to create an instance of the timer structure.

static OS_TIMER Timer;  //* Timer control structure

Once we have created the timer control structure we have to create the callback function the timer will use. In this case I’m going to use a single-shot timer, so I wont restart the timer.

static void Callback( void )
{
    SEGGER_SYSTEMVIEW_PrintfHost( "Hola Mundo\n" );
}

Now, just as with the task functions, embOS offer us two different ways to create our timer (function and macro). It's up to you what way you choose but the macro simplify the timer creation, so, let’s create the timer.

OS_TIMER_CREATE(&Timer, Callback, 200u); //* Macro to create the timer

With this macro we create and start the timer due to the macro invokes the function OS_TIMER_Start(). Let’s see how the main file is:

#include "bsp.h"

static OS_TIMER Timer;

static void Callback(void);

int main( void ){

    OS_Init();      // Initialize embOS (must be first)
    HAL_Init();
    OS_InitHW();   // Initialize Hardware for embOS

    GPIO_InitTypeDef GPIO_InitStruct;   //* GPIO Initialization struct

    __HAL_RCC_GPIOC_CLK_ENABLE( );      //* Enabling the GPIO C clock

    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull  = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pin   = GPIO_PIN_0;
    HAL_GPIO_Init( GPIOC, &GPIO_InitStruct );   //* Initializing GPIO C - Pin 0 to use it in our callback

    OS_TIMER_CREATE(&Timer, Callback, 500u);  //* Creating the software timer

    OS_Start();     // Start multitasking

    return 0u;
}

static void Callback(void){
    SEGGER_SYSVIEW_PrintfHost( "Hello world\n" );
}

SYSTEMVIEW

Build and flash the program and run systemview to notice that after 500 milliseconds the message “Hello world” appears.

Software Timer Functions

void OS_TIMER_Create( OS_TIMER* pTimer, OS_ROUTINE_VOID* pfTimerRoutine, OS_TIME Period );
void OS_TIMER_CreateEx( OS_TIMER_EX* pTimerEx, OS_ROUTINE_VOID_PTR* pfTimerRoutine, OS_TIME Period, void* pData );
void OS_TIMER_Delete( OS_TIMER* pTimer );
void OS_TIMER_DeleteEx( OS_TIMER_EX* pTimerEx );
OS_TIMER* OS_TIMER_GetCurrent( void );
OS_TIMER_EX* OS_TIMER_GetCurrentEx( void );
OS_TIME OS_TIMER_GetPeriod( OS_CONST_PTR OS_TIMER *pTimer );
OS_TIME OS_TIMER_GetPeriodEx( OS_CONST_PTR OS_TIMER_EX* pTimerEx );
OS_TIME OS_TIMER_GetRemainingPeriod( OS_CONST_PTR OS_TIMER *pTimer );
OS_TIME OS_TIMER_GetRemainingPeriodEx( OS_CONST_PTR OS_TIMER_EX* pTimerEx );
OS_BOOL OS_TIMER_GetStatus( OS_CONST_PTR OS_TIMER *pTimer );
OS_BOOL OS_TIMER_GetStatusEx( OS_CONST_PTR OS_TIMER_EX* pTimerEx );
void OS_TIMER_Restart(OS_TIMER* pTimer);
void OS_TIMER_RestartEx( OS_TIMER_EX* pTimerEx );
void OS_TIMER_SetPeriod( OS_TIMER* pTimer, OS_TIME Period );
void OS_TIMER_SetPeriodEx( OS_TIMER_EX* pTimerEx, OS_TIME Period );
void OS_TIMER_Start( OS_TIMER* pTimer );
void OS_TIMER_StartEx( OS_TIMER_EX* pTimerEx );
void OS_TIMER_Stop( OS_TIMER* pTimer );
void OS_TIMER_StopEx( OS_TIMER_EX* pTimerEx );
void OS_TIMER_Trigger( OS_TIMER* pTimer );
void OS_TIMER_TriggerEx( OS_TIMER_EX* pTimerEx );

Snippets

Exercises (printf)

  1. Create 3 timers with different times, timers should call the same callback function. The third timer should be initiated just the first time and with the timeout init the second timer, the timeout of the second timer must init the first timer, the timeout must init the third timer, and so on. Each timer should print a message indicating which timer has been executed.
  2. Create a task that communicates each 5sec to another task the activation of a timer. The timer should display a message each 200ms for a space of 2 seconds.
  3. Modify the last program, the first task should send to the second task a different timeout value for the timer every 5 seconds. (Use the values 200ms, 300ms, 500ms, and 1000ms).

Exercises

  1. Create a program, to create a Timer with reload mode to make LED blinks.
  2. Modify the last program to rotate the LED.
  3. Modify the first program to add a button, if the button is pressed the LED must stop blinking (the Timer is stopped ), and if the button is pressed again the timer can run normally. A task should be used to read the button pressed.
  4. Create a program that uses a button to activate a timer. A task must be created to read the button, each time the button is pressed the timer must run for 100ms to print a message.