uC/OS-II系统学习笔记(5)—— uC/OS-II概述下篇

1 就绪表

1.1 OS_LOWEST_PRIO & OS_MAX_TASKS

每个任务有不同的优先级,从0到63,在OS_CFG.H里对最低的优先级有专门的宏定义OS_LOWEST_PRIO。可以通过修改这个宏定义,来修改系统任务的最低优先级,但是注意,最低优先级永远都是被空闲应用idle task占用的。另外还有一个宏定义OS_MAX_TASKS表示系统最多有几个任务。之所以在就绪表说这两个,是因为这两个对就绪表或多或少有影响。

1.2 OSRedyGrp & OSRdyTbl[OS_RDY_TBL_SIZE]

每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量OSRedyGrp和OSRdyTbl[]。在 OSRdyGrp 中,任务按优先级分组,8个任务为一组。OSRdyGrp 中的每一位表示 8 组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时, 就绪表 OSRdyTbl[]中的相应元素的相应位也置位。就绪表 OSRdyTbl[]数组的大小取决于OS_LOWEST_PR1O(见文件 OS_CFG.H)。当用户的应用程序中任务数目比较少时,减少 OS_LOWEST_PR1O 的值可以降低μC/OS-Ⅱ对RAM(数据空间)的需求量。

引用中写的是OSRedyGrp,这个缩写怎么看怎么奇怪啊,去源码看了下,应该是OSRdyGrp,和OSRdyTbl[]一样都在文件ucos_ii.h里声明的,而且就单独一对放在一起,可见联系紧密了。

OS_EXT  OS_PRIO           OSRdyGrp;                        /* Ready list group                         */
OS_EXT  OS_PRIO           OSRdyTbl[OS_RDY_TBL_SIZE];       /* Table of tasks which are ready to run    */

教程没有提,但源码里有OSRdyTbl数组的容量OS_RDY_TBL_SIZE。
这个变量也是在ucos_ii.h里定义的。和它一起被定义还有些其他表的大小。如下即定义OS_RDY_TBL_SIZE的源码。

#if OS_LOWEST_PRIO <= 63u
#define  OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 8u + 1u) /* Size of event table                         */
#define  OS_RDY_TBL_SIZE   ((OS_LOWEST_PRIO) / 8u + 1u) /* Size of ready table                         */
#else
#define  OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 16u + 1u)/* Size of event table                         */
#define  OS_RDY_TBL_SIZE   ((OS_LOWEST_PRIO) / 16u + 1u)/* Size of ready table                         */
#endif

最低任务优先级肯定是小于64的,至于另外大于64的目前我也不清楚是干什么的。两个表容量,一个就绪表容量,一个事件表容量,后者以后会介绍到的。注意到表容量,最低优先级/8+1。可见最低优先级越小,表的大小就越小,这就可以节省RAM了。至于除以8再加1,举个例子,64个优先级,最低优先级为63,63 / 8 + 1 = 8。任务是每8个为一组,所以要除以8。

说了这么多,那引文中的就能解释了。任务优先级最大有64个,那么OSRdyTbl是一个容量最大为8的数组,数组中每一个变量都是8位的,每一位都可以代表一个任务,那么总共就可以最多代表64个任务了。任务进入就绪态时,对应的位置1。那么OSRdyGrp,也是个8位的变量,可以说相当于一个目录,当 OSRdyTbl的8个任务组中,有哪一组有任务进入就绪态了,那么对应的OSRdyGrp对应的位会置1。换句话说,OSRdyGrp的每一位,是OSRdyTbl中的每一个8位变量中,8个位的逻辑或值。

1.3 使任务进入就绪态

1.3.1 教程中给任务就绪标志位置1

OSRdyGrp |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

上述两行代码,实际上就是把OSRdyGrp和OSRdyTbl对应的位置1。OSMapTbl的值如下:

Index Bit Mask(Binary)
0 00000001
1 00000010
2 00000100
3 00001000
4 00010000
5 00100000
6 01000000
7 10000000

上两行代码中,prio代表优先级。假如有64个优先级,优先级prio为50(110010),那么从0开始数就是第51个任务,8个一组就是第7组的第三个任务。

先看第一行代码,那么右移三位相当于除以8,即prio >> 3 = 6。即OSMapTbl [prio >>3] = 01000000,那么第一行代码即是把OSRdyGrp的bit6置1。

第二行代码,prio & 0x07 即 prio % 8 = 2,即OSMapTbl[prio & 0x07] = 00000100。第二行代码即OSRdyTbl[6]的bit2置1。

总的来说,就是OSRdyTbl数组中的第7组任务中的第2个任务的标志位1,以及对应的OSRdyTbl第七组的标志位置1。

看下面这幅图,X就是一组任务里的任务,Y就是总共的8组任务。

这里写图片描述

1.3.2 源码中给任务就绪标志位置1

我去翻了一下源码,发现源码里没有找到OSMapTbl这个数组。源码中是利用任务控制块OS_TCBs的OSTCBBitX和OSTCBBitY进行置位的。

OSRdyGrp               |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;

其中ptcb是OSTCBPrioTbl[OS_LOWEST_PRIO + 1u],是个任务表吧。。之前在教程也没看到,只在源码看到过。OS_LOWEST_PRIO之前说过了是最低优先级,加个1的原因是因为有优先级0,那总共任务优先级有OS_LOWEST_PRIO+1个。OSTCBPrioTbl的类型就是指向OS_TCBs的指针,之前说过的这个结构体中含有OSTCBBitY和OSTCBBitX。这样看这两个变量就充当了OSMap的角色了。

同上一节的图一样,Y表示8个任务组,X表示每个任务组的8个任务。

1.3.3 找出进入就绪态优先级最高的任务

y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
prio = (y << 3) + x;

OSUnMapTbl是一个一维数组,共256位,如下所示

INT8U  const  OSUnMapTbl[256] = {
    0u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x00 to 0x0F                   */
    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x10 to 0x1F                   */
    5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x20 to 0x2F                   */
    4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x30 to 0x3F                   */
    6u, 0u, 
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值