Let's change the priorities of the tasks in previous code and let’s see what happen. uh-oh!, what happened this time?, The led with the lower priority task stop to blinking right?… Well, this happens because we are missing a very important detail… PREEMPTION. So, let’s remember what preemption is.
Basically, the highest-priority task in the READY state runs as long as it isn’t suspended by a call to an operating system blocking function, such as “OS_TASK_Delay().
” Therefore, the lowest-priority task will never run. This is what is called preemption.
Keeping this in mind, calling the “HAL_Delay()
” function is not the correct way to stop the task to execute. To make the tasks work properly, it’s important to use the delay function that comes with embOS “OS_TASK_Delay().
” This function suspends the task to allow other tasks to run. Therefore, lets apply the change to the highest-priority tasks.
#include "bsp.h"
static int Stack1[128], Stack2[128], Stack3[128]; // Task stacks
static OS_TASK Task1, Task2, Task3; // Task control blocks
void Task_Demo1( void );
void Task_Demo2( void );
void Task_Demo3( void );
int main( void )
{
OS_Init(); // Initialize embOS (must be first)
HAL_Init();
OS_InitHW(); // Initialize Hardware for embOS
OS_TASK_CREATE(&Task1, "HP Task1", 100, Task_Demo1, Stack1);
OS_TASK_CREATE(&Task2, "HP Task2", 50, Task_Demo2, Stack2);
OS_TASK_CREATE(&Task3, "HP Task3", 10, Task_Demo3, Stack3);
OS_Start(); // Start multitasking
return 0u;
}
void Task_Demo1( void )
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_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 );
for( ;; ){
SEGGER_SYSVIEW_PrintfHost( "TASK 1" );
HAL_GPIO_TogglePin( GPIOA, GPIO_PIN_5 );
OS_TASK_Delay(1000);
}
}
void Task_Demo2( void ){
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;
HAL_GPIO_Init( GPIOC, &GPIO_InitStruct );
for( ;; ){
SEGGER_SYSVIEW_PrintfHost( "TASK 2" );
HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_0 );
OS_TASK_Delay(500);
}
}
void Task_Demo3( void ){
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_2;
HAL_GPIO_Init( GPIOC, &GPIO_InitStruct );
for( ;; ){
SEGGER_SYSVIEW_PrintfHost( "TASK 3" );
HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_2 );
HAL_Delay(200);
}
}
The last task uses the “HAL_Delay()
” function because this task is the lowest priority.
SYSTEMVIEW.
Build and flash the program and then run systemview.

If we look the recording at 1 second we can see the 3 tasks running but with the priority order.

Now in the event list you can see the message each time the task is execute (each 200ms, 500ms and 1000ms in this case).