|
這段時間利用上下班的時間在看 《嵌入式實時操作系統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);
}
太晚------- 明晚繼續----------
|
|