Higher priority task that does not block

Hello all,
I am currently using FreeRTOS kernel on a STM32f4, and I have the following problem:

  • I have three tasks and when they are of the same priority as TimerTask (configTIMER_TASK_PRIORITY), everything works correctly.

  • If I use a task of higher priority than TimerTask nothing starts, and when I increase the priority of TimerTask (same priority as the higher one), only the higher task works.

  • If I leave the same priority for all tasks, but that of TimerTask and higher, no task starts (it is as if it takes the cpu without freeing it).

NOTE: Knowing that the higher priority task and indeed blocks a good time to allow the activity of lower priority tasks.

My code is Here (working version):

#define configUSE_PREEMPTION                     1
#define configUSE_TIMERS                               1
#define configUSE_TIME_SLICING                    1
#define configTIMER_TASK_PRIORITY             2

void TaskBlue(void *pvParameters) {
   while (1) {
       blue_on();
       vTaskDelay(pdMS_TO_TICKS(5000)); 
   }
}

void TaskGreen(void *pvParameters) {
      while (1) {
       green_on();
       vTaskDelay(pdMS_TO_TICKS(1000));
   }
}

void TaskRed(void *pvParameters) {
    while (1) {
       red_on();
       vTaskDelay(pdMS_TO_TICKS(1000));
   }
}



void main_loop(void) {

clock_Init ();
timer_init();

SystemCoreClockUpdate();


if(SystemCoreClock != 168000000u){
    error();
    return;
}

SysTick_Config(SystemCoreClock / configTICK_RATE_HZ);


NVIC_SetPriority(SysTick_IRQn, configKERNEL_INTERRUPT_PRIORITY);

BaseType_t resultBlue =  xTaskCreate(TaskBlue, "Blue LED",   configMINIMAL_STACK_SIZE*2, NULL, 2, NULL);

BaseType_t resultGreen = xTaskCreate(TaskGreen, "Green LED", configMINIMAL_STACK_SIZE*2, NULL, 2, NULL);

BaseType_t resultRed =   xTaskCreate(TaskRed, "Red LED",     configMINIMAL_STACK_SIZE*2, NULL, 2, NULL);

if (resultBlue != pdPASS || resultGreen != pdPASS || resultRed != pdPASS) {
    error();
    return;
}

vTaskStartScheduler();

error();

for (;;);
}

Thank you by advance!

1 Like

Hi @Belaid, welcome to the FreeRTOS Community.
Looking at your code, are you using FreeRTOS Software Timers in your code somewhere else that you haven’t shared here ?

The timer functionality is an optional feature, FreeRTOS provides a set of timer related API’s like xTimerCreate(), xTimerStart() etc, which uses the timer task. You can further read about the timer task here.

In the case when nothing starts, do you reach the error() after the scheduler start. This would happen if there was not enough FreeRTOS heap to create the idle task or the timer task. You can define configASSERT in your application and it would catch this.

1 Like

Timer Task (priority 2) is waiting but never gets CPU time because TaskRed and TaskGreen keep waking up every 1000 ms. Since the Timer Task never runs, it cannot process timers, which means TaskBlue will not wake up properly after its delay. TaskBlue gets permanently stuck in vTaskDelay(5000) because the Timer Task never runs.

When the priority of the timer task is increased to that of the higher task , make sure the timer task yields , else the low priority tasks will be starved and never run.

1 Like

Building off of @rohitmdn’s response - what does timer_init do exactly? Providing the code for this would be helpful.

1 Like

My thoughts based on typical errors:

What do blue_on(), green_on(), red_on() do? Could they be spinning in a loop to blink the LEDs and not returning to the vTaskDelay? A more normal blinky task would have a call to a function to turn on the LED, a vTaskDelay, a call to a function to turn off the LED, then another vTaskDelay, or a function to toggle the LED with a vTaskDelay.

Do you have any timer callback functions that might run for a long time or block? That can mess up the system.

Normally, when only highest priority task is running, that indicates that the task isn’t blocking but maybe spin-waiting for something to happen.

1 Like

Hello all and thank you for your response,

@rohitmdn no, in the case when nothing starts, i never reach the error() function.
Kody : yes i have the TIM2 running but without callback.
@kstribrn here is the whole code :

#include "mainloop.h"

int i=0,j=0,k=0;
void blue_on(void)
{
    i = ~i;
    gpio_set_pin(0u , 0u , i);
}

void green_on(void)
{
    j = ~j;
    gpio_set_pin(0u , 2u , j);
}

void red_on(void)
{
    k = ~k;
    gpio_set_pin(0u , 4u , k);
}

void error(void)
{
    gpio_set_pin(0u, 1u, 0u);
}


/******************************RTOS*********************************/
/*******************************************************************/

void TaskBlue(void *pvParameters) {
    TickType_t xLastWakeTime = xTaskGetTickCount();
    while (1) { 
        blue_on();
        xTaskDelayUntil(&xLastWakeTime,pdMS_TO_TICKS(5000));
   }
}

void TaskGreen(void *pvParameters) {
    TickType_t xLastWakeTime = xTaskGetTickCount();
    while (1) {
       green_on();
       xTaskDelayUntil(&xLastWakeTime,pdMS_TO_TICKS(3000));
   }
}

void TaskRed(void *pvParameters) {
    TickType_t xLastWakeTime = xTaskGetTickCount();
    while (1) {
       red_on();
       xTaskDelayUntil(&xLastWakeTime,pdMS_TO_TICKS(1000));
   }
}

void main_loop(void) {

clock_Init ();//see the code below
timer_init(); //see the code below

SystemCoreClockUpdate();
if(SystemCoreClock != 168000000u){
    error();
    return;
}
SysTick_Config(SystemCoreClock / configTICK_RATE_HZ);


NVIC_SetPriority(PendSV_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY);

NVIC_SetPriority(SVCall_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);

NVIC_SetPriority(SysTick_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY);



BaseType_t resultBlue =  xTaskCreate(TaskBlue, "Blue LED",   configMINIMAL_STACK_SIZE, NULL, 2, NULL);

BaseType_t resultGreen = xTaskCreate(TaskGreen, "Green LED", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

BaseType_t resultRed =   xTaskCreate(TaskRed, "Red LED",     configMINIMAL_STACK_SIZE, NULL, 2, NULL);

if (resultBlue != pdPASS || resultGreen != pdPASS || resultRed != pdPASS) {
    error();
    return;
}


vTaskStartScheduler();

error();
for (;;);
/******************************RTOS*********************************/
/*******************************************************************/

} /*mainloop*/

**Code of timer_init(void) function :**

/***********************************
*    function to init the timer    *
*    no parm, no return              *
************************************/
void timer_init(void)
{

/* APB1 peripheral clock enable register for tim2*/
RCC_APB1ENR |= 1u;
while(!(TIM2_ENABLE_FLAG & RCC_APB1ENR));

/* reload value */
TIM2_ARR = 0xFFFFFFFFu;

/* set the prescaler */
TIM2_PRS = 83u;
/* update timer to take the new prsc */
TIM2_EGR |= 01u; 
/* set the timer to 0 */
TIM2_CNT = 0x00u;

/* enble timer*/
TIM2_CR1 |= 0x01u;
while(!(TIM2_ENABLE_FLAG & TIM2_CR1));
}


**Clock init function :**

/*************************************
*  this function allows to init the  *
*  clock using PLL and HSI as source *
*  No param  - No return            */
void clock_Init(void)
{

/* enable HSI */
RCC_CR |= 0x01u;
while (!(RCC_CR & HSI_ON_FLAG));

/* desable PLL (only for security) */
RCC_CR &= ~(1u << 24u);
while (RCC_CR & PLL_ON_FLAG);

/* P=2 Q=7 N=168 M=8 : clock=168KHz PERCLOCK=48MHz */
RCC_PLLCFGR = (  8u << 0u) |
              (168u << 6u) |
              ( 0u << 16u) |
              ( 7u << 24u);

RCC_CCFGR = (2u << 0u)  | /* PLL selected */
            (0u << 7u)  | /* AHB prescaler = 0 */
            (5u << 10u) | /* APB1 prescaler = 4 (limite max = 42 MHz) */
            (4u << 13u);  /* APB2 prescaler = 2 (limite max = 84 MHz) */ 

/* enable USB OTG FS,RNGEN,HASHEN,CRYPEN and DCMIEN clock */
RCC_AHB2   = 0xF1u;

/* flash access latency 5 wait state and enable Prefetch enable , Instruction cache enable et data cache enable */
FLASH_ACR = (5u) | (1u << 8u) | (1u << 9u) | (1u << 10u);

/* enable PLL  */
RCC_CR |= (1u << 24u);
while (!(RCC_CR & PLL_ON_FLAG));

}

Can you break the code in the debugger and see what it is doing?

1 Like

Thanks for the code. Your code is currently mixing two different mechanisms. For TaskBlue, TaskGreen, and TaskRed you’re creating FreeRTOS tasks. Tasks are kernel-aware and are scheduled by the kernel. Your task_init function is a hardware timer and it not kernel-aware (aka kernel scheduling does not apply to it).

The configTIMER_TASK_PRIORITY field only applies to FreeRTOS Software Timers. For more on how to use these please see this documentation on timers and their related APIs.