embOS offers the ability to extend the context of a task by creating our own structures with the elements we want. This way, we can fill the structure elements in main function and use them within the task and all of this with a single function and with the function “OS_TASK_CREATE()"

💡
Note, the first element of the structure always must be an embOS task control structure OS_TASK.

Now our Control Task Blocks has to be the structure data type as you can see below.

#include "bsp.h"

/* In this case I'm adding 3 more elements apart from the Task Control Block 
   but you can add any number of elements to extend the context */
typedef struct{
    OS_TASK Task;       // OS_TASK has to be the first element
    char *Message;      // String to print a message
    OS_TIME Delay;      // Delay value for each task
    uint16_t Pin;       // Pin number
}MY_APP_TASK;

static int HPStack[128], LPStack[128];        // Task stacks
static MY_APP_TASK         HPTask, LPTask;    // Task control blocks

void Task_Demo( void );

int main( void )
{
    OS_Init();      // Initialize embOS (must be first)
    HAL_Init();
    OS_InitHW();   // Initialize Hardware for embOS

    HPTask.Message = "TASK 1";
    HPTask.Delay = 30;
    HPTask.Pin = GPIO_PIN_0;

    LPTask.Message = "TASK 2";
    LPTask.Delay = 10;
    LPTask.Pin = GPIO_PIN_2;
    
    OS_TASK_CREATE(&HPTask.Task, "HP Task", 100, Task_Demo, HPStack);
    OS_TASK_CREATE(&LPTask.Task, "LP Task", 50, Task_Demo, LPStack);

    OS_Start();     // Start multitasking

    return 0u;
}


void Task_Demo( void ){

    MY_APP_TASK* pThis;
    char *Message;
    OS_TIME Delay;
    uint16_t Pin;

    pThis = (MY_APP_TASK*)OS_TASK_GetID();

    GPIO_InitTypeDef GPIO_InitStruct;

    __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_0 | GPIO_PIN_2;
    HAL_GPIO_Init( GPIOC, &GPIO_InitStruct );

    for( ;; ){

        Message = pThis->Message;
        Delay = pThis->Delay;
        Pin = pThis->Pin;

        SEGGER_SYSVIEW_PrintfHost( Message );
        HAL_GPIO_TogglePin( GPIOC, Pin );
        OS_TASK_Delay( Delay );
        
    }
}

Now you know how to use the context of a task and how to extend it through a custom structure.

SYSTYEMVIEW

Build and flash the program and then run systemview.

Look at the timeline. You can see how every 10ms a task runs (TASK 2) and when the program reaches 30ms both tasks run. This means that the tasks are running according with their respective delays.

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