uCOS 就绪表实现方法解析

框图:

对于拥有63个优先级的ucos系统,就绪表如下


对于任务最高优先级=63的ucos系统,就绪表如下
上图可看出,需要的数据至少包括:OSRdyTbl,OSRdyGrp;
为了实现更可控的、便捷的添加、删除、查找等就绪表相关操作,增加了OSMapTbl、OSUnMapTbl。

相关的变量、数组源码:

OSRdyTbl数组:就绪表 --任务优先级 列

INT8U             OSRdyTbl[8];       /* Table of tasks which are ready to run    */

OSRdyGrp全局变量:就绪表 --任务优先级行(组)

INT8U             OSRdyGrp;                        /* Ready list group                         */

OSUnMapTbl数组:索引表是用于解决最高优先级的位模式;索引为任务优先级,值为优先级的二进制最低有效值的位置(bit0-bit7的位置)

/*
*********************************************************************************************************
*                                       PRIORITY RESOLUTION TABLE
*
* Note: Index into table is bit pattern to resolve highest priority
*       Indexed value corresponds to highest priority bit position (i.e. 0..7)
*********************************************************************************************************
*/

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                             */
};

OSMapTbl数组:屏蔽字

INT8U  const  OSMapTbl[8] = {
	00000001,
	00000010,
	00000100,
	00001000,
	00010000,
	00100000,
	01000000,
	10000000,
};

但是,OSMapTbl不是必须的。

OSRdyTbl[]与OSRdyGrp之间的关系:

可以这样讲:
当OSRdyTbl[0]中的任何一位是1时,OSRdyGrp的第0位置1,
当OSRdyTbl[1]中的任何一位是1时,OSRdyGrp的第1位置1,
当OSRdyTbl[2]中的任何一位是1时,OSRdyGrp的第2位置1,
当OSRdyTbl[3]中的任何一位是1时,OSRdyGrp的第3位置1,
当OSRdyTbl[4]中的任何一位是1时,OSRdyGrp的第4位置1,
当OSRdyTbl[5]中的任何一位是1时,OSRdyGrp的第5位置1,
当OSRdyTbl[6]中的任何一位是1时,OSRdyGrp的第6位置1,
当OSRdyTbl[7]中的任何一位是1时,OSRdyGrp的第7位置1,
异或是这样讲:
OSRdyTbl[0]的bit7-bit0对应于优先级7-0, 
OSRdyTbl[1]的bit7-bit0对应于优先级15-8, 
OSRdyTbl[2]的bit7-bit0对应于优先级23-16, 
OSRdyTbl[3]的bit7-bit0对应于优先级31-24, 
OSRdyTbl[4]的bit7-bit0对应于优先级39-32, 
OSRdyTbl[5]的bit7-bit0对应于优先级47-40, 
OSRdyTbl[6]的bit7-bit0对应于优先级55-48, 
OSRdyTbl[7]的bit7-bit0对应于优先级63-56 
对于拥有63个优先级的系统:OSRdyGrp确定了优先级的次低三位(bit5-bit3),OSRdyTbl确定了优先级的低三位(bit2-bit0), 
毕竟2的6次幂=2^6= 64。

举个例子:

OSRdyGrp = 0x011;  //0b00010001 //有两行存在就绪任务,分别是第0行和第4行
OSRdyTbl[0] = 0x0a; //0b00001010 //第0行的具体数值=0x0a ==即该行存在2个任务就绪
OSRdyTbl[4] = 0x01; //0b00000001 //第4行的具体数值=0x01==即该行存在1个任务就绪
以上数据,可以知道出当前就绪的任务数==3,3个任务就绪。
优先级依次为:
0*8+1=1,
0*8+3=3,
4*8+0=32 ,

但是,对于我们的ucos,是抢占式内核,我们更关心当前哪位是任务就绪表中,优先级最优先的任务,即哪个任务的优先级数值最小。

即优先级prio=1的任务,优先级最高。

就绪表操作:

添加任务到就绪表:

    OS_TCB    *ptcb;
    ptcb->OSTCBY             = (INT8U)(prio >> 3);          /* Pre-compute X, Y, BitX and BitY     */
    ptcb->OSTCBX             = (INT8U)(prio & 0x07);
    ptcb->OSTCBBitY          = (INT8U)(1 << ptcb->OSTCBY);
    ptcb->OSTCBBitX          = (INT8U)(1 << ptcb->OSTCBX);
    OSRdyGrp               |= ptcb->OSTCBBitY;  /* No,  Make ready          */
    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;

异或这样子操作:prio是任务的优先级

    OSRdyGrp            |= OSMapTbl[prio >> 3];
    OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

从就绪表中删除任务:

    y             =  OSTCBCur->OSTCBY;            /* Task no longer ready                              */
    OSRdyTbl[y]  &= ~OSTCBCur->OSTCBBitX;
    if (OSRdyTbl[y] == 0) {
        OSRdyGrp &= ~OSTCBCur->OSTCBBitY;         /* Clear event grp bit if this was only task pending */
    }

异或:

if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
    OSRdyGrp &= ~OSMapTbl[prio >> 3];

以上代码将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零,而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零。也就是说OSRdyTbl[prio>>3]所有的位都是零时,OSRdyGrp的相应位才清零。

从任务就绪表中查找最高优先级任务(prio最小的任务)

    INT8U OSPrioHighRdy;            /* Priority of highest priority task    此为全局变量  */
    INT8U  y;
    y= OSUnMapTbl[OSRdyGrp];//取最高优先级行
    OSPrioHighRdy = (INT8U)((y << 3)/*最高优先级列乘上8*/ + 
		OSUnMapTbl[OSRdyTbl[y]/*取出最高优先级行中的数据*/]/*取出最高优先级列*/);/*计算出最高优先级值*/
    OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];/*最高优先级对应的任务控制块*/

异或:

    y    = OSUnMapTbl[OSRdyGrp];
    x    = OSUnMapTbl[OSRdyTbl[y]];
	prio = (y << 3) + x;

例如,如果OSRdyGrp的值为二进制01101000,查OSUnMapTbl[OSRdyGrp]得到的值是3,它相应于OSRdyGrp中的第3位bit3,这里假设最右边的一位是第0位bit0。类似地,如果OSRdyTbl[3]的值是二进制11100100,则OSUnMapTbl[OSRdyTbc[3]]的值是2,即第2位。于是任务的优先级Prio就等于26(3*8+2)。利用这个优先级的值。查任务控制块优先级表OSTCBPrioTbl[],得到指向相应任务的任务控制块OS_TCB的工作就完成了。


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值