歡迎您光臨本站 登入註冊首頁

提高uCOS-II在ARM上的執行效率

admin @ 2014-03-25 , reply:0

概述

   uCOS-II是一個公開源碼的搶佔式、多任務的實時操作系統,因其具有開源性、實時性強、代碼緊湊、穩定可靠等特點在各種系統中得到了廣泛應用.uCOS-II在ARM處理……

    uCOS-II是一個公開源碼的搶佔式、多任務的實時操作系統,因其具有開源性、實時性強、代碼緊湊、穩定可靠等特點在各種系統中得到了廣泛應用.uCOS-II在ARM 處理器上的移植也已經實現.ARM處理器加uCOS-II操作系統的嵌入式系統常用於工業實時控制,對執行效率特別是實時性要求較高.提高uCOS-II執行效率的關鍵是減少任務切換時間,任務切換時主要的操作是任務棧的出棧和入棧操作.由於ARM處理器在不同的處理器運行模式具有不同的堆棧,合理利用該特性並結合處理器運行模式切換特點能夠減少任務棧操作次數,減少任務切換時間.本文主要提出了兩類提高uCOS-II在ARM 上執行效率的方法:
① 減少任務棧操作次數.
② ARM處理器上的uCOS-II的可重入中斷的實現.

1 uCOS-II在ARM 上的任務切換
    uCOS-II中進行任務切換的函數是OSStartHighRdy()、OSCtxSw()、OSIntCtxSw().其中OSStartHighRdy()是在操作系統第一次啟動的時候調用的,OSCtxSw()是用戶主動調用進行任務切換,這兩個函數和中斷無關,所以和ARM 的處理器模式無關,在ARM上的實現方法和一般處理器類似.
    OSIntCtxSw()用於在中斷中進行任務切換.嵌入式實時系統響應外部事件主要通過外部中斷,在中斷中將高優先順序的任務設置為就緒狀態,然後在中斷退出時自動切換到高優先順序的任務.為了實現該功能,uCOS-II要求用戶在中斷中:
① 若需運行高優先順序任務,設置該高優先順序任務的就緒標誌位.
② 在中斷函數末尾調用OSIntExit()函數,OSIntExit()函數檢查是否有高優先順序任務就緒,有則調用OSIntCtxSw(),並切換到該高優先順序任務.
    進行任務切換時需將當前任務的狀態變數壓入堆棧(也就是當前任務棧),然後將堆棧指針指向高優先順序任務的任務棧,並彈出該高優先順序任務堆棧中的狀態變數.由於OSIntCtxSw()在中斷中調用,而進入中斷函數后一般已經保存狀態變數到堆棧,於是OSIntCtxSw()不需要進行上述壓棧操作.但是由於ARM體系結構決定了中斷和非中斷中使用不同的運行模式和堆棧,使得該問題變得複雜.例如,假設在非中斷中使用SVC模式(管理模式)和SVC堆棧;中斷中使用IRQ模式(外部中斷模式)和IRQ堆棧;任務切換時需要保存的狀態變數為PC,R12-R0,RL,CPSR,SPSR,且它們任務棧中的排列順序如圖1所示.設中斷函數為OSInt1(),則通常在ARM上實現OSInt1()和OSIntCtxSw()可用表1、表2的偽代碼表述:
 
圖1 任務棧結構圖
表1 OSInt1中斷服務程序的偽代碼
OSInt1
{
將LR_irq-4、R12至R0的內容依次入棧;
/*LR-4是中斷服務程序的返回地址即PC*//*A處*/
清除中斷標誌位; /*B處*/
調用OSIntEnter;
中斷事件處理,例如使得高優先順序任務就緒;
調用OSIntExit;
將堆棧的內容依次彈出到R0至R12、PC寄存器中,同時從SPSR_irq恢復狀態寄存器;
}
表2 OSIntCtxSw程序的偽代碼
OSIntCtxSw
{
調整堆棧指針SP到表1中”A處”; /*C處*/
保存SPSR_irq(中斷返回狀態寄存器),從堆棧中彈出R0-R12,LR_irq,並保存LR_irq(中斷返回地址);/*D處*/
強制切換到SVC模式;
將LR_irq,LR_SVC,R12-R0,CPSR_irq,SPSR_irq依次壓入堆棧; /*E處*/
調用_OSCtxSw;/*_OSCtxSw是OSCtxSW 函數去除入棧操作的部分*/
}
    從表1、表2可見在ARM 處理器上OSIntCtxSw()不僅沒有節省壓棧操作,而且還多了一步出棧操作.這是由於中斷函數OSInt1()壓入的狀態變數不在任務棧(即SVC堆棧)中而是在IRQ堆棧中,所以OSIntCtxSw()必須重新從IRQ堆棧中彈出狀態變數,並將其壓入SVC堆棧.該額外的出棧入棧操作增加了任務切換時間.這也是現有的uCOS-II在ARM 上實現的方式.

2 減少任務棧操作次數的改進
    為了防止OSIntCtxSw()中進行額外的出棧入棧操作,本文提出了兩種改進方案:
2.1 中斷中使用SVC堆棧
    假如在中斷中直接使用SVC堆棧,那麼進入中斷函數后的壓棧操作將狀態變數直接壓入了任務棧,這樣就不需要在OSIntCtxSw()中進行額外的出棧和入棧操作.實現方法是,在進入中斷函數的第一時刻,將SVC堆棧寄存器SP_svc的內容拷貝到IRQ堆棧寄存器SP_irq中.此後雖然中斷中仍然使用SP_irq寄存器,然而實際指向任務棧.本文實現該方案的偽代碼如表3、表4所示:
表3 改進1的OSInt1中斷服務程序的偽代碼
OSInt1
{
切換到SVC模式;
將 SP_SVC保存到臨時變數save_sp_svc中;
切換回IRQ模式;
將save_sp_svc的內容載入到SP_irq中;
跳轉到_OSInt1;/*這裡的_OSInt1和表1的OSInt1完全一樣*/
}
表4 改進1的OSIntCtxSw程序的偽代碼
OSIntCtxSw
{
調整堆棧指針SP_irq;
保存SPSR_irq(中斷返回狀態寄存器)到R0,保存SP_irq到R2;
強制切換到SVC模式;
複製R2(=SP_irq)到 SP_SVC;將LR_svc,R0(=SPSR_irq),R0(=CPSR),依次壓入堆棧;
調用_OSCtxSw;
}
    本文實際彙編程序實現表1、2的代碼共需45次出棧入棧操作,而實現表3、4的代碼減少到17次出棧入棧操作.

2.2 中斷中使用SVC模式
    §2.1的改進需要首先切換到SVC模式,然後切換回IRQ模式(如表3所示),最後在OSIntCtxSw()中又要切換到svc模式(如表4所示),假如在IRQ中直接使用SVC模式,即可以同樣使用SVC堆棧達到§2.1改進的效果,同時減少了在SVC和IRQ之間來回切換的麻煩.本文實現在中斷中使用SVC模式的偽代碼如表5、6所示:
表5 改進2的OSInt1中斷服務程序的偽代碼
OSInt1
{
保存lr-4到臨時變數INT_RET_ADDR;
將SPSR_irq(返回后的CPSR內容)保存到INT_RET_CPSR;
強制切換到SVC模式;
將INT_RET_ADDR,R12-0,LR_SVC,INT_RET_CPSR依次入棧;
清除中斷標誌位; /*F處*/
調用OSIntEnter;
中斷事件處理,例如使得高優先順序任務就緒;
調用OSIntExit;
從堆棧中彈出INT_RET_CPSR,寫入CPSR;
表6 改進2的OSIntCtxSw程序的偽代碼
OSIntCtxSw
{
調整堆棧指針SP;
將SPSP_SVC壓入堆棧;
調用_OSCtxSw;
}
    實際代碼中該方案的出棧入棧次數也是17次.但該方法要求在IRQ模式切換到SVC模式之前保存IRQ模式下的一些變數(如SPSR_irq、LR_irq)這增加額外的一些操作.§2.3的實驗表明該改進的效率沒有§2.1的改進高效,但是該改進為§3的可重入中斷做好了準備.

2.3 任務切換時間的比較
    為驗證改進方法對減少任務切換時間的效果,本文設計如下實驗:
    讓uCOS-II的一個任務Task1等待(用OSSemPend函數實現)信號量mysem,此時Task1掛起.當鍵盤按下時進入OSInt1中斷函數,在該中斷中發送(使用OSSemPost函數)mysem信號量,使得Task1進入就緒狀態.當OSInt1退出時切換到Task1任務.對於三種實現方法:通常的任務切換方法、中斷中使用SVC堆棧的任務切換方法和中斷中使用SVC模式的任務切換方法,分別測試鍵盤按下到切換到Task1的時間差.為此在OSInt1()中斷函數開始處獲取定時器初始值t1,在進入Task1以後讀取定時器當前值t2,則t=|t1-t2|就是想要的時間差.
    對三種實現方法分別進行43次實驗,測得的t如圖2所示.實驗時,定時器以PCLK/2(PCI K設置為50700000)的速率減法計數.
 
圖2 三種方法的任務切換時間比較
    從圖2可知,兩種改進的方法比通常方法需要更少的任務切換時間;§2.2的方法比§2.1的方法需要更多的任務切換時間與原先的分析符合.
    從改善的性能上,這裡可以從計數值的相對值來看,§2.1的方法比通常方法約改善了61/1403=4.3% ,但是必須考慮到時間t包含了中斷產生到切換到Task1的整個代碼的執行時間,其中包含了OSSemPost()、OSIntExit()等較複雜函數,所以可以說該改進是有效的.

3 可重入中斷對任務切換時間的影響
3.1 uCOS-II對可重入中斷的支持
    uCOS-II本身支持可重入中斷,它在OSIntExit中使用IntNesting變數表示了中斷嵌套的層數,uCOS-II只在退出最後一層嵌套時才進行任務的切換,這可以通過檢查IntNesting變數來獲知.
    中斷的嵌套增加了任務切換的實時性,以例子說明如下:假設有兩個任務:taskTimer和taskKey,taskTimer由定時器觸發;taskKey由外部中斷源(例如按鍵)觸發,taskKey的優先順序比taskTimer高.如圖3所示,當外部中斷髮生時,若處理器正好處於定時中斷中.中斷可重入時,系統馬上進入外部中斷服務程序讓Task_Key就緒,並在退出最後一層中斷(定時中斷)時,切換到Task_Key;中斷不可重入時,需要首先切換到低優先順序任務TaskTimer,然後再次進入中斷,然後才切換到高優先順序任務Task_Key.
    由此可見中斷可重入時,在有多個優先順序的任務共存的情況下,高優先順序任務的實時響應時間更短了.
 
圖3 中斷可以重入和不可重入時任務切換的差別

3.2 ARM處理器對可重入中斷的支持
    在默認情況下ARM處理器不支持可重入中斷.當ARM進入IRQ中斷以後自動關閉IRQ使能標誌,禁止IRQ中斷的嵌套.為了支持IRQ的可重入,需要:
(1)在重新使能IRQ中斷之前保存必要的寄存器.
(2)在重新使能IRQ之前使用SVC模式,並在中斷退出以前一直保持SVC模式.

3.3 在Arm上實現uCOS-II可重入中斷
    §2.2的方法實際已具備可重入中斷的要求,只要在表5的“F處”之後重新使能IRQ中斷標誌位即可.在重新使能IRQ中斷之前需要注意的是首先需要清除中斷源的中斷位,防止重新使能IRQ中斷標誌位后同一中斷源重複中斷.

4 結論
    本文提出了兩點提高uCOS-II在ARM 上執行效率的方法:減少任務棧操作次數和實現可重入中斷.在中斷中直接使用SVC堆棧和在中斷中直接使用SVC模式的改進減少了額外的出棧入棧操作,減少了任務切換時間,實驗結果證實該改進的有效性.可重入中斷在ARM處理器的uCOS-II上的實現,使得高優先順序任務的實時響應時間更短了.兩點提高效率的方法不僅有助於提高ARM 上uCOS-II的執行效率.同時也對在ARM上實現高實時的嵌入式操作系統有借鑒意義.


[admin via 研發互助社區 ] 提高uCOS-II在ARM上的執行效率已經有2260次圍觀

http://cocdig.com/docs/show-post-42126.html