隨著信息社會的發(fā)展,,信息家電,、智能儀表和智能安保系統(tǒng)等產(chǎn)品已經(jīng)越來越多地出現(xiàn)在人們的生活中??梢灶A見,,為了滿足人們對舒適,、便捷,、安全生活環(huán)境的需求,,嵌入式信息產(chǎn)品的設計、應用將得到快速發(fā)展,。
單片機作為嵌入式信息產(chǎn)品的一個重要應用方面,,其使用、設計面臨著全新的挑戰(zhàn),。一方面,,人們對嵌入式產(chǎn)品的要求越來越高,穩(wěn)定可靠,、功能豐富,、物美價廉的信息產(chǎn)品將成為人們的首選。另一方面,,隨著微電子工藝水平的發(fā)展,,單片機處理器的能力不斷提高,從最初的8位單片機到16位,,進而32位單片機,,功能越來越強大,執(zhí)行速度越來越快,,集成度,、精確度也越來越高,應用領域進一步拓寬,??梢哉f,單片機芯片的性能已經(jīng)能夠滿足現(xiàn)代人們對嵌入式信息產(chǎn)品的更高要求,。為了能將二者有效地結(jié)合起來,,嵌入式RTOS的軟件設計方法也取代了以前的前后臺(超循環(huán))設計方法,越來越受到重視和應用,。
正如分時操作系統(tǒng)中Linux的出現(xiàn)打破了Windows一統(tǒng)天下的局面一樣,,由美國Jean J.Labrosse先生設計和編寫的uC/OS-II(Micro C OS 2)的出現(xiàn)也給國內(nèi)的RTOS應用者帶來了驚喜。uC/OS-II的最大優(yōu)點與Linux相同,,即其源代碼全部公開,,使人們在應用它的同時能清楚地了解內(nèi)部的實現(xiàn)細節(jié),并且能夠根據(jù)自己的需求進行移植和修改,。特別重要的是uC/OS-II經(jīng)過8年的發(fā)展,,已經(jīng)成功地在多個行業(yè)得到應用,保證了實用性和可靠性,。它的出現(xiàn)改變了以前人們在使用RTOS時的態(tài)度,,減少了經(jīng)濟上的顧慮,對于國內(nèi)RTOS的研究、推廣,、應用將起到重要的推動作用,。uC/OS-II采用微內(nèi)核設計,使用C語言編寫,,追求靈活性,,可配置、可裁剪,、可擴充,、移植性強。需要強調(diào)的是 uC/OS-II嚴格采用優(yōu)先級搶占式調(diào)度方案,。在創(chuàng)建任務時,,根據(jù)任務的重要性給每個任務分配不同的優(yōu)先級。任務調(diào)度時,,先執(zhí)行高優(yōu)先級的任務,,然后按照優(yōu)先級由高到低執(zhí)行任務。如果在某個任務執(zhí)行中,,激發(fā)了一個優(yōu)先級更高的任務,,那么在該任務執(zhí)行結(jié)束后,將由任務調(diào)度器調(diào)度去執(zhí)行所激發(fā)的高優(yōu)先級任務,,而不是順序執(zhí)行,。
下面就uC/OS-II在TI公司生產(chǎn)的MSP430F148芯片上的移植和應用來探討在單片機上實現(xiàn)RTOS可能遇到的一些問題。
1 MSP430系列單片機簡介
MSP430系列單片機是由TI公司開發(fā)的16位單片機,。其突出特點是超低功耗,,非常適合于各種功率要求低的場合。有多個系列和型號,,分別由一些基本功能模塊按不同的應用目標組合而成,。典型應用是流量計、智能儀表,、醫(yī)療設備和保安系統(tǒng)等方面,。由于其較高的性能價格比,應用已日趨廣泛,。
MSP430F148是TI新近推出的MSP430F14x/13x系列單片機中的一款,。相對MSP430系列的其它芯片,主要特點如下:
超低功耗,。由于內(nèi)置了功耗極低的快速閃存,,因此,MSP430F14x/13x系列在待機模式下所消耗的電能還少于電池未使用時的自然損耗,。在正常的工作狀態(tài)下,,如果工作電壓為2.2 V,其典型消耗電流僅為250uA/MIPS,而待機模式下工作電流降至僅1uA以下,。
執(zhí)行速度快,。MSP430F13x/14x系列的工作電壓范圍為1.8~3.6 V,性能可達8 MIPS,。
存儲容量大,。MSP430F148片內(nèi)內(nèi)置了48 KB Flash ROM和2 KB RAM,。RAM空間是MSP430系列中最大的,,基本符合運行RTOS的需要。
高性能A/D,。包含了1個具有8個外部通道的12位高性能A/D轉(zhuǎn)換器,。利用芯片內(nèi)置的自動掃描功能,A/D轉(zhuǎn)換器可以不需要中央處理器的協(xié)助而獨立工作,。
集成度高,。該器件還包括1個獨立的看門狗、2個脈寬調(diào)制定時器(PWM),、1個比較器,、2個USART口以及48個輸入/輸出引腳等部件。
在線支持強,。MSP430F13x/14x系列均可由MSP-FET430P140閃速仿真工具(FET)提供支持,。該FET是一種完整的集成開發(fā)環(huán)境,包括源代碼級調(diào)試器,、仿真器,、匯編/連接器、C編譯器,、2種評估芯片,、目標板、JTAG接口以及編程單元等,。
由以上介紹可以看出,,MSP430F148屬于一種中低端的單片機,只具備運行RTOS的基本條件,,所以在它上面運行RTOS所遇見的一些問題,,對于一般的單片機而言是具有代表性的。
2 中斷堆棧的結(jié)構設計
在uC/OS-II中,,任務切換分為任務級切換和中斷級切換,。其中任務級切換是通過發(fā)軟中斷指令或依靠處理器執(zhí)行陷阱指令來完成的。軟中斷指令會強制將一些處理器寄存器保存到當前任務的堆棧中,,并執(zhí)行任務調(diào)度,。其目的是使處于就緒態(tài)的任務的堆棧結(jié)構看起來就像剛發(fā)生過中斷并將全部寄存器保存在堆棧的情形一樣。如MCS-5l以及x86芯片都有類似的指令,但問題出在有一些單片機芯片中沒有軟中斷指令,,并且在發(fā)生中斷時保存寄存器的情況根據(jù)單片機芯片和所使用的編譯器的不同而有很大區(qū)別,。
MSP430F148中就沒有軟中斷指令,所使用的IAR編譯器在發(fā)生中斷時也不保存所有的寄存器,,而是只保存幾個在中斷中使用到的寄存器,。所有這些都是不符合uC/OS-II的移植條件的。我們的解決方法是根據(jù)具體情況來自己定義一個中斷結(jié)構,,不論是在任務級調(diào)度還是中斷發(fā)生或調(diào)度以及任務堆棧的初始化時,,都要按照這個結(jié)構來執(zhí)行。代價是必須對所編寫的中斷程序的匯編代碼進行人工修改,,使之符合這個中斷結(jié)構,。
為設計一個符合要求的中斷堆棧結(jié)構,首先必須清楚所使用的單片機在發(fā)生中斷時執(zhí)行了哪些操作,,即向堆棧中保存了哪些寄存器以及它們的順序,。當MSP430單片機發(fā)生中斷時,只進行2條基本操作,,先將SR(狀態(tài)寄存器)壓入堆棧中保存,,然后將中斷發(fā)生時要執(zhí)行的下一條指令的PC值壓入堆棧保存。其次,,要清楚所使用的C編譯器在編譯C語言編寫的中斷程序時,,進行了哪些默認的操作。通過對所使用的IAR V2.13編譯器編譯產(chǎn)生的匯編程序進行分析,,可以發(fā)現(xiàn),,除了以上的2條基本操作以外,在中斷程序的開頭,,還自動保存了 R12~R15四個寄存器,,余下的R4~Rll八個寄存器中只保存在中斷程序中用到的個別寄存器,而不是全部保存,。但在RTOS中必須保存所有的寄存器,,這樣才能正確保存該任務的狀態(tài)。通過以上分析,,我們定義了MSP430運行uC/OS-II時的中斷堆棧結(jié)構,,如圖1所示。
3 如何保證單片機的低功耗特性
單片機在嵌入式方面的應用都非常強調(diào)單片機的超低功耗特性,。MSP430系列的特點也在于此,。如果由于運行RTOS而破壞了單片機的低功耗特性是得不償失的。一般的單片機都規(guī)定了幾種不同功耗的工作模式,,可以根據(jù)具體的需求來選擇,。不同工作模式是通過讀寫1個或1組寄存器來控制CPU,、時鐘、晶振以及外圍設備的運行來實現(xiàn)的,。
MSP430系列單片機有6種不同的工作模式,,都是通過對狀態(tài)寄存器SR的讀寫來實現(xiàn)的。在RTOS中,,由于每個任務都可以分別保存自己的狀態(tài),,包括狀態(tài)寄存器,所以在實現(xiàn)低功耗工作模式時更加靈活方便,。首先,,在設計每個任務時,都可以根據(jù)任務的具體要求定義它的工作模式,。其次,,在整個系統(tǒng)設計中,,設計一個最低優(yōu)先級的任務,,其作用就是使系統(tǒng)進入特定的低功耗工作模式。這樣,,在其它任務都運行完畢后,,系統(tǒng)會調(diào)用這個任務使整個系統(tǒng)進入低功耗工作模式。當其它任務又恢復運行時(如延時結(jié)束),,會自動進入其特定的工作狀態(tài),,以達到降低功耗的目的。
4 如何減少RTOS在運行中占用的RAM空間
影響RTOS在單片機上應用的主要原因是由于在單片機上運行RTOS需要占用一定的系統(tǒng)資源,,如系統(tǒng)時鐘,、RAM、FLASH或ROM等,,從而減少了應用系統(tǒng)對資源的利用,。特別是對RAM的占用。一般而言,,單片機上的內(nèi)部RAM數(shù)量都很少(如MSP430F148是整個MSP430中RAM最多的,,也只有2 KB),雖然可以通過外部擴展來增加RAM數(shù)量,,但這樣不僅增加了設計的難度和產(chǎn)品成本,,而且有時還使系統(tǒng)應用無法進行擴展。所以,,最好的方法是能夠充分利用單片機的內(nèi)部RAM來運行RTOS,。
通過分析uC/OS-II對RAM的使用情況可知,占用RAM空間最多的原因,,是由于在設計uC/OS-II時,,要給每個任務都分配一個單獨的任務堆棧,。特別在單片機的硬件設計沒有將中斷堆棧與任務堆棧分開時,計算任務堆棧的大小時不僅要計算任務中變量和函數(shù)嵌套所使用的RAM大小,,還必須計算該任務在運行時發(fā)生中斷和中斷嵌套所需要的RAM空間的大小,。由于每一個任務均需預留中斷和中斷嵌套所需要的RAM空間的大小,所以使得大量RAM空間被浪費,。最直接的解決方法就是利用軟件來將任務堆棧和中斷堆棧分離,,使得在計算任務堆棧的大小時,只需計算任務本身所需的RAM空間大小,,從而提高了RAM的使用效率,,增加了更多的應用任務。
所謂將中斷堆棧與任務堆棧分離,,就是在內(nèi)存中專門開辟出一塊區(qū)域作為中斷堆棧使用,,任何一個任務運行時發(fā)生中斷都只使用它。設計的原則:一是要盡量將中斷任務與普通任務分開,;二是模擬的中斷堆棧指針必須一直保持在中斷堆棧的頂部,,即中斷時中斷堆棧指針要時刻保持與SP的同步變化。
為了達到這個目的,,單片機芯片必須具備以下2個條件,。
首先,單片機芯片必須有一個通用寄存器和相應的指令能夠模仿堆棧指針SP的功能,,即能實現(xiàn)軟堆棧,。在MSP430系列單片機中有以下指令可以仿真SP的功能(把R4作為中斷堆棧指針使用):
MOV @R4+,SP ,;將R4所指向地址中的內(nèi)容存入SP,;中,同時R4中內(nèi)容加2
MOV SP,,0(R4) ,;將SP中的內(nèi)容存入R4所指向的地址中
MOV @R4+,PC ,;將R4所指向地址中的內(nèi)容存入PC,;中,同時R4中內(nèi)容加2
其次,,作為模擬中斷堆棧指針的寄存器R4,,必須在中斷之外的任何情況下不被使用。因為,,此時的R4必須時刻保持在中斷堆棧的頂部,,如果改變它的值,就會改變中斷堆棧的結(jié)構,。一般這個要求是由所使用的編譯器來保證的,,在我們所使用的IAR編譯器中,,有一個選項可以避免使用R4和/或R5。
具體設計時,,我們在uC/OS-II每個任務的TCB(任務控制塊)結(jié)構中加入以下幾項:
TSP--任務堆棧指針,。發(fā)生中斷后,指向該任務的任務堆棧的頂部,。
ISP--中斷堆棧指針,。如果在中斷中發(fā)生任務切換,指向該任務在中斷堆棧所保存狀態(tài)的頂部,。
FromInt標志--是否來自中斷標志,。用來判斷該任務的狀態(tài)是保存在中斷堆棧中(為1),還是保存在任務堆棧中(為0),。
下面假設一個普通任務1在執(zhí)行過程發(fā)生中斷,,對它在中斷執(zhí)行過程中可能出現(xiàn)的幾種情況進行分析。
(1)在普通任務1運行時引發(fā)中斷,,在中斷中沒有激活更高優(yōu)先級的任務,,而是正常結(jié)束中斷,繼續(xù)執(zhí)行任務1,,如圖2所示,。
開始中斷:將在中斷發(fā)生時保存在當前任務堆棧的SR和PC移到中斷堆棧中保存,,同時 SP回到中斷前的位置并將它保存到該任務TCB中的TSP中(這是為了在中斷結(jié)束后,,保持任務堆棧的連續(xù)性),然后將SP指到目前中斷堆棧的頂部,,按照自定義堆棧結(jié)構的順序依次將所有寄存器都保存到中斷堆棧中,。保存的過程中R4必須與SP保持同步變化,同時將FromInt標志置l,。
退出中斷:由于沒有激活更高優(yōu)先級的任務,,所以在中斷任務完成后,將按正常的順序退出中斷,,即將保存在中斷堆棧中的寄存器推出堆棧,,將FromInt標志置0,SP重新指向該任務的任務堆棧中,,最后,,將PC指針指向中斷前的返回地址,繼續(xù)程序運行,。
(2)在普通任務1運行時引發(fā)中斷,,在中斷中激活更高優(yōu)先級的任務2。中斷結(jié)束時由任務調(diào)度器調(diào)度去執(zhí)行更高優(yōu)先級的任務2,,沒有返回普通任務1,。
當執(zhí)行任務2時,,任務調(diào)度器會將任務2保存在自己任務堆棧中的狀態(tài)恢復并執(zhí)行任務2。執(zhí)行完后,,如果沒有激活更高優(yōu)先級的任務,,那么按照優(yōu)先級高低的原則,調(diào)度器將調(diào)度執(zhí)行任務1,。通過判斷任務1的TCB中的FromInt標志,,可以知道任務1的狀態(tài)是保存在任務堆棧中還是中斷堆棧中,從而可以將其狀態(tài)恢復,,繼續(xù)運行,。
(3)在普通任務1運行時引發(fā)中斷,在中斷中激活更高優(yōu)先級的任務2,,執(zhí)行任務2時又發(fā)生中斷,。
由于uC/OS-II是嚴格按照優(yōu)先級搶占式原則進行任務調(diào)度的,所以將任務狀態(tài)保存在中斷堆棧頂部的任務的優(yōu)先級一定比狀態(tài)保存在它下面的任務的優(yōu)先級高,。在執(zhí)行時,,是由中斷堆棧的頂部向底部順序執(zhí)行。在這種假設中,,一定先執(zhí)行任務2,,然后執(zhí)行任務1,如圖3所示,。
(4)在普通任務1運行時引發(fā)中斷,,在中斷中激活更高優(yōu)先級的任務2。在執(zhí)行任務2時又發(fā)生中斷,,在中斷過程中任務2由于等待信號量而被掛起,。
這種情況在系統(tǒng)最初設計時已經(jīng)被禁止,在中斷中不允許使用信號量將中斷掛起,。
(5) 在普通任務1運行時引發(fā)中斷,,在中斷中激活更高優(yōu)先級的任務2。在執(zhí)行任務2時又發(fā)生中斷,,中斷中激活更高優(yōu)先級的任務3,。中斷結(jié)束時由任務調(diào)度器調(diào)度去執(zhí)行更高優(yōu)先級的任務3。
這種情況與討論的情況2是一樣的,。
(6)高優(yōu)先級任務2被更高優(yōu)先級的任務3中止,,在任務3運行完后,任務調(diào)度器將直接調(diào)度執(zhí)行任務1(按照優(yōu)先級調(diào)度),。
由于各個任務的ISP和TSP在任務切換前都已經(jīng)保存在該任務的TCB中,,任務1的堆棧指針和R4可以回到該任務在其任務堆棧和中斷堆棧的正確的位置。
任務2被中止包括兩種情況,。一是任務2被別的任務刪除,,此時任務2在中斷堆棧中占用的空間會自動釋放,。二是任務2被別的任務掛起,此時應在將程序掛起的函數(shù)TaskSuspend()中添加一段代碼,,將其保存在中斷堆棧中的狀態(tài)移到自己的任務堆棧中,,同時將其TCB中的FromInt標志設為0。這樣,,在任務2解除掛起后,,會去任務堆棧中恢復其狀態(tài)。
(7)中斷中發(fā)生中斷嵌套,。
發(fā)生中斷嵌套時,,要按照中斷嵌套的機制進行處理。首先,,在中斷嵌套中,,不允許進行任務調(diào)度,這樣,,即使在中斷嵌套中激發(fā)了更高優(yōu)先級的任務,,也必須等到最后中斷退出前才進行調(diào)度執(zhí)行。這一點是由uC/OS-II系統(tǒng)設計保證的,。其次,,保存寄存器和函數(shù)調(diào)用所占用的RAM字節(jié)全部在中斷嵌套中。在退出中斷嵌套時,,不必將TCB中的FromInt標志復位,。
5 程序設計流程
(1)中斷程序結(jié)構和設計流程,如圖4所示,。
(2)普通任務間的任務切換程序流程,,如圖5所示。
(3)在中斷中任務切換程序流程,,如圖6所示。
我們已經(jīng)在MSP430F148上成功運行了uC/OS-II,,在RAM只有2 KB的情況下,,能夠運行16個任務,可以滿足一些復雜的應用需求,,大大擴展了MSP430F148的應用范圍,,并且提高了應用系統(tǒng)的實時性。為了驗證實際效果,,在此基礎上,,我們將幾個常用的家庭儀表--水表、暖氣表,、熱水表集成在一起,,運行效果良好,,達到設計要求。