The Idle Task

If enabled, OS_IdleTask() is the very first task created by µC/OS-III. The priority of the idle task is always set to OS_CFG_PRIO_MAX-1. In fact, OS_IdleTask() is the only task that is ever allowed to be at this priority and, as a safeguard, when other tasks are created, OSTaskCreate() ensures that there are no other tasks created at the same priority as the idle task. The idle task runs whenever there are no other tasks that are ready-to-run.

If RAM space is tight, the idle task can be removed. This allows the user to save some data space since there is no need to have a stack for the idle task. However, even if there is not an actual task running at priority OS_CFG_PRIO_MAX-1, the user cannot create a task at that priority level. The level is still used to determine when to idle the CPU.

The important portions of the code for the idle task are shown below (refer to os_core.c for the complete code). These portions are still executed even if the idle task is disabled in os_cfg.h.

Listing - Idle Task
          void  OS_IdleTask (void *p_arg)
          {
              while (DEF_ON) {                    (1) 
                  CPU_CRITICAL_ENTER();
                  OSIdleTaskCtr++;                (2)   
                  OSStatTaskCtr++;
                  CPU_CRITICAL_EXIT();
                  OSIdleTaskHook();               (3) 
              }
          }

(1) The idle task is a “true” infinite loop that never calls functions to “wait for an event”. This is because, on most processors, when there is “nothing to do,” the processor still executes instructions. When µC/OS-III determines that there is no other higher-priority task to run, µC/OS-III “parks” the CPU in the idle task. However, instead of having an empty “infinite loop” doing nothing, µC/OS-III uses this “idle” time to do something useful.

(2) Two counters are incremented whenever the idle task runs.

OSIdleTaskCtr is typically defined as a 32-bit unsigned integer (see os.h). OSIdleTaskCtr is reset once when µC/OS-III is initialized. OSIdleTaskCtr is used to indicate “activity” in the idle task. In other words, if your code monitors and displays OSIdleTaskCtr, you should expect to see a value between 0x00000000 and 0xFFFFFFFF. The rate at which OSIdleTaskCtr increments depend on how busy the CPU is at running the application code. The faster the increment, the less work the CPU has to do in application tasks.

OSStatTaskCtr is also typically defined as a 32-bit unsigned integer (see os.h) and is used by the statistic task (described later) to get a sense of CPU utilization at run time.

(3) Every time through the loop, OS_IdleTask() calls OSIdleTaskHook(), which is a function that is declared in the µC/OS-III port for the processor used. OSIdleTaskHook() allows the implementer of the µC/OS-III port to perform additional processing during idle time. It is very important for this code to not make calls that would cause the idle task to “wait for an event”. This is generally not a problem as most programmers developing µC/OS-III ports know to follow this simple rule.

OSIdleTaskHook() may be used to place the CPU in low-power mode for battery-powered applications and thus avoid wasting energy. However, doing this means that OSStatTaskCtr cannot be used to measure CPU utilization (described later).


          void  OSIdleTaskHook (void)
          {
              /* Place the CPU in low power mode */
          }

Typically, most processors exit low-power mode when an interrupt occurs. Depending on the processor, however, the Interrupt Service Routine (ISR) may have to write to “special” registers to return the CPU to its full or desired speed. If the ISR wakes up a high-priority task (every task is higher in priority than the idle task) then the ISR will not immediately return to the interrupted idle task, but instead switch to the higher-priority task. When the higher-priority task completes its work and waits for its event to occur, µC/OS-III causes a context switch to return to OSIdleTaskHook() just “after” the instruction that caused the CPU to enter low-power mode. In turn, OSIdleTaskHook() returns to OS_IdleTask() and causes another iteration through the “infinite loop” which places the CPU back in the low power state.