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