|
这段时间利用上下班的时间在看 《嵌入式实时操作系统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);
}
太晚------- 明晚继续----------
|
|