单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:4675|回复:0

uC/OS-III 任务就绪表学习记录

[复制链接]
ID:82083发表于 2015-6-6 02:54|显示全部楼层
    

这段时间利用上下班的时间在看 《嵌入式实时操作系统uC/OS-III》这本书,里面有很多很有意思的思想。如今看到第九章,想将之前的一些心得记录下来,本想今晚从第三章开始写笔记,敲了一段文字之后,感觉像是抄书,觉得没有太大意义。时间长了,连笔记都不知道如何写。先来个简单点的开始吧。

uC/OS-III 的任务就绪表和uC/OS-II的就绪表差别很大,简单的了很多。
拿8位的单片机,64级优先级来说。
// 优先级表
unsigned char OSPrioTbl[8] = {0};



每个元素的每bit位对应的优先级如下,优先级数值越低表示优先级越高:

OSPrioTbl[0]->bit0~bit7  优先级 0 ~ 7
OSPrioTbl[1]->bit0~bit7  优先级 8 ~ 15
OSPrioTbl[2]->bit0~bit7  优先级 16 ~ 23
OSPrioTbl[3]->bit0~bit7  优先级 24 ~ 31  
OSPrioTbl[4]->bit0~bit7  优先级 32 ~ 39  
OSPrioTbl[5]->bit0~bit7  优先级 40 ~ 47  
OSPrioTbl[6]->bit0~bit7  优先级 48 ~ 55    
OSPrioTbl[7]->bit0~bit7  优先级 56 ~ 63

当某一优先级的任务就绪,对于的bit位就会被置1,例如 优先级 7 的任务就绪,那么
OSPrioTbl[0] 的第bit7位将会被置位。

查找最高优先级的流程如下(原理实际上是计算零的个数,零的个数恰好对于优先级数):

OS_PRIO OS_PrioGetHighest()
{
     char i = 0,  char prio = 0;


     // 一次性比较 8位 由于空闲任务的存在,所以这个循环最终都会跳出而数组不会越界访问。
     while( 0 == OSPrioTbl[i++])
     {
         prio += 8;
     }
     // 这个函数实际上是计算前导零,即计算该元素的前面有几个零,再与prio相加即得到最高优先级。
     prio += CPU_CntLeadZeros(OSPrioTbl[i-1]);
     return (prio);
}    


有些CPU支持CLZ指令(即计算签导零数量),那么就可以充分利用该指令加速计算过程。

实际上,如果是在32位的单片机下需要64级优先级,那么这个算法还可以再优化成如下:

unsigned  int  OSPrioTbl[2] = {0};

OS_PRIO OS_PrioGetHighest()
{
     char i = 0,  char prio = 0;


     if( 0 != OSPrioTbl[0])
         prio = CPU_CntLeadZeros(OSPrioTbl[0]);
     else
         prio = CPU_CntLeadZeros(OSPrioTbl[1]) + 32;
    
     return (prio);
}    

上述代码并不是 uC/OS-III  的实现,只是我自己为了方便理解写了具备相同功能的代码。
书籍上所述代码如下:

OS_PRIO OS_PrioGetHighest()
{
       CPU_DATA     *p_tbl;
       OS_PRIO         prio;
       prio = (OS_PRIO)0;
       p_tbl =& OSPrioTbl[0];
     while(*p_tbl == (CPU_DATA)0)
       {
           prio += DEF_INT_CPU_NBR_BITS;  //  DEF_INT_CPU_NBR_BITS : CPU 位宽
           p_tbl ++;
       }
     prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl);
       return(prio);
}    



太晚------- 明晚继续----------







手机版|小黑屋|51黑电子论坛|51黑电子论坛6群QQ管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网