When we work with tasks we have the possibility of using the same function for more than one tasks. With timers is the same case, we have the macro “OS_TIMER_CREATEEX()” to pass a void pointer as parameter, so, lets check the following example.

#include "bsp.h"
#include "RTOS.h"

static OS_TIMER_EX Timer0, Timer1;      //* Now we have to use this control structure type

static void Callback(void* Parameter);

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;
    HAL_GPIO_Init( GPIOC, &GPIO_InitStruct );       //* Initializing GPIO C to use it in our callback

    OS_TIMER_CREATEEX(&Timer0, Callback, 200u, (void *)GPIO_PIN_0 );       //* Creating the software timer passing the pin 0 as parameter
    OS_TIMER_CREATEEX(&Timer1, Callback, 500u, (void *)GPIO_PIN_2 );       //* Creating the software timer passing the pin 2 as parameter

    OS_Start();     // Start multitasking
    
    return 0u;
}

static void Callback(void* Parameter)
{    
    HAL_GPIO_TogglePin( GPIOC, (uint16_t)Parameter );   //* Here is where we use the void pointer. A cast to uint16_t is needed
    OS_TIMER_RestartEx( OS_TIMER_GetCurrentEx() );      //* When we are workink with extended timers we have to use the "EX" functions

}

SYSTEMVIEW

Build and flash the program and run systemview. First, let's look at the entire recording on the timeline. As you can see, the timers are running according with the established time.

Looking closer you can notice how the timers are running.

In the event list and terminal window you can see the behavior of both timers in more detail.