首先看下不是很好理解的核心代码
ptcb->OSTCBY = (INT8U)(prio >> 3u); /* Pre-compute X, Y, BitX and BitY */
ptcb->OSTCBX = (INT8U)(prio & 0x07u);
ptcb->OSTCBBitY = (INT8U)(1u << ptcb->OSTCBY);
ptcb->OSTCBBitX = (INT8U)(1u << ptcb->OSTCBX);
OSRdyGrp |= ptcb->OSTCBBitY; //让该任务进入就绪态
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
然后内核挑选优先级最高的逻辑是这样
y = OSUnMapTbl[OSRdyGrp]; /* Find HPT waiting for message */
x = OSUnMapTbl[OSRdyTbl[y]];
prio = (INT8U)((y << 3u) + x); /* Find priority of task getting the msg */
我的理解是 prio 是个 8字节的数据,00 000 000 这样分为 2 3 3 , 用只用到 3 3。
在给 64 个优先级 分成了 8*8 的二维数组, 存在 INT8U OSRdyTbl[OS_RDY_TBL_SIZE]; 里面, 0~64中n 位为1 的话, 那n优先级的任务就就绪了。
假设某个任务 T 的优先级是 13 , 对应的二进制是 001 101, 那他就是 第 1 组 里面的 第 5 个 位。 //UCOS源代码里面用的是 Y 表示组; X表示 每组里的第几位
现在要把 OSRdyTbl 里面的 13 位 (即 第 1 组 里面的 第 5 个 位)首先截取出 高三位(按6位算,忽略高2位) (INT8U)(prio >> 3u)//Y 的值取出来了
截取出 低三位 (INT8U)(prio & 0x07u); //X的值取出来了
接下来就是要把 存 组情况的 OSRdyGrp 的 第 Y 位置 1 OSRdyGrp |= ptcb->OSTCBBitY;
然后把 OSRdyTbl 里面的 Y组 X 位 置一 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
当要查询就绪态谁的优先级最高就容易了
OSRdyGrp 的8 位中, 为 1 的最低的那一位 N, 就代表 第 N 组里面有就绪的 (通过查表法 y = OSUnMapTbl[OSRdyGrp] )
得到 第 N 组 OSRdyTbl[y] 的 8位后, 同样是找为 1 的最低位 (通过查表法 x = OSUnMapTbl[OSRdyTbl[y]] )
最后要 把 y 和 x 重新换算成 8 位 优先级 prio = (INT8U)((y << 3u) + x);
最后就是 OSUnMapTbl[] 查表的方案其实是 第 N 个数据的值 就是 N 的 为 1 的最低位 是 几。
类似 14 = 001 110B OSUnMapTbl[13] = 2
OSUnMapTbl[] 有 64 种 , 其实就是 8位 可以组成那么多状态吧, 然后每种状态里面优先级最高, 而且最低位 的那个 值存起来,在用来查查.....