vApplicationIdleHook not running with FreeRTOS Kernel V10.4.6 and ARM Cortex M7

I am using an S32K3 from NXP with embedded FreeRTOS.

We have successfully added 5 periodic tasks at 1/4/5/10/100 milliseconds.
It seems like that IDLE hook never runs.

  1. In the FreeRTOSConfig.h:
    #define configSUPPORT_STATIC_ALLOCATION 1
    #define configUSE_IDLE_HOOK 1

    #define configUSE_PREEMPTION 1
    #define configUSE_TICKLESS_IDLE 0

    #define configIDLE_SHOULD_YIELD 1
    #define configUSE_IDLE_HOOK 1

  2. In the main.c

    #if ( configUSE_IDLE_HOOK == 1 )
    /* A variable that is incremented by the idle task hook function. /
    static volatile uint32_T ulIdleCycleCount = 0U;
    #endif // configUSE_IDLE_HOOK == 1
    … … …
    #if ( configUSE_IDLE_HOOK == 1 )
    /
    Idle hook functions MUST be called vApplicationIdleHook(), take no parameters,
    and return void. /
    void vApplicationIdleHook( void )
    {
    /
    This hook function does nothing but increment a counter. */
    ulIdleCycleCount++;
    }
    #endif // configUSE_IDLE_HOOK == 1

Task.c file kept unchanged, o.c.

Using Lauterback debugger I could see that periodic task are correctly triggered

xIdleTaskHandle is not NULL (i.e. correctly created and allocated by the scheduler) but Idle counter is always 0 and never increased.
The two breakpoint on the lauterbach debbuger are never triggered.

Where am I wrong with the FreeRTOS configuration? IDLE task is very important for pur applications for background activities (when not periodic neither event-driven tasks are in execution)

Thank you in advance,
Best Regards,

Andrea

My first thought is you have some task that never blocks that is at a priority level higher than 0, and is starving the idle task.

You also probably want to set configUSE_TIME_SLICING to 1 or a priority 0 task that never blocks or yields will also cause this issue.

Hi Richard,
For the sake of simplicity, I have set 5 periodic tasks with the same priority (1), as depicted below


In the FreeRTOS_config.h we have
image
Could it be a problem of Idle stack size?

Consider that we are reserving 500*4=2000 bytes for each periodic task.
Maybe OS configuration values must be tuned better.

If you are never going into the Idle task, it isn’t memory, it is CPU time. If there aren’t times when all 5 tasks are blocked, the idle task will never get time.

Since the tasks are above priority 0, the TIME_SLICING parameter isn’t as important for the Idle task.

Understood,

But how can I block/restart periodic task? below you could see its template

void Task5ms(void *argument)
{

    TickType_t xLastWakeTime;
    const TickType_t xFrequency = TASK_TIM_5MS_PERIOD;

    // Initialise the xLastWakeTime variable with the current time.
    xLastWakeTime = xTaskGetTickCount();

    for( ;; )
    {
        // Wait for the next cycle.
        vTaskDelayUntil( &xLastWakeTime, xFrequency );

        // Perform action here.
        FuncTask5ms();
        Task5msCnt++;
    }

}

Task of that format will block unless it takes more time to run than is available. The question comes, have you saturated your CPU with task activitiy.

Understood,

So, what is the solution?
I have saturated the CPU with only 5 periodic tasks…not a good thing for me.
We need both periodic and event-driven tasks (to be activated on CAN/LIN/SPI interrupt service routines).
How can I harmonize everything with FreeRTOS? Maybe it does not fit on our application.

One big question is do your I/O drivers use interrupts and block the task using the device while the I/O is in process, or do the tasks just poll a ready flag?

If the latter, then you are wasting a LOT of CPU time during I/O. Many vendor supplied I/O libraries do the latter and are a cause of this sort of problem.

IF that isn’t the problem, It may be needed to use the run-time stats functions to see if one of the tasks is over heavy.

Note, a task that runs every millisecond can’t do a lot without using up a large portion of the CPU time available.

It is also very possible that you just underspecified the CPU power you need, not knowing what all the tasks are doing, it is hard to say.

Another question is do these tasks really need to be “periodic”, or could they be changed to respond to actual needs? Waking up a task often for it to just check if it is needed wastes a lot of CPU time.

Yes, peripherals’ ISRs (CAN for diagnostics, or SPI communication between master uC and slave SBC, or a PWM for electronic motor control, Half bridges, and so on…) can block OS tasks during their execution; we usually pull (-> ISR disabled) only 1 CAN channel for development, for sure not during production phases.

Both OS periodic and event-driven tasks are fundamental for our application.

Using FreeRTOS manual, I have create the tasks and set delay for timing sheduling but, to be very honest, at the moment it is totally unclear for me how FreeRTOS manage tasks’ “switch-in”/ “switch-off” and how next IDLE (or background) task is activated and managed.

Anyway, just few minutes ago I have performed a very simple test, with all peripherals’ ISRs disabled, one periodic task with priortity 2 and cycling time 100msec.

As you could see, neither in this case the IDLE task is activated

Task is very simple

So just incrementing an unsigned counter every 100 milliseconds is consuming all of the CPU? Are we serious Richard?

I think instead that I am missing something in the FreeRTOS configuration and tasks’ internal handling (timeout or forced “go-to-block”).

Attached you could find the config file, could take a look for a fast check please?

B.R.

Andrea

image718970.png

image788792.png

image245508.png

image718970.png

image362321.png

image245508.png

FreeRTOSConfig.h (7.69 KB)

Priority 0 is NOT “Disabled”, so the fact they exist says they may be taking time (unless your code does something with this structure you are printing out).

Personally, I would likely turn on Run Time States, and see which task is using the time. The other option is to randomly breakpoint the system a few times and see what task is currently running.

Yes, it is quite possible that you have something misconfigured, but there is a lot of code you haven’t shared, so hard to tell, but Coretex-M7 should be a fairly straight forward port without a lot of options to get wrong, unless you HAVE changed something to customize it.

Ok,
Following your suggestion, I have enabled only one task (100 msec cycle period) and enabled the run stat (all conditions before still valid: no ISRs, etc…).

I added a simple FuncTask100ms (empty body) just for Lauterbach debugger breakpoints.
This is the situation at first occurrence of FuncTask100ms

At the second occurrence

At the third occurrence

Do you see something strange?

I have seen that these two counters
image
could overflow after a very long time, am I wrong?

Running the application w/o breakpoints I have noticed that task RunTimeCouter increases
image
and its overflow could be reached after a very long time, am I wrong?

The run time counter will continue to count (until it rolls over, at which point the run time stats get hard to interprete). The purpose of doing this was to see which task is getting all the CPU time.

The fact that you when you were running w/o break point you ended up in a “TaskEvent”, with a very large ulRunTimeCounter value makes me wonder what that task is doing. That may be your task that is using all your time.

Great Richard!
This was the problem; I checked again the OS_FreeRTOS_Init function and there were TaskEvent/TaskEvent1/TaskEvent2 not handled in any way, consuming all the CPU.

After code clean-up, we are now able to use the IDLE loop!
image

I can flag your response as problem solution
Thank you very much!

B.R
Andrea

That OS_FreeRTOS_Init function and those tasks are NOT part of the FreeRTOS distribution, but something added by someone (maybe the implementation as a “generic” interface). Maybe they were sample code that the framework intended to be edited with implementations.

For sure yes, some refuses (or “gift”) from my collegues.
Thks!