第一次接触ucos实时操作系统,对就绪列表的优先级的查找,一头雾水,感觉完全没必要写的如此复杂,但经过一天的查找资料与思考,哈哈,原来还是我太年轻了,原来通过查表确保了查找最高优先级的实时性(优先级的高低并不影响查表花费的时间,因为查表过程都一样,能够准确知道查表的时间),为了方便以后回顾知识,便整理如理知识框架。
一、初始化过程 (os_core.c)
ptcb->OSTCBY = (INT8U)(prio >> 3u);
ptcb->OSTCBX = (INT8U)(prio & 0x07u);
但以上还不能在就绪表找到对应位置,因为就优先级在绪表的位置是X.Y的交点,而以上:比如优先级31时.
ptcb->OSTCBY =00000110, ptcb->OSTCBX =00000111 这就造成有两个X的对应一个Y,产生混乱,因此必须将00000110转化成一个坐标(坐标只用了三位,扩展至八位即可)即00000011---->00000100 , 00000111--->010000000,看下图。
二、确定优先级具体坐标
可发现,位置都差一位,因此可采取以下措施:
ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);
这个时候正好对应,如上如的31在第四行,第一列。
三、查找最高优先级
首先每次增加一个优先级,就需要或运算:
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSRdyGrp里面存放所有优先级的组成员, OSRdyTbl[ptcb->OSTCBY]存放所在组的所有成员,
比如优先级为13,14,15,19,20,30,31时,就绪表里就有7个点。
OSRdyGrp=00001110,
OSRdyTbl[1]=11100000,
OSRdyTbl[2]=00011000,
OSRdyTbl[3]=11000000,
可轻易发现最高优先级是13,但单片机不知道啊,我们可以从0开始查找,但就不知道到底花了多久能找到最高优先级,(因为位置不固定)。此时查表法的优势显现出来,
此时 OSRdyGrp里对应的0000010,在OSRdyTbl[1]里对应着00100000,这个坐标可利用如下表查找(查找
0-256里1最右边的位置)
INT8U const OSUnMapTbl[256] = {
0, 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
};
将查表后的数据代入下公式的最高优先级为13,
y = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);
剩下的就是系统处理最高优先级的任务了哈哈