首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ucos任务优先级从64到256,任务就绪表的改变

ucos任务优先级从64到256,任务就绪表的改变

首先我们看任务就绪表的设置过程,当任务创建的时候需要设置一次任务就绪表,所以我们先看oscreatetask,在里面查找到这句代码
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);//然后初始化tcb任务区
    还记得tcb中有四个变量是用于快速查找任务就绪表的,分别是

ptcb->OSTCBY           

ptcb->OSTCBX            

ptcb->OSTCBBitY         

ptcb->OSTCBBitX      

    在OS_TCBInit中处理流程如下

#if OS_LOWEST_PRIO <= 63u                                         

        ptcb->OSTCBY             = (INT8U)(prio >> 3u);

        ptcb->OSTCBX             = (INT8U)(prio & 0x07u);

#else                                                            

        ptcb->OSTCBY             = (INT8U)((INT8U)(prio >> 4u) & 0xFFu);

        ptcb->OSTCBX             = (INT8U) (prio & 0x0Fu);

#endif


        ptcb->OSTCBBitY          = (OS_PRIO)(1uL << ptcb->OSTCBY);

        ptcb->OSTCBBitX          = (OS_PRIO)(1uL << ptcb->OSTCBX);

    可以看到,现在当系统定义的优先级大于63之后OSTCBY和OSTCBX的赋值方式发生了改变,之前是将345三位用于存放任务就绪分组,012存放就绪任务状态,这样就有了8个分组和每组八个任务,一共64个任务,而现在

    将0123四个位存放就绪任务状态值,4567四个位存放就绪任务分组的值,这样就有16个分组和16个位来存放,一共就能有256个任务了.

    这样改变之后就需要重新设置OSRdyGrp和OSRdyTbl[]的位宽,查看代码有以下内容

OS_EXT  OS_PRIO           OSRdyGrp;                       

OS_EXT  OS_PRIO           OSRdyTbl[OS_RDY_TBL_SIZE];

    位宽由OS_PRIO指定,再看OS_PRIO的定义,如下

#if OS_LOWEST_PRIO <= 63u

typedef  INT8U    OS_PRIO;

#else

typedef  INT16U   OS_PRIO;

#endif      

#define  OS_RDY_TBL_SIZE   ((OS_LOWEST_PRIO) / 16u + 1u)

    当优先级变化的时候,分组的宽度变成了16位,同时,数组长度变成了优先级/16+1,也就是说最多有16个元素,和我们所料不差,同样,当我们从任务就绪表中找出当前最高优先级的就绪任务的时候,查找方式也发生了变化,如下

INT8U     y;

OS_PRIO  *ptbl;


if ((OSRdyGrp & 0xFFu) != 0u) {

    y = OSUnMapTbl[OSRdyGrp & 0xFFu];

} else {

    y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;

}

ptbl = &OSRdyTbl[y];

if ((*ptbl & 0xFFu) != 0u) {

    OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);

} else {

    OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u);

}

    而之前的查找方式就颇为简单了

y             = OSUnMapTbl[OSRdyGrp];

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

    这两种方式有什么区别?

      首先, OSUnMapTbl这个数组是没有变化的,但是OSRdyGrp变成16位了,不能直接去表里面去查找了,这里面就做了一个调整,当低八位有任何一个不为0的时候,说明此时优先级最高的就绪任务的优先级在前八个OSRdyTbl元素中,0-7这是可以直接查表的,那当为0的时候,说明此时最高优先级的元素至少是第八个元素,那么将高八位代表的数值标出来,加上8,就能得到大于8的分组优先级.

      好,此时分组优先级得到了,要去找子优先级,可以直接在数组中找到,但是得到的数据时16进制的bcd码,还需要转换一次到hex,并且找出最高优先级,那就再用OSUnMapTbl过一次,处理的原理还是低八位有效直接通过低八位查找,高八位有效通过高八位查找并加上8,两个都得到之后

      Y左移四位加上子分组四位,就能得到当前最高优先级的任务的优先级了


    总结:ucos扩展任务优先级的方法就是将OSTCBY和OSTCBX原先三位标识优先级转为四位,将优先级从64转为256.

继承事业,薪火相传
返回列表