框图:
对于拥有63个优先级的ucos系统,就绪表如下
相关的变量、数组源码:
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[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[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),
举个例子:
OSRdyGrp = 0x011; //0b00010001 //有两行存在就绪任务,分别是第0行和第4行OSRdyTbl[0] = 0x0a; //0b00001010 //第0行的具体数值=0x0a ==即该行存在2个任务就绪
OSRdyTbl[4] = 0x01; //0b00000001 //第4行的具体数值=0x01==即该行存在1个任务就绪
以上数据,可以知道出当前就绪的任务数==3,3个任务就绪。
但是,对于我们的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的工作就完成了。