It’s time to learn how the “OS_TASK_CREATEEX()" function works. when we are in the necessity of using one single function for different tasks we can pass a parameter to this function and use it in the way we want. To do this, we’re going to use the “OS_TASK_CREATEEX()" to provide a void pointer as parameter and use it into the different tasks. This void pointer is call “task context” and in the case of the example below we are using it to represent different delay values

#include "bsp.h"

static int Stack1[128], Stack2[128];  // Task stacks
static OS_TASK  Task1, Task2;                     // Task control blocks

void Task_Demo1( void* Parameter );

int main( void )
{
    OS_Init();      // Initialize embOS (must be first)
    HAL_Init();
    OS_InitHW();   // Initialize Hardware for embOS
    
    OS_TASK_CREATEEX(&Task1, "HP Task1", 100, Task_Demo1, Stack1, (void*) 1000); // creating the first task with its respective context
    OS_TASK_CREATEEX(&Task2, "HP Task2", 50, Task_Demo1, Stack2, (void*) 200);  // creating the second task with its respective context

    OS_Start();     // Start multitasking

    return 0u;
}


void Task_Demo1( void* Parameter ){

    GPIO_InitTypeDef GPIO_InitStruct;

    __HAL_RCC_GPIOA_CLK_ENABLE( );
    __HAL_RCC_GPIOC_CLK_ENABLE( );

    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull  = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pin   = GPIO_PIN_5;
    HAL_GPIO_Init( GPIOA, &GPIO_InitStruct );

    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 );

    for( ;; ){

        if( (OS_TIME)Parameter == 1000 ){
            SEGGER_SYSVIEW_PrintfHost( "TASK 1" );
            HAL_GPIO_TogglePin( GPIOA, GPIO_PIN_5 );
            OS_TASK_Delay((OS_TIME)Parameter);
        }
        else{
            SEGGER_SYSVIEW_PrintfHost( "TASK2 2" );
            HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_0 );
            OS_TASK_Delay((OS_TIME)Parameter);
        }
        
    }
}

The example above is a simple demonstration for using context within a task. However, embOS offers another little complex way of using the context.

SYSTEMVIEW

Build and flash the program and then run systemview.

Look at the timeline. You can see how every 200ms a task runs (TASK 2) and when the program reaches 1 second both tasks run.

looking closer you can notice how the tasks are running according with their priorities.

In the Event List we can see the messages that the tasks printed when each one was executed. In this way, we corroborate the task contexts are correct.