uCOS-Ⅱ C51移植筆記
前/后臺系統(tǒng):一個大循環(huán),循環(huán)查詢各種標(biāo)志位。如果標(biāo)志位置位,就執(zhí)行相應(yīng)的服務(wù)程序。標(biāo)志位就是標(biāo)志事件的發(fā)生,事件響應(yīng)延時處于不可預(yù)測狀態(tài)。最壞的情況是循環(huán)中所有其他的事件服務(wù)程序執(zhí)行完,才響應(yīng)當(dāng)前事件。中斷服務(wù)雖然能即時/優(yōu)先響應(yīng),但是它們和主循環(huán)的通訊,也是通過置主循環(huán)中相應(yīng)的標(biāo)志位來完成的。
本文引用地址:http://2s4d.com/article/201611/320408.htm實(shí)時系統(tǒng)(uCOS):整個程序分成一個個看起來好象是并行的任務(wù),每個任務(wù)都在等待事件的發(fā)生。除了最低優(yōu)先級任務(wù)(在uCOS中是IDLE任務(wù))是死循環(huán)以外,其他的任務(wù)都不能死循環(huán),只能在驅(qū)動事件驅(qū)動下工作。任何驅(qū)動事件的產(chǎn)生,都使優(yōu)先級最高的就緒任務(wù)運(yùn)行。任務(wù)和任務(wù)/任務(wù)和中斷的通訊,是通過相應(yīng)事件驅(qū)動來完成的。
驅(qū)動事件:
不論是什么系統(tǒng),CPU不可能一直在工作。CPU的工作是在各種驅(qū)動事件的驅(qū)動下工作的。CPU在完成一次驅(qū)動事件事件服務(wù)程序以后,進(jìn)入IDLE模式等待新的驅(qū)動事件的發(fā)生。包括實(shí)時系統(tǒng)和前/后臺系統(tǒng)都是在驅(qū)動事件的驅(qū)動下運(yùn)行的。
按照uCOS中的觀點(diǎn),驅(qū)動事件分為三類:
1、事件 (Event)。包括信號量(Semaphores)、事件標(biāo)志組(Flag)、郵箱(Message Box)、郵箱隊(duì)列(Message Queue)。
2、時間(Time Tick)。包括時間延時和事件超時。
3、中斷(Interrupt)??梢园l(fā)出各種event。
由于第1種事件,通常都是在第2、3種狀態(tài)下發(fā)出的,所以其實(shí)事件的驅(qū)動只有兩種:時間(定時)和中斷(各種異步中斷)。
時間實(shí)際上也是中斷的一種,可以說程序的驅(qū)動事件只有一種,就是:中斷。
前/后臺系統(tǒng)中還有一種驅(qū)動事件的產(chǎn)生,在主循環(huán)中不斷的查詢。有別與一般的定時查詢,這種查詢是為了將事件的響應(yīng)時間降到最低,也可以將其歸納于定時(時間)事件。
(2)uCOS C51移植的準(zhǔn)備工作;
2004年8月份,我在書城買了一本《uCOS-Ⅱ 第2版》,準(zhǔn)備學(xué)習(xí)RTOS。因?yàn)橐郧皼]有玩過RTOS,在工作之余斷斷續(xù)續(xù)的看了3、4章。一直到12月初的時候,公司要重新設(shè)計一個項(xiàng)目,恰好要把uCOS移植到c51上。我的RTOS學(xué)習(xí)才正式開始。
因?yàn)閷S向往以久,我并不想在網(wǎng)上Down一個現(xiàn)成的移植OS程序,做一個OS的應(yīng)用者。揭開OS的神秘面紗,了解OS的內(nèi)部運(yùn)行機(jī)制,這才是我想要做的。本文的主要目的是討論uCOS的移植,希望對即將進(jìn)行uCOS c51移植的兄弟有些幫助。對于OS的內(nèi)部運(yùn)行機(jī)制,由于東西比較多,在這里不想太展開。如果以后有時間,也想寫一篇文章來討論討論。
最開始,我的計劃就是看書,看《uCOS-Ⅱ 第2版》??赐赀@本幾百頁的大本本,花了我2個半星期。因?yàn)槭枪ぷ餍枰也趴梢赃@樣心安理得的在那里看呀看書^_^,辛苦呀L。在這期間,為了自己的思想不受別人的影響,我堅(jiān)決沒有從網(wǎng)上下任何uCOS的資料,我手頭的資料就是uCOS-Ⅱ的書和附帶光盤,這些就是最權(quán)威的資料了。在看書的時候,我都堅(jiān)持做筆記,把每天的重點(diǎn),明白的東西和心中的疑問都隨時記錄下來。對付這種大本本,前后的知識又相互關(guān)聯(lián),光靠我們的大腦是搞不定啊。
弄懂了uCOS的內(nèi)核,下一本書應(yīng)該是《單片機(jī)高級語言C51Windows環(huán)境編程與應(yīng)用》。對于Keil C我還是很熟的,還是花了2、3天來復(fù)習(xí)。這里的重點(diǎn)是C51對匯編的轉(zhuǎn)換結(jié)構(gòu),例于數(shù)據(jù)/系統(tǒng)堆棧的使用,C&Asm混合編程。我想對于任何CPU的uCOS移植,C語言的實(shí)現(xiàn)機(jī)制,你都是要了解的。這里也是要花大把時間的。
《uCOS-Ⅱ 第2版》和《單片機(jī)高級語言C51Windows環(huán)境編程與應(yīng)用》這兩本書網(wǎng)上都可以下電子檔的,我這里也有(大家需要可以來信索?。?。
uCOS和C51的書都看完了。我就下載了一堆uCOS的C51移植資料。其中的源程序有很多個版本的,不過詳細(xì)的移植文檔只有一個版本:巨龍一位大蝦的“uCOS C51移植心得”,相信很多人都看過。這些資料的作者都是我移植過程中的老師,有了這些資料,我才能把心中的朦朧想法變成源程序。但是我也發(fā)現(xiàn)這些資料中大多都有一些錯誤和遺漏,當(dāng)然這是難免的。這也正是驅(qū)使我寫這篇文章的原因,希望在前輩的基礎(chǔ)上有所進(jìn)步。歡迎大家來批評!
真正的源代碼移植,我花了大概一個星期時間。
(3)uCOS C51的移植概況;
1、工具:
uCOS 2.52版;
Keil C V6.23a。
2、uCOS V2.52的文件結(jié)構(gòu)與移植所需要的修改:
A、與處理器無關(guān)的文件:
OS_CORE.C
OS_FLAG.C
OS_MBOX.C
OS_MEM.C
OS_MUTEX.C
OS_Q.C
OS_SEM.C
OS_TASK.C
OS_TIME.C
uCOS_II.C
uCOS_II.H
這些文件在c51的移植過程中,只需要給函數(shù)加上重入屬性即可。
B、與應(yīng)用相關(guān)的文件:
INCLUDES.H: 包含C51的標(biāo)準(zhǔn)庫頭文件;對”pdata”等c51關(guān)鍵字的重定義
OS_CFG.H: “OS_TICKS_PER_SEC”、“ OS_FLAGS”注意可能需要修改。
C、與處理器相關(guān)的文件:
OS_CPU.H: 數(shù)據(jù)類型、關(guān)中斷方法、任務(wù)堆棧方向、任務(wù)切換的宏定義都需要修改。
OS_CPU_A.ASM: OSTickISR()、OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()這幾個函數(shù)的編寫,是整個移植的關(guān)鍵。
OS_CPU_C.C:OSTaskStkInit()函數(shù)的編寫。
(4)uCOS C51具體的移植過程;
1、C51的堆棧結(jié)構(gòu);
這是整個移植過程中的重中之重,所以特別詳細(xì)介紹。
A、
c51中,系統(tǒng)堆棧的棧底地址是“?STACK”,棧頂指針就是“SP”拉,棧的生長方向是向上的,??臻g分配在51的內(nèi)部RAM(idata)中。“?STACK”分配在所有內(nèi)部RAM數(shù)據(jù)段的最后面,所以系統(tǒng)堆棧的范圍是從?STACK到內(nèi)部RAM的最高位(0x80或者0xFF)。
B、
c51中,由于我們使用OS,采用的LARGE編譯模式,所以數(shù)據(jù)堆棧的指針是“?C_XBP”,棧的生長方向是向下的,??臻g分配在51的外部RAM(xdata)中。
C、
研究中斷中堆棧的保護(hù)的意義在于,因?yàn)閡COS中的任務(wù)切換,本身就是模擬一次中斷的發(fā)生:保護(hù)Task1的CPU寄存器,SP切換到Task2的堆棧,彈出Task2的CPU寄存器。用C51寫中斷函數(shù)的時候,編譯器會自動保護(hù)CPU的寄存器,所以中斷返回時任務(wù)調(diào)度OSIntCtxSw(),就不用重新保護(hù)寄存器。
C51中斷中調(diào)用函數(shù)可以分為四種情況(中斷函數(shù)本身不設(shè)為reentrant):
一、沒有函數(shù)調(diào)用;
二、調(diào)用非reentrant函數(shù),函數(shù)中沒有嵌套調(diào)用其他函數(shù);
三、調(diào)用非reentrant函數(shù),函數(shù)中嵌套調(diào)用其他函數(shù);
四、調(diào)用reentrant函數(shù)。
t0_isr:
POP
因?yàn)閡COS中所有的函數(shù)都必須是重入函數(shù),因此我們只需要研究第四種情況下的堆棧保護(hù),對于其他情況有興趣可以在c51中看看。(注意:可能因?yàn)閏51編譯器的版本不同,上述壓棧的順序可能不同。)
2、uCOS C51任務(wù)切換時的堆棧操作;
每個任務(wù)都有一個獨(dú)立的數(shù)據(jù)堆棧,系統(tǒng)堆棧是公用空間。
保護(hù)Task1的CPU寄存器:首先將CPU寄存器按上例壓進(jìn)Task1系統(tǒng)堆棧,再將整個Task1系統(tǒng)堆棧壓進(jìn)Task1數(shù)據(jù)堆棧;
SP切換:?C_XBP = Task2 的數(shù)據(jù)堆棧棧頂?shù)刂贰?/p>
彈出Task2的CPU寄存器:從Task2的數(shù)據(jù)堆棧重新恢復(fù)整個系統(tǒng)堆棧,然后再從Task2系統(tǒng)堆棧中恢復(fù)CPU寄存器值。
實(shí)現(xiàn)的方法有很多種,只要遵循uCOS任務(wù)切換的原理就可以了。
3、INCLUDES.H的移植;
4、OS_CPU.H的移植;
5、OS_CPU_A.ASM的移植;
6、OS_CPU_C.C的移植;
7、其他的移植;
評論