We can extend the task context using our own structures, well this is also possible with timers and here is the example. You can notice the resemblance to the fourth code snippet. In this code I create 3 timers with 3 different times. Each timer has it’s own message and pin to toggle but this element are part of a structure. This elements are used in the callback function to determine what message and what pin should be printed and toggled.
#include "bsp.h"
#include "RTOS.h"
typedef struct
{
OS_TIMER Timer; // OS_TIMER has to be the first element
char* Message; // String to print a message
uint16_t Pin; // Pin number
// add more elements if you need
} My_App_Timer;
static My_App_Timer Timer0, Timer1, Timer2; // Timer control blocks
static void Callback(void);
int main( void )
{
OS_Init(); // Initialize embOS (must be first)
HAL_Init();
OS_InitHW(); // Initialize Hardware for embOS
__HAL_RCC_GPIOC_CLK_ENABLE( ); //* Enabling the GPIO C clock
GPIO_InitTypeDef GPIO_InitStruct; //* GPIO Initialization struct
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 | GPIO_PIN_2 | GPIO_PIN_3;
HAL_GPIO_Init( GPIOC, &GPIO_InitStruct ); //* Initializing GPIO C to use it in our callback
Timer0.Message = "TIMER 0";
Timer0.Pin = GPIO_PIN_0;
Timer1.Message = "TIMER 1";
Timer1.Pin = GPIO_PIN_2;
Timer2.Message = "TIMER 2";
Timer2.Pin = GPIO_PIN_3;
OS_TIMER_CREATE( &Timer0.Timer, Callback, 100 );
OS_TIMER_CREATE( &Timer1.Timer, Callback, 200 );
OS_TIMER_CREATE( &Timer2.Timer, Callback, 300 );
OS_Start(); // Start multitasking
return 0u;
}
static void Callback(void)
{
My_App_Timer* pThis;
char* Message;
uint16_t Pin;
pThis = (My_App_Timer*)OS_TIMER_GetCurrent(); // Obtaining the pointer to the software timer object whose callback is currently executing.
Message = pThis->Message; // Obtaining the message to print
Pin = pThis->Pin; // Obtaining the Pin to toggle
SEGGER_SYSVIEW_PrintfHost( Message );
HAL_GPIO_TogglePin( GPIOC, Pin );
/* Depending what message is received the next timer is restarted */
if( strcmp( Message, "TIMER 0" ) == 0 )
{
OS_TIMER_Restart( &Timer1.Timer );
}
else if( strcmp( Message, "TIMER 1" ) == 0 )
{
OS_TIMER_Restart( &Timer2.Timer );
}
else
{
OS_TIMER_Restart( &Timer0.Timer );
}
}
SystemView
Build and flash this program and run SystemView to appreciate with more detail the behavior of this example. First let’s look at the timeline, notice how the timers are running according with their periods.

Looking closer you can notice how the timers are running.

Now in the event list and terminal window you can see the behavior in more detail.
