uC/OS-II任务调度中判断最高优先级

一、任务优先级的表示

   uC/OS-II中,规定最多可以有64个任务。每个任务的优先级不能相同,因此,优先级为0~63.数字越小,优先级越高,那么0就是最高优先级,63就是最低优先级。系统保留了优先级最高及最低的各4个,因此用户不能使用这8个优先级作为自己的任务的优先级。宏OS_LOWEST_PRIO用于设置规定最低优先级,如定义为30,那么比30数字大的更低优先级就不能用了。这里有点拗口。也就是,所有的任务不能多于31个。

  系统将64个优先级分为8组,每组8个。OSRdyGrp 表示组, OSRdytbl[]表示每一组。他们定义如下:

#if OS_LOWEST_PRIO <= 63
OS_EXT  INT8U   OSRdyGrp;      /* Ready list group     */
OS_EXT  INT8U   OSRdyTbl[OS_RDY_TBL_SIZE];  /* Table of tasks which are ready to run    */
#else
OS_EXT  INT16U  OSRdyGrp;    /* Ready list group   */
OS_EXT  INT16U  OSRdyTbl[OS_RDY_TBL_SIZE];       /* Table of tasks which are ready to run    */
#endif    

#if OS_LOWEST_PRIO <= 63
....
#define    OS_RDY_TBL_SIZE  ( ( OS_LOWEST_PRIO ) / 8 + 1 )          /* Size of ready table  */
#else
......
#define   OS_RDY_TBL_SIZE   ((OS_LOWEST_PRIO) / 16 + 1)           /* Size of ready table */
#endif
       这里好像是做了扩展,不局限于 8 位,貌似最多的任务不只 64 了。不管它,我们忽略另一种情况。因为不管多少任务,处理方式的是一样的。我们考虑所有优先级都有可能用到的情况, OS_LOWEST_PRIO 就应该定义为 63 OS_RDY_TBL_SIZE 就是。 OSRdyTbl 就是一个含 8 个元素的数组。

       好了,OSRdyGrp的每一位表示一个组,如果该位为1,表示有任务用到了该组内的优先级(由于优先级不能相同,也表明有该任务,否则没有)。OSRdyTbl[x]的每一位表示该组内的每一个优先级,为1就有。例如OSRdyGrp[bit : 2] = 1;第三组内存在一个任务,也即是优先级16~238个优先级存在一个及多个。如果此时OSRdyTbl[2][bit :4] = 1; 表示第三组的第5个优先级存在,也就是数值为20的优先级存在。

二、设置OSRdyGrpOSRdyTbl

        讲了优先级列表如何表示,那么接下来就是创建一个任务时,如何将其对应的优先级加入到列表中。这是OS_TCBInit函数的关于设置OSRdyGrpOSRdyTbl的代码。注:以下源码,就不摘录16位的情况。 

     ptcb->OSTCBY    =  (INT8U)(prio >> 3);         /* Pre-compute X, Y, BitX and BitY   */
     ptcb->OSTCBBitY      = (INT8U)(1 << ptcb->OSTCBY);
     ptcb->OSTCBX         = (INT8U)(prio & 0x07);
     ptcb->OSTCBBitX      = (INT8U)(1 << ptcb->OSTCBX);
     .........

      OSRdyGrp  |= ptcb->OSTCBBitY;         /* Make task ready to run    */
      OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
      优先级prio是传人的参数,由于不会大于 64 prio 6 位值,因此 OSTCBY prio 3 位,表示组,不会大于 8 OSTCBX prio 3 , 表示一个组的偏移量。OSRdyGrp OSRdyTbl 是按位表示的,就得将数值转化为位模式。接上面的例子 prio = 20 = 0x10100 OSTCBY是prio 高3 位,为 1 , 表明该优先级落在第二组(从 0 开始), OSTCBBitY=0x10 ,也就是 bit:1 1 。同理,OSTCBX= 4 OSTCBBitX  bit :5 1 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;  就是设置 OSRdyTbl[1] bit5.

三、任务调度中判断最高优先级

        uC/OS-II每次任务调度都是运行最高优先级的任务。那么如何在所有的任务中寻找最高优先级了?前面已经介绍了,优先级信息存在OSRdyGrpOSRdyTbl中。低位代表高优先级。先检查组,由低位到高位检查,检查到后,再在该组中由低位到高位检查,第一个为1的就是最高优先级了。

       这个过程,说白了就是检查一个char型的数,所有位是1的最小的那个位。uC/OS-II中用的查表法进行的。表如下:

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 */
   };

    下面是OS_SchedNew()函数中获取最高优先级的代码:

       y  =  OSUnMapTbl[OSRdyGrp];
       OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
    y 就是查表得到的最小的那一个组的,上面已经解释过了,优先级的高 3 位表示组,所以左移 3 位到高三位。加上查表得到的该组内的偏移量,就是最高优先级的数值了。

四、结语

    该方法还是挺巧妙的。让每次查找进行几条语句就可以实现了。这个方法可以借鉴到其他地方。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入式实时多任务操作系统在软件编程上有一定的相似性。这种相似的特性,使得我们可以将个别系统的编程经验推广到更多的系统上。本文就μC/OS-II内核的任务管理和内存管理进行基本的介绍,并介绍一个通用的应用软件结构。然后,与之相对应,提供两个不同操作系统下的应用实例。 关键词:嵌入式系统 多任务 编程 引言 嵌入式系统的面向应用特性,使得大多数程序员沉陷于不同的应用。在进入新的一轮开发后,往往只有一些简单的经验可供参考。为了加快应用的开发进度,有必要研究一种统一的应用软件结构,使开发人员能够通过简单模式套用,简化大量系统研究方面的工作,以加快嵌入式开发人员对新系统的理解和使用。 操作系统μC/OS-II和ECOS(Embedded Configurable OS)是我在研发过程使用过的两个系统。这两个源码公开的系统是我们研究的基础。开发平台依次是PC机和EP7212开发板。 1 μC/OS-II内核 对于一个嵌入式系统内核,我们最关心的是:任务调度、内存管理及时间特性等。这里,只介绍与多任务编程联系最多的任务调度和内存管理。 1.1 任务调度 任务的状态有休眠、就绪及运行几种。任务调度就是遵循一定的原则,使多个任务共同使用同一处理机的过程。这一过程主要是通过对任务控制块(TCB)的管理来实现的。 当一个任务建立时,μC/OS-II系统为其所对应的OS_TCB赋值;当任务的CPU使用权被剥夺时,系统用OS_TCB来保存该任务的状态;当任务重新得到CPU使用权时,系统就可通过任务控制埠来使任务从被断处继续执行下去。 在μC/OS-II,TCB内包含如下基本项: *OSTCBStkPtr是一个指向当前任务栈顶的指针,通过允许每个任务拥有自己的栈来减小系统的内存开销; *OSTCBNextOSTCBPrev用于任务控制块的双重链接; *OSTCBDly用于任务延时或超时限制; *OSTCBStat任务的状态字,0表示就绪态; *OSTCBPrio任务优先级,值越小,优先级越高。 在μC/OS-II,还有两个与任务调度相关的结构就绪表和估级判定表。就绪表有两个变量用来存放每个任务的就绪标志。通过分组与优先级的项实现一一对应,进而确定进入就绪态的优先级最高任务任务调度算法原型: *关断; *取优先级最高的就绪任务; *若不是当前任务,则进行任务切换; *开断。 任务切换两步完成:将被挂起的任务的微处理器寄存器堆入栈,然后,将较高优先级任务的寄存器值从栈恢复到寄存器。 1.2 内存管理 在嵌入式系统,为了更高效地使用内存,除了常规的malloc()和free()外,通常提供不同的内存组织形式,以满足特殊应用的需求。ΜC/OS-II,操作系统把连续的大块内存按分区来管理,每个分区包含整数大小相同的内存块。利用这种机制,μC/OS-II对malloc()和free()进行改造,使得它们可分配和释放固定大小的内存块,并且使这两个函数的执行时间也固定下来。 ..................

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值