實時操作系統(tǒng)mC/OS-II在AT91上的移植
摘 要:本文介紹了嵌入式實時操作系統(tǒng)mC/OS-II的工作原理,并以AT91FR40162為例,重點討論了mC/OS-II在基于ARM架構(gòu)的AT91系列中的移植。最后給出了移植結(jié)果。
關(guān)鍵詞:嵌入式實時操作系統(tǒng);AT91FR40162;mC/OS-II;移植
mC/OS-II內(nèi)核工作原理
實時嵌入式操作系統(tǒng)mC/OS-II內(nèi)核的工作原理如圖1所示。首先,在主程序中對操作系統(tǒng)進行初始化,完成mC/OS-II所有變量和數(shù)據(jù)結(jié)構(gòu)的初始化,包括任務控制塊(TCB)初始化,TCB優(yōu)先級表初始化,TCB鏈表初始化,事件控制塊(ECB)鏈表初始化以及空閑任務的創(chuàng)建等。
然后,根據(jù)應用程序的需要,用戶可以調(diào)用OSTaskCreate()函數(shù)創(chuàng)建多個任務(至少1個)。該函數(shù)為新任務建立任務堆棧(OSTaskStkInit())以及初始化任務控制塊TCB(OS_ TCBInit())。
最后,通過調(diào)用OSStart()啟動多任務調(diào)度。程序?qū)⑻骄途w表中優(yōu)先級最高的任務開始執(zhí)行。這里假設(shè)啟動多任務調(diào)度前創(chuàng)建了一個任務Task1()。
程序進入Task1()后,首先初始化時鐘和啟動時鐘節(jié)拍源開始計時。此節(jié)拍源給系統(tǒng)提供周期性的時鐘中斷信號,實現(xiàn)延時和超時確認。然后根據(jù)應用程序要求,完成該任務的基本功能。最后,調(diào)用OSTimeDly(),將自己掛起,即從就緒表中刪除。直到等待延時時間到,才將該任務恢復到就緒表中,并等待調(diào)度器的調(diào)度。
OSTimeDly()將任務掛起的同時,為其做好延時記號,然后調(diào)用OS_Sched()進行任務級的任務調(diào)度。若此時沒有任何任務進入就緒態(tài),就切換到空閑任務。
當時鐘中斷來臨時,系統(tǒng)進入中斷服務程序OSTickISR()。系統(tǒng)把當前正在執(zhí)行的任務掛起,保護現(xiàn)場,進行中斷處理OSTimeTick(),判斷有無任務延時到期,若有,則使該任務進入就緒態(tài)。最后調(diào)用OSIntExit()進行中斷級的任務調(diào)度,從而切換到優(yōu)先級最高的任務,若沒有別的任務進入就緒態(tài),則恢復現(xiàn)場繼續(xù)執(zhí)行原任務。
AT91FR40162簡介
AT91FR40162是ATMEL公司出品的一款基于ARM7TDMI內(nèi)核的AT91 16/32位微控制器,其核心為高性能的32位RISC體系結(jié)構(gòu),并具有高密度的16位指令集和極低的功耗。
ARM處理器共有7種運行模式,處理器模式可以通過軟件控制進行切換,也可以通過外部中斷或異常處理過程進行切換。在每一種處理器模式中有一組相應的寄存器組。任意時刻(也就是任意的處理器模式下),可見的寄存器包括15個通用寄存器(R0~R14)、一個或兩個狀態(tài)寄存器及程序計數(shù)器(PC)。
CPSR(當前程序狀態(tài)寄存器)可以在任何處理器模式下被訪問。它包含了條件標志位、中斷禁止位、當前處理器模式標志以及其他的一些控制和狀態(tài)位。每一種處理器模式下都有一個專用的物理狀態(tài)寄存器,稱為SPSR(備份程序狀態(tài)寄存器)。當特定的異常中斷發(fā)生時,這個寄存器用于存放CPSR的內(nèi)容。在異常中斷程序退出時,可以用SPSR中保存的值來恢復CPSR。
mC/OS-II在
AT91FR40162上的移植
本文使用的內(nèi)核是mC/OS-II v2.76,選用ADS1.2中的C編譯器。
整個移植過程主要分為兩個方面:與應用相關(guān)的mC/OS-II配置(OS_CFG.H,INCLUDES.H);與處理器相關(guān)的mC/OS-II移植(OS_CPU.H,OS_CPU_A.ASM,OS_CPU_C.C)。
OS_CPU.H
此文件中主要是定義了一些與處理器相關(guān)的常數(shù)、宏以及類型。根據(jù)ADS1.2的編譯手冊,char型變量為8位,short型為16位,int型為32位,堆棧為32位寬。另外,v2.76版本中新增加了一個全局變量OSIntCtxSwFlag,如果需要中斷級的任務切換時,就令OSIntCtxSwFlag=TRUE。
OS_CPU_C.C
在這里需要編寫兩個函數(shù):OSInitHookBegin()和OSTaskStkInit()。
OSInitHookBegin()在OSInit()中調(diào)用,用來初始化移植中出現(xiàn)的特殊變量。這里將OSIntCtxSwFlag初始化為0。
OSTaskStkInit()在OSTaskCreate()和OSTaskCreateExt()中調(diào)用,用來初始化任務的棧結(jié)構(gòu)。圖2顯示了初始化后任務棧的結(jié)構(gòu)。堆棧從上往下遞減。mC/OS-II規(guī)定任務工作在SVC模式下。另外,根據(jù)ATPCS規(guī)定,子程序間通過R0~R3傳遞參數(shù),所以參數(shù)p_arg放在R0里。
與以往的版本不同,這里OSIntCtxSw()(由OSIntExit()調(diào)用)并不完成任務的切換工作,僅將OSIntCtxSwFlag變量置1,標志需要進行任務切換。當OSIntExit()調(diào)用返回到ISR時,檢查OSIntCtxSwFlag變量,如果為1,則跳到OS_IntCtxSw()函數(shù)執(zhí)行任務切換。
OS_CPU_A.S
由于C語言不能對寄存器進行直接操作,所以必須用匯編語言編寫以下函數(shù)。
OSStartHighRdy()由OSStart()調(diào)用。該函數(shù)使就緒態(tài)任務中優(yōu)先級最高的任務開始運行。注意開始要將IRQ和FIQ中斷禁止,最后從堆棧彈出所有寄存器時,必須按照OSTaskStkInit()中相反的順序彈出。
OSCtxSw()由OSSched()調(diào)用,完成任務級的任務切換。任務級的任務切換包括將當前任務在SVC模式下的寄存器壓入任務棧中,并且將新任務的堆棧彈出到SVC模式下的寄存器中。注意必須按照OSTaskStkInit()中任務棧的結(jié)構(gòu)對任務棧進行操作。
OS_CPU_SR_Save()用于關(guān)中斷,OS_CPU_SR_Restore()用于開中斷。OS_CPU_SR_Save()將CPSR保存到R0中,通過將CPSR中I位和F位置1來禁止IRQ和FIQ中斷。OS_CPU_SR_Restore()只需將R0中保存的CPSR恢復即可。
OS_IntCtxSw()完成中斷級的任務切換。當檢查OSIntCtxSwFlag變量為1時,就調(diào)用該函數(shù)。因為OS_IntCtxSw()是在ISR中被調(diào)用的,所以所有的處理器寄存器都已經(jīng)被正確地保存到了被中斷任務的堆棧中。
mC/OS-II 要求用戶提供一個周期性的時鐘源,來實現(xiàn)時間的延遲和超時功能。這里時鐘節(jié)拍設(shè)為100次每秒,使用定時器0來完成該任務。時鐘節(jié)拍中斷OSTickISR()代碼如下,此時系統(tǒng)進入IRQ模式。
STMFD SP!, {R0-R3, R12, LR}
BL OSIntEnter
BL Tmr_TickISR_Handler
BL OSIntExit
LDR R0,addr_OSIntCtxSwFlag
LDR R1, [R0]
CMP R1, #1
BEQ OS_IntCtxSw
LDMFD SP!, {R0-R3,R12,LR}
SUBS PC, LR, #4
Tmr_TickISR_Handler是中斷處理程序,用C語言編寫。如果是其他類型的中斷,可以替換為相應的中斷處理程序。這里定時器0中斷處理程序要做的工作是首先清中斷源,即讀取TC_SR寄存器值,AIC_ICCR=0x00000010,然后告訴處理器中斷結(jié)束(向AIC_EOICR寫數(shù)據(jù)),最后調(diào)用OSTimeTick()函數(shù),對延時記號進行處理。
定時器0的設(shè)置為:WAVE模式;TC_CMR中CPCTRG=1,表示RC比較將復位計數(shù)器并開啟時鐘;TC_RC=計時時間;TC_IER=AT91C_TC_CPCS,允許RC比較中斷。
移植中要注意的問題
由于各方面的原因,移植中編寫的代碼不一定完全正確,需要進行逐步調(diào)試。調(diào)試過程中,要善于根據(jù)具體現(xiàn)象來發(fā)現(xiàn)問題所在。根據(jù)筆者的調(diào)試經(jīng)歷,總結(jié)了一些移植調(diào)試過程中要注意的問題。
(1) 對mC/OS-II的內(nèi)核機理要有充分理解??梢試L試對其內(nèi)核進行調(diào)試,這樣可以幫助自己從更深的層次來理解嵌入式實時操作系統(tǒng)。只有對mC/OS-II的內(nèi)核有了清楚地認識,才能在移植過程中發(fā)現(xiàn)問題的本質(zhì)。
(2) 對所使用的編譯器要有深刻細致的了解。由于ADS1.2的C 編譯器有很多優(yōu)化編譯選項和流水處理選項,在處理內(nèi)核編譯時很容易有沖突,所以,選擇優(yōu)化選項要慎重。加強對ADS1.2的C 編譯器的理解,可以節(jié)約代碼編寫時間。
(3) 在移植過程中,最容易出問題的就是堆棧處理。堆棧處理是操作系統(tǒng)移植的關(guān)鍵部分。先分析ARM系統(tǒng)自身在進行現(xiàn)場保護時的堆棧處理的操作,然后模擬其過程。關(guān)鍵是要將需要的寄存器都保護到。由于我們在進行任務切換的時候采用了系統(tǒng)函數(shù)來進行現(xiàn)場保護,因此在堆棧初始化的時候,就應該按照這兩個函數(shù)的操作來對任務堆棧進行初始化。
(4) 要詳細分析ARM系統(tǒng)自身處理中斷時的壓棧操作,必須將多余的信息從堆棧中清理干凈。如果對編譯器不熟悉,可以通過仔細調(diào)試中斷,來確定編譯器的具體操作。在對AT91FR40162的移植中,由于ARM處理器有7種運行模式,每種運行模式下都有自己獨立的寄存器,所以在處理中斷的過程中,要注意運行模式的切換,避免寄存器的內(nèi)容無法正確保存和恢復。
(5) 注意程序的返回地址。異常中斷發(fā)生時,程序計數(shù)器PC所指的位置對各種不同的異常中斷是不同的,所以,返回地址也是不同的。需要根據(jù)不同的中斷類型,確定不同的中斷返回地址偏移量,否則程序?qū)⑴茱w。
結(jié)語
本方案經(jīng)過測試已證明移植成功。本文是以AT91FR40162為例,說明mC/OS-II的移植,對于ARM系列的處理器,只需稍加改動就可以實現(xiàn)?!?/p>
參考文獻
1 邵貝貝等譯. 嵌入式實時操作系統(tǒng)mC/OS-II(第2版). 北京:北京航空航天大學出版社,2003
評論