uC/OS-II在ARM微處理器上的移植

uC/OS-IIARM微處理器上的移植<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

引言:在開發嵌入式系統時,一般選擇基於ARM uC/OS-II 的嵌入式開發平臺,因爲ARM 微處理器具有處理速度快、超低功耗、價格低廉、應用前景廣泛等優點。uC/OS - II 是由Jean J . Labrosse 先生編寫的完整的可移植、固化、裁剪的佔先式實時多任務內核。uC/OS - II 結構簡單,容易移植,適於學習。

   1.硬件平臺要求

要使uC/OS – II可以正常工作,處理器必須滿足如下工作要求:

1.  處理器的C編譯器能產生可重入代碼。

2.  在程序中可以打開或者關閉中斷。

3.  處理器支持中斷,並且能產生中斷(通常10HZ~100HZ之間)。

4.  處理器支持能夠容納一定數據的硬件堆棧。

5.  處理器有將堆棧指針和其他CPU寄存器存儲和讀出到堆棧的指令。

ARM的大多數處理器完全滿足上述要求。

下面是uC/OS的文件結構圖:

 

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

應用軟件

核心代碼

Os_core.c  OS_FLAG.C

Os_task.c  OS_MUTEX.C

Os_mem.c

Os_q.c

Os_sem.c

Os_time.c

Os_ii.c      Os_ii.h

Os_mbox.c

 

設置代碼

(應用相關)

Os_cfg.h

Includes.h

移植代碼(處理器相關)

OS_CPU.H ,  OS_CPU_A.ASM ,  OS_CPU.C

<?xml:namespace prefix = w ns = "urn:schemas-microsoft-com:office:word" />

2. 移植需要修改的部分

數據類型:BOOLEA INT8U, INT8S, INT16U, INT16S, INT32U, INT32S, FP32, FP64, OS_STK, OS_CPU_SR, 這些都在OS_CPU.H中。

宏與宏定義:OS_STK_GROWTHOS_ENTER_CRITICAL() OS_EXIT_CRITICAL() 它們都在OS_CPU.H中。

彙編函數:OSStartHighRdy(),OSCtxSw(),OSIntCtxSw(),OSTickISR(), 這三個在OS_CPU_A.ASM中,它們的修改相對比較複雜。

OS_CPU_C.C 中要修改的C語言函數:OSTaskStkInit(), OSInitHookBegin (void), OSInitHookEnd (void), OSTaskCreateHook (OS_TCB *ptcb), OSTaskDelHook (OS_TCB *ptcb),  OSTaskStatHook (void), OSTaskSwHook (void), OSTCBInitHook (OS_TCB *ptcb), OSTimeTickHook (void), OSTaskIdleHook (void)。這10個函數都修改只有OSTaskStkInit()的修改比較複雜,其他的函數很多都是空的。

3 與處理器和編譯器相關的代碼

1)與編譯器相關的數據類型,放在OS_CPU.H

比如typedef unsigned char  INT8U;  // Unsigned 8 bit quantity   

2) OS_ENTER_CRITICAL() OS_EXIT_CRITICAL()

#define  OS_CRITICAL_METHOD    1//修改這一句就可以修改兩個以上兩個函數的定義?                

3OS_STK_GROWTH

定義堆棧的增長方向:#define  OS_STK_GROWTH       1  //從下往上

同理#define  OS_STK_GROWTH        0   //從上往下

4. OS_CPU_C. C及其6個用 C語言編寫的函數  

1OSTaskStkInint()用於任務棧的初始化,在創建任務和異常的時候都會被調用到,

2OSTaskCreateHook (OS_TCB *ptcb)在創建任務和異常的時候都會被調用到,該函數調用時中斷是被禁止的,所以要縮短代碼,以縮短中斷的相應時間。當它被調用時,回收到指向已建立任務的OS_TCB指針。

3OSTaskDelHook (OS_TCB *ptcb)收到被刪除任務的OS_TCB指針。

4OSTaskSwHook ()任務切換是調用到,這個函數也要注意縮短響應時間。

5OSTaskStatHook (void)每秒鐘都會被OSTasKStat()調用一次。用戶可用它來擴展統計功能。

6OSTimeTickHook()在每個時鐘節拍都會被OSTaskTick()調用。實際上是在節拍被uC/OS-II真正處理,並通知用戶的移植實例或應用程序之前別調用的。

5個可以不用加代碼只有OS_CFG.H中的OS_CPU_HOOKS_EN被置爲1時纔會產生這些函數的代碼。

5. 用彙編語言編寫的4個處理器相關的函數(OS_CPU_A.ASM

OS_CPU_A. S 文件的移植需要對處理器的寄存器進行操作,所以必須用彙編語言來編寫。這個文件的實現集中體現了所要移植到處理器的體系結構和uC/OS-II 的移植原理。它包括4 個子函數:OSStartHighRdy() OSCtxSw() OSIntCtxSw() OSTick2ISR() 其中難點在於OSIntCtxSw() OSTickISR() 函數的實現,因爲這兩個函數的實現與移植者的移植思路以及相關硬件定時器、中斷寄存器的設置有關。在實際的移植工作中,這兩處也是比較容易出錯的地方。

  OSIntCtxSw( ) 函數由OSIntExit ( ) 函數調用,而OSIntExit () 函數又由OSTickISR() 調用。OSIntCtxSw()函數最重要的作用就是它完成在中斷ISR 中直接進行任務切換,從而提高了實時響應的速度。它發生的時機是在ISR 執行到OSIntExit ( ) 時,如果發現有高優先級的任務因爲等待time_tick 的到來獲得了執行。uC/OS-II ARM系統上的移植與實現的條件,就可以馬上被調度執行,而不用返回被中斷的那個任務之後再進行任務切換。實現OSIntCtxSw() 的方法大致也有兩種情況:一是通過調整SP 堆棧指針的方法,根據所用的編譯器對於函數嵌套的處理,通過精確計算出所需要調整的SP 位置來使得進入中斷時所作的保護現場的工作可以被重用。 二是設置需要切換標誌位的方法,在OSIntCtxSw( ) 裏面不發生切換,而是設置一個需要切換的標誌,等函數嵌套從進入OSIntExit ( ) = > OS ENTER CRITI2CAL() = > OSIntCtxSw( ) = > OS EXIT CRITICAL() = > OSIntExit ( ) 退出後,再根據標誌位來判斷是否需要進行中斷級的任務切換。

其次是對OSTickISR() 修改,OSTickISR() 首先在被中斷任務堆棧中保存CPU 寄存器的值,然後調用OSIntEnter () 。隨後調用OSTimeTick() ,檢查所有處於延時等待狀態的任務,判斷是否有延時結束就緒的任務。最後調用OSIntExit ( ) 。如果在中斷中(或其他嵌套的中斷) 有更高優先級的任務就緒,並且當前中斷爲中斷嵌套的最後一層,OSIntExit ( ) 將進行任務調度。如果進行了任務調度,OSIntExit () 將不再返回調用者,而是用新任務的堆棧中的寄存器數值恢復CPU 現場,然後實現任務切換。如果當前中斷不是中斷嵌套的最後一層,或中斷中沒有改變任務的就緒狀態,OSIntExit ( ) 將返回調用者OSTickISR ( ) OSTickISR() 返回被中斷的任務。 最後就是退出臨界區和進入臨界區函數。 進入臨界區時,必須關閉中斷,用ARMDisableInt () 函數實現。在退出臨界區的時候恢復原來的中斷狀態,通過ARMEnableInt ( ) 函數來實現。 至於進行任務級上下文切換,則是由彙編子程序OSCtxSw 實現。

應用軟件

核心代碼

Os_core.c  OS_FLAG.C

Os_task.c  OS_MUTEX.C

Os_mem.c

Os_q.c

Os_sem.c

Os_time.c

Os_ii.c      Os_ii.h

Os_mbox.c

 

設置代碼

(應用相關)

Os_cfg.h

Includes.h

移植代碼(處理器相關)

OS_CPU.H ,  OS_CPU_A.ASM ,  OS_CPU.C

[參考文章]

《嵌入式實時操作系統uC/OS-II》(第二版) Jean J.Labrosse 邵貝貝 等譯

uC/OS-IIARM系統上的移植與實現》作者:李學橋、劉放美

《嵌入式系統設計與實例開發——基於ARM微處理器與uC/OS-II實時操作系統》(第二版)   王田苗 主編

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章