Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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.

Anchor
Listing - Idle Task
Listing - Idle Task

Code Block
languagecpp
titleListing - Idle Task
linenumberstrue
          void  OS_IdleTask (void *p_arg)
          {
              while (DEF_ON) {                    (1) 
                  CPU_CRITICAL_ENTER();
                  OSIdleTaskCtr++;                (2)   
                  OSStatTaskCtr++;
                  CPU_CRITICAL_EXIT();
                  OSIdleTaskHook();               (3) 
              }
          }


Panel
bgColor#f0f0f0

(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).


Code Block
          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.