zoukankan      html  css  js  c++  java
  • ucos任务优先级从64到256,任务就绪表的改变

         Ucos在任务调度中经常使用的技术为任务就绪表,在之前的文章中使用的例子是低于64个优先级的任务就绪表查找方法,现在ucos将任务扩展到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.

  • 相关阅读:
    利用dockerfile定制镜像
    发布Docker 镜像到dockerhub
    Docker 停止容器
    133. Clone Graph
    132. Palindrome Partitioning II
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    127. Word Ladder
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4324919.html
Copyright © 2011-2022 走看看