2、ucos优先级调度以及位运算的一些思考

ucos 的调度算法设计的很巧妙,是一个很经典的位图算法。很简洁。

   OSRdyGrp 、 OSRdyTbl[]、OSMapTbl[]、OSUnMapTbl[] 这四个变量组成。都是8位无符号类型的。ucos的设计是支持64个优先级(0 63 ,0优先级最高)。假设优先级为 prio,运算过程如下:

映射:    Y   = prio >> 3;             

           BitY      = OSMapTbl[Y];

           X         = prio & 0x07;

           BitX      = OSMapTbl[X];

OSRdyGrp  |= BitY;      

           OSRdyTbl[Y] |= BitX;

 

求最高优先级: y     = OSUnMapTbl[OSRdyGrp];        

        OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);

 

前一阵子,我以为把ucos扩展到256个优先级应该很容易。最近想了一下,不容易的,要改动的地方还不少。

   第一步,就是把OSRdyGrp 、 OSRdyTbl[]、OSMapTbl[]都定义为INT16U类型的变量,这是必须的。

此时INT16U const OSMapTbl[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000};

  

   第二步,这一步很关键,如果把OSUnMapTbl[]直接扩展到16位,那肯定行。。不过这样太那个了,65536个字节,这个玩笑开不得呢。 

我想还是用现成的吧,可以先算低八位,然后根据情况算高八位。  这样的话,有一个棘手的问题,低八位的值为0就惨了(64个优先级时,不会出现)。 可以这样处理:当低八位为0时,OSUnMapTbl[0] = -1;

此时: INT8S  const  OSUnMapTbl[] = {

-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,    

 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,    

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,         

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,                               

6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,         

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,         

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,         

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       

7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,         

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,          

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,        

6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,        

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,        

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0      

};

 

假设优先级为 prio,运算过程如下:

映射:    Y   = prio >> 4;             

           BitY      = OSMapTbl[Y];

           X         = prio & 0x0f;

           BitX      = OSMapTbl[X];

OSRdyGrp  |= BitY;      

           OSRdyTbl[Y] |= BitX;

 

求最高优先级: Y_L  =  OSRdyGrp &0XFF;

               Y_H  =  OSRdyGrp >> 8 ;

 

                if ((y = OSUnMapTbl[Y_L]) == -1)

                   y = OSUnMapTbl[Y_H] + 8 ;

              

 

              X_LOSRdyTbl[y] &0XFF ;

               X_H =  OSRdyTbl[y] >> 8 ; 

 

             if ((x = OSUnMapTbl[X_L]) == -1)

                   x = OSUnMapTbl[X_H] + 8 ;

 

               OSPrioHighRdy = (INT8U)((y << 4) + x);

 

麻烦吧,哈哈! 不过原理还是清晰的。就是把16位分为高八位,低八位咯。根据特殊情况做一下特殊处理就可以了。

 

1、 记得前一段时间,有个人问我怎么快速计算出一个usigned char 类型的数据有几个位为1。 当时我是说弄一个256个数据的数组,做一个映射。 其实不用这么麻烦的。16个数据的数组足够了。

unsigned char const map_1_tbl[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};

假设有数据 unsigned char类型的数据data

可以这样查:

 size = map_1_arr[data>>4] + map_1_arr[data & 0x0f] ;

 

1、很自然会想到,怎么快速计算出一个usigned char 类型的数据第一个为1的位呢?(低位到高位。)

为了方便,如果有为1的位,则计算出第一个为1的位的位置(0 - 7),如果没有则为-1 ; 可以这么做.

映射表:

 char const  map_frist_1_tbl[16] = {

-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,    

 };

 

计算: 

                if ((result = map_frist_1_tbl[data &0x0f]) == -1)

                   if((result = map_frist_1_tbl[data >> 4]) != -1)

                         result = result + 4 ;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值