Versions Compared

Key

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

...

µC/OS-III allows up to OS_CFG_PRIO_MAX different priority levels (see os_cfg.h). In µC/OS-III, a low-priority number corresponds to a high-priority level. Priority level zero (0) is thus the highest priority level. Priority OS_CFG_PRIO_MAX-1 is the lowest priority level. µC/OS-III uniquely assigns the lowest priority to the idle task and thus, no other tasks are allowed at this priority level. If there are tasks that are ready-to-run at a given a priority level, then its corresponding bit is set (i.e., 1) in the bitmap table. Notice in the figures below that “priority levels” are numbered from left to right and, the priority level increases (moves toward lower priority) with an increase in table index. The order was chosen to be able to use a special instruction called Count Leading Zeros (CLZ), which is found on many modern processors. This instruction greatly accelerates the process of determining the highest priority level.

Anchor
Figure - CPU_DATA declared as a CPU_INT08U
Figure - CPU_DATA declared as a CPU_INT08U

Panel
borderWidth0
titleFigure - CPU_DATA declared as a CPU_INT08U

Image Added


Anchor
Figure - CPU_DATA declared as a CPU_INT16U
Figure - CPU_DATA declared as a CPU_INT16U

Panel
borderWidth0
titleFigure - CPU_DATA declared as a CPU_INT16U

Image Added


Anchor
Figure - CPU_DATA declared as a CPU_INT32U
Figure - CPU_DATA declared as a CPU_INT32U

Panel
borderWidth0
titleFigure - CPU_DATA declared as a CPU_INT32U

Image Added


os_prio.c contains the code to set, clear, and search the bitmap table. These functions are internal to µC/OS-III and are placed in os_prio.c to allow them to be optimized in assembly language by replacing os_prio.c with an assembly language equivalent os_prio.asm, if necessary.

Anchor
Table - Priority Level access functions
Table - Priority Level access functions

Panel
borderWidth0
titleTable - Priority Level access functions


FunctionDescription
OS_PrioGetHighest()Find the highest priority level
OS_PrioInsert()Set bit corresponding to priority level in the bitmap table
OS_PrioRemove()Clear bit corresponding to priority level in the bitmap table



To determine the highest priority level that contains ready-to-run tasks, the bitmap table is scanned until the first bit set in the lowest bit position is found using OS_PrioGetHighest(). The code for this function is shown in the listing below.

Anchor
Listing - Finding the highest priority level
Listing - Finding the highest priority level

Code Block
languagecpp
titleListing - Finding the highest priority level
linenumberstrue
          OS_PRIO  OS_PrioGetHighest (void)
          {
              CPU_DATA  *p_tbl;
              OS_PRIO    prio;
              
              
              prio  = (OS_PRIO)0;
              p_tbl = &OSPrioTbl[0];
              while (*p_tbl == (CPU_DATA)0) {               (1) 
                  prio += DEF_INT_CPU_NBR_BITS;             (2) 
                  p_tbl++;
              }
              prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl);    (3) 
              return (prio);
          }


Panel
bgColor#f0f0f0

(1) OS_PrioGetHighest() scans the table from OSPrioTbl[0] until a non-zero entry is found. The loop will always terminate because there will always be a non-zero entry in the table because of the idle task.

(2) Each time a zero entry is found, we move to the next table entry and increment “prio” by the width (in number of bits) of each entry. If each entry is 32-bits wide, “prio” is incremented by 32.

(3) Once the first non-zero entry is found, the number of “leading zeros” of that entry is simply added and we return the priority level back to the caller. Counting the number of zeros is a CPU-specific function so that if a particular CPU has a built-in CLZ instruction, it is up to the implementer of the CPU port to take advantage of this feature. If the CPU used does not provide that instruction, the functionality must be implemented in C.


The function CPU_CntLeadZeros() simply counts how many zeros there are in a CPU_DATA entry starting from the left (i.e., most significant bit). For example, assuming 32 bits, 0xF0001234 results in 0 leading zeros and 0x00F01234 results in 8 leading zeros.

At first view, the linear path through the table might seem inefficient. However, if the number of priority levels is kept low, the search is quite fast. In fact, there are several optimizations to streamline the search. For example, if using a 32-bit processor and you are satisfied with limiting the number of different priority levels to 64, the above code can be optimized as shown in Listing 6-2. In the listing below. In fact, some processors have built-in “Count Leading Zeros” instructions and thus, the code can even be written with just a few lines of assembly language instead of C. Remember that with µC/OS-III, 64 priority levels does not mean that the user is limited to 64 tasks since with µC/OS-III, any number of tasks are possible at a given priority level (except 0 and OS_CFG_PRIO_MAX-1).

Anchor
Listing - Finding the highest priority level within 64 levels
Listing - Finding the highest priority level within 64 levels

Code Block
languagecpp
titleListing - Finding the highest priority level within 64 levels
linenumberstrue
          OS_PRIO  OS_PrioGetHighest (void)
          {
              OS_PRIO  prio;
              
           
              if (OSPrioTbl[0] != (OS_PRIO_BITMAP)0) {
                  prio = OS_CntLeadZeros(OSPrioTbl[0]);
              } else {
                  prio = OS_CntLeadZeros(OSPrioTbl[1]) + 32;
              }
              return (prio);
          }