一、任务优先级的表示
uC/OS-II中,规定最多可以有64个任务。每个任务的优先级不能相同,因此,优先级为0~63.数字越小,优先级越高,那么0就是最高优先级,63就是最低优先级。系统保留了优先级最高及最低的各4个,因此用户不能使用这8个优先级作为自己的任务的优先级。宏OS_LOWEST_PRIO用于设置规定最低优先级,如定义为30,那么比30数字大的更低优先级就不能用了。这里有点拗口。也就是,所有的任务不能多于31个。
系统将64个优先级分为8组,每组8个。OSRdyGrp 表示组, OSRdytbl[]表示每一组。他们定义如下:
#if OS_LOWEST_PRIO <= 63
OS_EXT  INT8U   OSRdyGrp;      /* Ready list group     */
OS_EXT  INT8U   OSRdyTbl[OS_RDY_TBL_SIZE];  /* Table of tasks which are ready to run    */
#else
OS_EXT  INT16U  OSRdyGrp;    /* Ready list group   */
OS_EXT  INT16U  OSRdyTbl[OS_RDY_TBL_SIZE];       /* Table of tasks which are ready to run    */
#endif    
#if OS_LOWEST_PRIO <= 63
....
#define    OS_RDY_TBL_SIZE  ( ( OS_LOWEST_PRIO ) / 8 + 1 )          /* Size of ready table  */
#else
......
#define   OS_RDY_TBL_SIZE   ((OS_LOWEST_PRIO) / 16 + 1)           /* Size of ready table */
#endif       这里好像是做了扩展,不局限于
 8
 位,貌似最多的任务不只
 64
 了。不管它,我们忽略另一种情况。因为不管多少任务,处理方式的是一样的。我们考虑所有优先级都有可能用到的情况,
 OS_LOWEST_PRIO
 就应该定义为
 63
 ,
 OS_RDY_TBL_SIZE
 就是。
 OSRdyTbl
 就是一个含
 8
 个元素的数组。 
 好了,OSRdyGrp的每一位表示一个组,如果该位为1,表示有任务用到了该组内的优先级(由于优先级不能相同,也表明有该任务,否则没有)。OSRdyTbl[x]的每一位表示该组内的每一个优先级,为1就有。例如OSRdyGrp[bit : 2] = 1;第三组内存在一个任务,也即是优先级16~23这8个优先级存在一个及多个。如果此时OSRdyTbl[2][bit :4] = 1; 表示第三组的第5个优先级存在,也就是数值为20的优先级存在。
二、设置OSRdyGrp及OSRdyTbl
讲了优先级列表如何表示,那么接下来就是创建一个任务时,如何将其对应的优先级加入到列表中。这是OS_TCBInit函数的关于设置OSRdyGrp及OSRdyTbl的代码。注:以下源码,就不摘录16位的情况。
     ptcb->OSTCBY    =  (INT8U)(prio >> 3);         /* Pre-compute X, Y, BitX and BitY   */
     ptcb->OSTCBBitY      = (INT8U)(1 << ptcb->OSTCBY);
     ptcb->OSTCBX         = (INT8U)(prio & 0x07);
     ptcb->OSTCBBitX      = (INT8U)(1 << ptcb->OSTCBX);
     .........
      OSRdyGrp  |= ptcb->OSTCBBitY;         /* Make task ready to run    */
      OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;      优先级prio是传人的参数,由于不会大于
 64
 ,
 prio
 为
 6
 位值,因此
 OSTCBY
 为
 prio
 高
 3
 位,表示组,不会大于
 8
 ,
 OSTCBX
 为
 prio
 低
 3
 位, 表示一个组的偏移量。OSRdyGrp
 和OSRdyTbl
 是按位表示的,就得将数值转化为位模式。接上面的例子
 prio = 20 = 0x10100
 ,OSTCBY是prio
 的高3
 位,为
 1
 , 表明该优先级落在第二组(从
 0
 开始), OSTCBBitY=0x10
 ,也就是
 bit:1
 为
 1
 。同理,OSTCBX= 4
 ,OSTCBBitX 
 的
 bit :5
 为
 1
 。
 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; 
 就是设置
 OSRdyTbl[1]
 的
 bit5. 
  
 三、任务调度中判断最高优先级
uC/OS-II每次任务调度都是运行最高优先级的任务。那么如何在所有的任务中寻找最高优先级了?前面已经介绍了,优先级信息存在OSRdyGrp,OSRdyTbl中。低位代表高优先级。先检查组,由低位到高位检查,检查到后,再在该组中由低位到高位检查,第一个为1的就是最高优先级了。
这个过程,说白了就是检查一个char型的数,所有位是1的最小的那个位。uC/OS-II中用的查表法进行的。表如下:
INT8U const OSUnMapTbl[256] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F */
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F */
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF */
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0xF0 to 0xFF */
    };
下面是OS_SchedNew()函数中获取最高优先级的代码:
       y  =  OSUnMapTbl[OSRdyGrp];
       OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);    y
 就是查表得到的最小的那一个组的,上面已经解释过了,优先级的高
 3
 位表示组,所以左移
 3
 位到高三位。加上查表得到的该组内的偏移量,就是最高优先级的数值了。 
 四、结语
该方法还是挺巧妙的。让每次查找进行几条语句就可以实现了。这个方法可以借鉴到其他地方。
                  
                  
                  
                  
                            
本文详细解析了uC/OS-II操作系统中任务优先级表示方法、优先级列表的设置及最高优先级任务的选择过程。通过巧妙的数据结构设计,实现高效的任务调度。
          
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
					806
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            