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