1. 程式人生 > >理解uC/OS的任務切換和任務就緒表、就緒組

理解uC/OS的任務切換和任務就緒表、就緒組

uC/OS的任務切換

1、每個任務都建立了一個任務執行的堆疊,每次任務切換時找到就緒的優先順序最高的任務,將堆疊指標指向該任務,然後就恢復該任務對CPU的佔有。

2、uC/OS的任務切換分為兩種:

一種是非中斷情況下,當任務被阻塞、建立、刪除時,需要呼叫任務切換函式OS_Schedule,儲存執行的上下文(執行地址和CPU暫存器),壓到堆疊裡面去。需要注意的是,因為當前還在被換出的任務中執行,因此該任務返回後將執行任務切換的最後一句(實際上就是我們在呼叫函式時的情況一樣,函式執行變數的進棧和出棧),然後返回恢復任務執行地址。

一種是中斷處理的任務切換函式,中斷產生後,會自動將一部分暫存器值壓入到堆疊,不需要去儲存環境。直接將堆疊指標指向優先順序最高的任務堆疊的棧頂,然後依次彈出各CPU暫存器的值到CPU暫存器進行環境恢復,最後彈出任務地址和任務引數,轉到任務地址去執行。

任務就緒表、就緒組

這兩張查詢表表示的是查詢的優先順序任務最高就緒,用空間換時間的方法實現的。這裡在uC/OS管理了64個任務,在版本2.82以後擴充套件至255個任務。

就緒組是一個無符號字元型別,就緒表是無符號字元陣列型別,大小為8。是通過結合就緒表和就緒組字元的位來實現對優先順序的查詢。

1、根據任務優先順序來給就緒組和就緒表賦值

如優先順序23=8*2+7,23/8相當於表示在哪個就緒組的哪個位置置1,這裡是第二組,所以用OSRdyGrp|=OSMapTbl[prio>>3],這裡的或操作就是通過查詢OSMapTbl給就緒組置1。OSMapTbl[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}對映表。

同時用OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07]給就緒表賦值,這裡是prio&0x07是相當於取餘的操作,比如這裡的23取餘的操作是7。後面的操作和上類似。

2、根據就緒組和就緒表來找到最低優先順序任務賦值

y=OSUnMapTbl[OSRdyGrp];本來可能有幾個任務就緒了,要找到最低的優先順序就緒組需要計算,這裡是通過查表的方式來實現的,比如之前我們的OSRdyGrp的值為10000100這裡第八位最高位為1是因為必須有空閒任務一直執行,而第三位為1是之前我們優先順序23的賦值,這個值換成十進位制為132,通過查表OSUnMapTbl得到為2。

如果不查表的話,呼叫這樣一個函式:

INTU8 fun(INTU8 n)

{

INTU8  count=0,

while(n!=0)

{

count++;

if(n&1==1)

{

return count;

}

n<<=1;

}

}

count就是就緒組最低位,計算的方式浪費時間。

同時OSPrioHighRdy=(INT8U)((y<<3)+OSUnMapTbl[OSRdyTbl[y]]),這裡的跟上面也是同樣的道理查詢就緒表裡面位最低的優先順序,再和之前組裡查詢的數相加就得到最低或準備好的優先順序的任務了。