Overhead and the idle-task

hermarcel wrote on Saturday, February 05, 2005:

I was wondering:

The idle-task is run as often as other tasks allow it (priorities). In the idle-task, interrupts are switched off (enter_critical) and on again.
Doesn’t this make the system less responsive to interrupts? Why is there no call to vTaskDelay() to have the idle-task only run once in “portTICK_RATE_IDLE”-ticks?

rtel wrote on Saturday, February 05, 2005:

There must always be one task that is ready to execute.  It is important that the idle task does not delay or make any other blocking call.

There are a few options:

+ The idle task checks to see if any tasks have been deleted - and if so performs the necessary tidy up.  If you application does not delete tasks at run time then this call can be removed and the idle task never has to enter a critical section.

+ The idle task cannot block - but it can put the CPU into sleep mode.  The chosen sleep mode has to be such that the timer keeps running, and the tick interrupt will wake the processor.  This has the effect of the idle task only ever performing one loop - preventing it from entering any critical sections and wasting power.

+ If you have enough memory you can starve out the idle task (provided you don’t delete any tasks at run time).  Effectively create your own idle task at a priority 1 higher.  If you create a task that never blocks and has a priority higher than the idle task the idle task will never run.

+ Use the idle task to perform you background processing.  You effectively merge your low priority tasks and the idle task.  This is very good when you don’t have much memory.  See the http://www.FreeRTOS.org/tutorial pages for more info on this option.


hermarcel wrote on Saturday, February 05, 2005:

Understood. Thanks!

hermarcel wrote on Sunday, February 06, 2005:

Hmm, maybe two tasks. An idle-task which does nothing (well, putting the cpu to sleep would be nice) but is always ready to run and a cleanup-task which delays x ticks between calls to prvCheckTasksWaitingTermination.

Could even make it conditional from portmacro.h: A single, combined idle-task (same as current implementation) or seperate idle and cleanup-tasks, both at idle-priority.

But an additional task…more ram needed…only a few kB available…AAAARGH

hermarcel wrote on Saturday, February 12, 2005:

To continue this thread :wink: :

It "feels" like the system is more responsive if the idle-task always calls yield, even when running in pre-emptive mode.

I can explain this because normally (without yield-call) a taskswitch from the idle-task to another ready-task is not done until the idle-task has completely used it’s timeslice. Why wait for this? If the yield is executed, the next task will get control sooner.

Am I correct? Are there any reasons why the yield is skipped when running pre-emptive?

Remember: I’m still learning :slight_smile:

rtel wrote on Saturday, February 12, 2005:

When the idle task is running -

+ If a task with higher priority becomes available a task switch will occur immediately - the idle task will be preempted.

+ If a task that has the same priority as the idle task becomes available then the idle task will continue to the end of it’s timeslice.

The allocation of priorities is obviously an application design decision and effects this behavior.  It comes back to the same choice of should there be any tasks that run at the idle priority, should an idle task switch be used instead, etc

The only problem with adding a yield to each cycle of the idle task is that interrupts will be disabled for longer (overall) as each yield call will have interrupts disabled for a period of time.


hermarcel wrote on Sunday, February 13, 2005:

ok, learned something again :slight_smile:

In my ongoing quest to reduce the amount of time the idletask disables interrupts:

What if a simple cpu-loop was built into the idletask?

for(i=0; i<loopcount;i++)

rtel wrote on Sunday, February 13, 2005:

Don’t see why not.

As you know … the idle task has responsibility for deleting resources used by tasks that have been deleted, and this is where interrupts get disabled.  If you are not deleting tasks from your application then the call is not needed and can be removed.  This leaves the idle task just as a null loop.

However, changing the idle task means that each time you upgrade to a new release you have to paste back in your changes.  It might be good to make the changes in an idle task hook:

void prvIdleTask( void *pvParameters )
    <normal idle code>
    <more normal idle code>

void IdleHook( void )

OR - a nice alternative,

void IdleHook( void )

The sleep mode is obviously processor specific, and has to be a mode whereby the processor is woken by interrupts.

hermarcel wrote on Sunday, February 13, 2005:

I like that. But I know from your docs that you are not to fond of hooks…

This hook, however would be a good one. With the "hookcode" in port.c.

hermarcel wrote on Sunday, February 13, 2005:

Sorry, my mistake. The hookcode should not go in port.c because, of course, it can be different for every project.