Ucos_ii when a task switch is in progress, the highest priority task in the current ready queue is selected to run. So how did Ucos_ii find the Task with the highest priority?
Start with the following code snippet to analyze
#define Os_lowest_prio 63u/ * Defines the LOWEST priority, can be assigned ... */static void os_schednew (void) {#if Os_lowest_prio <= 63u/* See if we support up to + tasks */ I nt8u y; Y = osunmaptbl[osrdygrp]; Ospriohighrdy = (int8u) ((y << 3u) + osunmaptbl[osrdytbl[y]); #else */
Visible, Ospriohighrdy can be obtained by calculating osrdygrp,osunmaptbl and OSRDYTBL. So what is the meaning of these three parameters, explained below?
Pre-defined:
#if os_lowest_prio <= 63u#define os_rdy_tbl_size ((Os_lowest_prio)/8u + 1u)/* SIZE of Ready table */#if Os_lowest_prio <= 63utypedef int8u os_prio; #if os_lowest_prio <= 63u#define os_rdy_tbl_size ( (Os_lowest_prio)/8u + 1u)/* Size of Ready table */#if os_lowest_prio <= 63utypedef int8u Os_prio;
Osrdytbl
Os_ext Os_prio osrdytbl[os_rdy_tbl_size]; /* Table of tasks which is ready to run */
The visible osrdytbl is an array of type int8u of length 8, where each bit represents the priority 0-63.
Osrdytbl[0] Bit7. Bit0-- Prio7 . PRIO0OSRDYTBL[1] Bit7. Bit0-- Prio15. PRIO8OSRDYTBL[2] Bit7. Bit0-- Prio23. PRIO16OSRDYTBL[3] Bit7. Bit0-- Prio31. PRIO24OSRDYTBL[4] Bit7. Bit0-- Prio39. PRIO32OSRDYTBL[5] Bit7. Bit0-- Prio47. PRIO40OSRDYTBL[6] Bit7. Bit0-- Prio55. PRIO48OSRDYTBL[7] Bit7. Bit0-- Prio63. Prio56
Each Task in the ready state can have the corresponding position 1 in osrdytbl[] based on its priority value. For example, if a Task with ready has a priority value of 4, you need to set osrdytbl[0] |= bit_4.
Osrdygrp
Os_ext Os_prio osrdygrp; /* Ready List Group
Each bit of the OSRDYGRP represents the group of each priority in osrdytbl[]. For example, the Prio5 Task is in the ready state and it belongs to Osrdytbl[0], so osrdygrp |= bit_0. Another example is the Prio13 Task is in the ready state, it belongs to Osrdytbl[1], so osrdygrp |= bit_1.
Osunmaptbl
int8u Const OSUNMAPTBL[256] = {0u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x00 to 0x0F */4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x10 to 0x1F */ 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x20 to 0x2F */4u, 0u, 1u, 0u, 2 U, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x30 to 0x3F * * 6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0U, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x40 to 0X4F */4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 0 U, 1u, 0u,/* 0x50 to 0x5f */5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u,/* 0x60 To 0x6F */4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x70 to 0x7F */7u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x80 to 0x8F */4u, 0U, 1u, 0u, 2u, 0u, 1u, 0U, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0x90 to 0x9F */5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 0 U, 2u, 0u, 1u, 0u,/* 0xA0 to 0xAF */4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, /* 0xb0 to 0xBF */6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u,/* 0xC0 to 0U */4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0xD0 to 0xDF * /5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u,/* 0xE0 to 0xEF */4u, 0u, 1u, 0 U, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u//0xF0 to 0xFF */};
Each member of osunmaptbl[] represents the bit position where the least significant bit (the lowest non-zero bit) is located for a int8u number (0-255). For example, 0x01, 0x03, 0x05, their least significant bits are bit_0, so osunmaptbl[1], osunmaptbl[3], osunmaptbl[5] are all 0. And 0x2, 0x6, 0xA, their least significant bits are bit_1, so osunmaptbl[2], osunmaptbl[6], osunmaptbl[10] are all 1. Therefore, you can use osunmaptbl[] to quickly determine the location of the least significant bit of a number of a int8u type by using a table-checking method.
Let's take a look at how Ucos_ii handles priority.
1. When a task is created, it calls the
int8u os_tcbinit (int8u prio, os_stk *ptos, os_stk *pbos, int16u ID, int32u stk_size, void *pext, int16u opt)
which
#if os_lowest_prio <= 63u /* Pre-compute X, Y * /ptcb->ostcby = (int8u) (PRIO >> 3u); PTCB->OSTCBX = (int8u) (Prio & 0x07u); /* Pre-compute BITX and bity */ ptcb->ostcbbity = (Os_prio) (1uL << ptcb->ostcby); Ptcb->ostcbbitx = (Os_prio) (1uL << PTCB->OSTCBX);
Visible in Os_tcbinit () in the Prio bit2-bit0 assigned to PTCB->OSTCBX, Bit5-bit3 was assigned to PTCB->OSTCBY. Therefore, Ptcb->ostcby represents the group number of the Prio in osrdytbl[], and PTCB->OSTCBX represents the bit position of the prio in Osrdytbl[ptcb->ostcby].
2. Now look at the Ostimetick () query Task in the ready state.
if ((Ptcb->ostcbstat & os_stat_suspend) = = Os_stat_rdy) {/ * is task suspended? */ osrdygrp |= ptcb->ostcbbity; /* No, make ready */ osrdytbl[ptcb->ostcby] |= ptcb->ostcbbitx; }
Here, the bit position in osrdygrp corresponding to the group number of the task priority is 1, which corresponds to the position 1 of the task priority in Osrdytbl[ptcb->ostcby].
3. Back to the previous mentioned,
static void os_schednew (void) {#if Os_lowest_prio <= 63u/* See if we support up to + tasks */
int8u y; Y = osunmaptbl[osrdygrp]; Ospriohighrdy = (int8u) ((y << 3u) + osunmaptbl[osrdytbl[y]);
In order to find the task of the highest priority in the ready queue (the lower number corresponding to higher), you need to find the one with the smallest group numbers and the smallest number within the group. Osunmaptbl[] is the table that is used to find the least significant bit of a int8u type number. Thus, the value corresponding to the highest priority in the current ready queue can be calculated.
Reference:
Priority the decision table Osunmaptbl principle Interpretation UCos
Ucos-ii how to get the highest-priority task