教你構(gòu)造一個51單片機(jī)的實時操作系統(tǒng)_第1頁
教你構(gòu)造一個51單片機(jī)的實時操作系統(tǒng)_第2頁
教你構(gòu)造一個51單片機(jī)的實時操作系統(tǒng)_第3頁
教你構(gòu)造一個51單片機(jī)的實時操作系統(tǒng)_第4頁
教你構(gòu)造一個51單片機(jī)的實時操作系統(tǒng)_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、教你構(gòu)造一個51單片機(jī)的實時操作系統(tǒng)    目前,大多數(shù)的產(chǎn)品開發(fā)是在基于一些小容量的單片機(jī)上進(jìn)行的。51系列單片機(jī),是我國目前使用最多的單片機(jī)系列之一,有非常廣大的應(yīng)用環(huán)境與前景,多年來的資源積累,使51系列單片機(jī)仍是許多開發(fā)者的首選。針對這種情況,近幾年涌現(xiàn)出許多基于51內(nèi)核的擴(kuò)展芯片,功能越來越齊全,速度越來越快,也從一個側(cè)面說明了51系列單片機(jī)在國內(nèi)的生命力。多年來我們一直想找一個合適的實時操作系統(tǒng),作為自己的開發(fā)基礎(chǔ)。根據(jù)開發(fā)需求,整合一些常用的嵌入式構(gòu)件,以節(jié)約開發(fā)時間,盡最大可能地減少開發(fā)工作量;另外,要求這個實時操作系統(tǒng)能非常容易地嵌入到

2、小容量的芯片中。畢竟,大系統(tǒng)是少數(shù)的,而小應(yīng)用是多數(shù)而廣泛的。顯而易見,COSII是不太適合于以上要求的,而Keil C所帶的RTX Tiny不帶源代碼,不具透明性,至于其FULL版本就更不用說了。1 Keil C51與重入問題說到實時操作系統(tǒng),就不能不考慮重入問題。對于PC機(jī)這樣的大內(nèi)存處理器而言,這似乎并不是一個很麻煩的問題,借用COSII RTOS的說法,即要求在重入的函數(shù)內(nèi),使用局部變量。但5l系列單片機(jī)堆棧空間很小,僅局限在256字節(jié)之內(nèi),無法為每個函數(shù)都分配一個局部堆空間。正是由于這個原因,Keil C51使用了所謂的可覆蓋技術(shù):局部變量存儲在全局RAM空間(不考慮擴(kuò)展外部存儲器的

3、情況);在編譯鏈接時,即已經(jīng)完成局部變量的定位;如果各函數(shù)之間沒有直接或間接的調(diào)用關(guān)系,則其局部變量空間便可覆蓋。正是由于以上的原因,在Keil C51環(huán)境下,純粹的函數(shù)如果不加處理(如增加一個模擬棧),是無法重人的。那么在Keil C5l環(huán)境下,如何使其函數(shù)具有可重人性呢?下面分析在實時操作系統(tǒng)下面,任務(wù)的基本結(jié)構(gòu)與模式:vold TaskA(void*ptr)UINT8 vaL_a;其他一些變量定義do實際的用戶任務(wù)處理代碼while(1);void TaskB(void*ptr)UINT8 vaLb;其他一些變量定義doFuncl();其他實際的用戶任務(wù)處理代碼)while(1);voi

4、d Funcl()UlNT8 v al_fa;其他變量的定義函數(shù)的處理代碼在上面的代碼中,TaskA與TaskB并不存在直接或間接的調(diào)用關(guān)系,因而其局部變量val_a與val_b便是可以被互相覆蓋的,即其可能都被定位于某一個相同的RAM空間。這樣,當(dāng)TaskA運行一段時間,改變了val_a后,TaskB取得CPU控制權(quán)并運行時,便可能會改變val_b。由于其指向相同的RAM空間,導(dǎo)致TaskA重新取得CPU控制權(quán)時,vala的值已經(jīng)改變,從而導(dǎo)致程序運行不正確,反過來亦然。另一方面,F(xiàn)uncl()與TaskB有直接的調(diào)用關(guān)系,因而其局部變量val_fa與val_b不會被互相覆蓋,但也不能保證其

5、局部變量val_fa不會與TaskA或其他任務(wù)的局部變量形成可覆蓋關(guān)系。將val_a、val_b以及val_fa等局部變量定義為靜態(tài)變量(加上static指示符)可以解決這一問題。但問題是,定義大量的static類型變量,將導(dǎo)致RAM空間的大量占用,有可能直接導(dǎo)致RAM空間不夠用。尤其是在一些小容量的單片機(jī)內(nèi),一般只有128或256字節(jié),大量的靜態(tài)變量定義,在如此小的RAM資源狀況下顯然就不太合適了。由此而有了另一種的解決方法,如下代碼所示:void TaskC(void)UINT8 x,v;whlk(1)OS_ENTER_CRITICAL();x=GetX(); (1)y=GetY(); (

6、2)任務(wù)的其他代碼OS_EXIT_CRITICAL(); (3)0SSleep(100); (4)以上代碼TaskC中使用了臨界保護(hù)的方法來保護(hù)代碼不被中斷占先,確實有效地解決了RAM空間太小,不宜大量定義靜態(tài)變量的問題。然而如果每個任務(wù)都采用此種結(jié)構(gòu),任務(wù)一開始,就關(guān)閉中斷,將使實時性得不到保證。事實證明,這種延時是相當(dāng)可觀的。用一個實例來說明,如果想在系統(tǒng)中使用一個動態(tài)刷新的LED顯示器,就難以保證顯示的穩(wěn)定與連續(xù),哪怕在系統(tǒng)中是使用一個單獨的定時器來做這一工作(進(jìn)入臨界區(qū)后,EA=0)。其次,這種結(jié)構(gòu)事實上將占先的任務(wù)調(diào)度轉(zhuǎn)化為非占先的任務(wù)調(diào)度。實際上如果在(3)與(4)之間沒有碰巧發(fā)生

7、中斷并導(dǎo)致一個任務(wù)調(diào)度,那就可以理解為是任務(wù)主動放棄CPU的控制。如果在(3)和(4)之間碰巧產(chǎn)生了一個中斷并導(dǎo)致了一個任務(wù)調(diào)度,只是執(zhí)行了一次多余的任務(wù)調(diào)度而已,而且并不希望在(3)之后發(fā)生2次甚至多次的任務(wù)調(diào)度,相信讀者也有這一愿望。除此之外,還可以發(fā)現(xiàn)任務(wù)的一個特點:當(dāng)任務(wù)從(1)重新開始時,局部變量x和y是一個什么值并不在乎,即x和y即使在(3)之后改變了,也已經(jīng)不再重要,不會影響程序的正確性。其實這一特點也是大部分任務(wù),至少是太部分任務(wù)的大部分局部變量的一個共性如果任務(wù)在整個執(zhí)行過程中,不會(被占先)放棄CPU控制權(quán),則其局部變量大多數(shù)并不需要進(jìn)行特別的保護(hù),即其作用域只是任務(wù)的當(dāng)次

8、執(zhí)行,針對上面的代碼,就是臨界保護(hù)區(qū)內(nèi)的代碼區(qū)域。目前,大多數(shù)的產(chǎn)品開發(fā)是在基于一些小容量的單片機(jī)上進(jìn)行的。51系列單片機(jī),是我國目前使用最多的單片機(jī)系列之一,有非常廣大的應(yīng)用環(huán)境與前景,多年來的資源積累,使51系列單片機(jī)仍是許多開發(fā)者的首選。針對這種情況,近幾年涌現(xiàn)出許多基于51內(nèi)核的擴(kuò)展芯片,功能越來越齊全,速度越來越快,也從一個側(cè)面說明了51系列單片機(jī)在國內(nèi)的生命力。多年來我們一直想找一個合適的實時操作系統(tǒng),作為自己的開發(fā)基礎(chǔ)。根據(jù)開發(fā)需求,整合一些常用的嵌入式構(gòu)件,以節(jié)約開發(fā)時間,盡最大可能地減少開發(fā)工作量;另外,要求這個實時操作系統(tǒng)能非常容易地嵌入到小容量的芯片中。畢竟,大系統(tǒng)是少數(shù)

9、的,而小應(yīng)用是多數(shù)而廣泛的。顯而易見,COSII是不太適合于以上要求的,而Keil C所帶的RTX Tiny不帶源代碼,不具透明性,至于其FULL版本就更不用說了。1 Keil C51與重入問題說到實時操作系統(tǒng),就不能不考慮重入問題。對于PC機(jī)這樣的大內(nèi)存處理器而言,這似乎并不是一個很麻煩的問題,借用COSII RTOS的說法,即要求在重入的函數(shù)內(nèi),使用局部變量。但5l系列單片機(jī)堆??臻g很小,僅局限在256字節(jié)之內(nèi),無法為每個函數(shù)都分配一個局部堆空間。正是由于這個原因,Keil C51使用了所謂的可覆蓋技術(shù):局部變量存儲在全局RAM空間(不考慮擴(kuò)展外部存儲器的情況);在編譯鏈接時,即已經(jīng)完成局

10、部變量的定位;如果各函數(shù)之間沒有直接或間接的調(diào)用關(guān)系,則其局部變量空間便可覆蓋。正是由于以上的原因,在Keil C51環(huán)境下,純粹的函數(shù)如果不加處理(如增加一個模擬棧),是無法重人的。那么在Keil C5l環(huán)境下,如何使其函數(shù)具有可重人性呢?下面分析在實時操作系統(tǒng)下面,任務(wù)的基本結(jié)構(gòu)與模式:vold TaskA(void*ptr)UINT8 vaL_a;其他一些變量定義do實際的用戶任務(wù)處理代碼while(1);void TaskB(void*ptr)UINT8 vaLb;其他一些變量定義doFuncl();其他實際的用戶任務(wù)處理代碼)while(1);void Funcl()UlNT8 v

11、al_fa;其他變量的定義函數(shù)的處理代碼在上面的代碼中,TaskA與TaskB并不存在直接或間接的調(diào)用關(guān)系,因而其局部變量val_a與val_b便是可以被互相覆蓋的,即其可能都被定位于某一個相同的RAM空間。這樣,當(dāng)TaskA運行一段時間,改變了val_a后,TaskB取得CPU控制權(quán)并運行時,便可能會改變val_b。由于其指向相同的RAM空間,導(dǎo)致TaskA重新取得CPU控制權(quán)時,vala的值已經(jīng)改變,從而導(dǎo)致程序運行不正確,反過來亦然。另一方面,F(xiàn)uncl()與TaskB有直接的調(diào)用關(guān)系,因而其局部變量val_fa與val_b不會被互相覆蓋,但也不能保證其局部變量val_fa不會與Task

12、A或其他任務(wù)的局部變量形成可覆蓋關(guān)系。將val_a、val_b以及val_fa等局部變量定義為靜態(tài)變量(加上static指示符)可以解決這一問題。但問題是,定義大量的static類型變量,將導(dǎo)致RAM空間的大量占用,有可能直接導(dǎo)致RAM空間不夠用。尤其是在一些小容量的單片機(jī)內(nèi),一般只有128或256字節(jié),大量的靜態(tài)變量定義,在如此小的RAM資源狀況下顯然就不太合適了。由此而有了另一種的解決方法,如下代碼所示:void TaskC(void)UINT8 x,v;whlk(1)OS_ENTER_CRITICAL();x=GetX(); (1)y=GetY(); (2)任務(wù)的其他代碼OS_EXIT_

13、CRITICAL(); (3)0SSleep(100); (4)以上代碼TaskC中使用了臨界保護(hù)的方法來保護(hù)代碼不被中斷占先,確實有效地解決了RAM空間太小,不宜大量定義靜態(tài)變量的問題。然而如果每個任務(wù)都采用此種結(jié)構(gòu),任務(wù)一開始,就關(guān)閉中斷,將使實時性得不到保證。事實證明,這種延時是相當(dāng)可觀的。用一個實例來說明,如果想在系統(tǒng)中使用一個動態(tài)刷新的LED顯示器,就難以保證顯示的穩(wěn)定與連續(xù),哪怕在系統(tǒng)中是使用一個單獨的定時器來做這一工作(進(jìn)入臨界區(qū)后,EA=0)。其次,這種結(jié)構(gòu)事實上將占先的任務(wù)調(diào)度轉(zhuǎn)化為非占先的任務(wù)調(diào)度。實際上如果在(3)與(4)之間沒有碰巧發(fā)生中斷并導(dǎo)致一個任務(wù)調(diào)度,那就可以理

14、解為是任務(wù)主動放棄CPU的控制。如果在(3)和(4)之間碰巧產(chǎn)生了一個中斷并導(dǎo)致了一個任務(wù)調(diào)度,只是執(zhí)行了一次多余的任務(wù)調(diào)度而已,而且并不希望在(3)之后發(fā)生2次甚至多次的任務(wù)調(diào)度,相信讀者也有這一愿望。除此之外,還可以發(fā)現(xiàn)任務(wù)的一個特點:當(dāng)任務(wù)從(1)重新開始時,局部變量x和y是一個什么值并不在乎,即x和y即使在(3)之后改變了,也已經(jīng)不再重要,不會影響程序的正確性。其實這一特點也是大部分任務(wù),至少是太部分任務(wù)的大部分局部變量的一個共性如果任務(wù)在整個執(zhí)行過程中,不會(被占先)放棄CPU控制權(quán),則其局部變量大多數(shù)并不需要進(jìn)行特別的保護(hù),即其作用域只是任務(wù)的當(dāng)次執(zhí)行,針對上面的代碼,就是臨界保護(hù)

15、區(qū)內(nèi)的代碼區(qū)域。2 實時操作系統(tǒng)要不要占先由上面的分析,如果要保持一個函數(shù)可重人,就得使用靜態(tài)變量,系統(tǒng)的RAM資源將是一個嚴(yán)峻的考驗;如果使用臨界區(qū)來保護(hù)運行環(huán)境,系統(tǒng)的實時性又得不到保證,而且有將占先式任務(wù)調(diào)度轉(zhuǎn)為非占先任務(wù)調(diào)度之虞。顯然,使用靜態(tài)變量簡單,但有更多的不適用性,對將來功能的調(diào)整也是一個阻礙,一般不被采用。那么,就只能從環(huán)境保護(hù)上來下功夫了,但是果真只能以進(jìn)入臨界區(qū)犧牲系統(tǒng)的實時性來保證任務(wù)不被占先?下面看看臨界保護(hù)這一方法的基本思路:在一個任務(wù)中,如果局部變量在其作用域內(nèi)不被占先切換,則這些變量在任務(wù)被剝奪了CPU控制權(quán)后,不關(guān)心其值也不會影響任務(wù)的正確執(zhí)行;使用臨界區(qū)保護(hù)

16、,可以達(dá)到上面所提到的要求;由此導(dǎo)致的實時性能與占先切換的減弱可以接受。由此可知,不被占先是任務(wù)保護(hù)局部變量的關(guān)鍵。既然如此,何不舍棄占先式的任務(wù)調(diào)度?這不失為一個好的出發(fā)點。針對Keil C51,非占先式任務(wù)調(diào)度,可能是一種更好的方法,更能協(xié)調(diào)51系列單片機(jī)的既定資源。下面編寫這樣一個系統(tǒng):使用非占先式任務(wù)調(diào)度;可以在小容量的芯片中使用,開發(fā)目標(biāo)是,即使是8051這樣小的芯片,也可使用這個實時操作系統(tǒng);支持優(yōu)先級調(diào)度,盡可能保證其實時性。 3 實時操作系統(tǒng)的實現(xiàn) 基于以上的分析與目的,近日完成了這個操作系統(tǒng)。在堆棧上借用RTx的管理方法,即當(dāng)前任務(wù)使用全部的堆空間,如圖1

17、所示。  3.1 堆棧的初始化與任務(wù)的創(chuàng)建堆棧的初始化實際是初始化0STaskStackBotton數(shù)組,并將當(dāng)前任務(wù)指定為空閑任務(wù),下一個運行任務(wù)指定為最高優(yōu)先級任務(wù),即優(yōu)先級為零的任務(wù)。初始化時,將SP的值存人OSTaslkStackBottonO,SP+2的值存入OSTaskStacKBotton1,依此類推。而任務(wù)是調(diào)用0STa-skCreate函數(shù)建立的。實際上只是將任務(wù)(假設(shè)為n號任務(wù))的地址填人到對應(yīng)OSTaskStackBottonn所指向的位置,并將SP向后移動2個字節(jié),如圖2所示。  為什么要以這樣一種規(guī)律而不是其他的方式呢?這是由于

18、在任務(wù)建立后,還未進(jìn)行任務(wù)調(diào)度之前,各任務(wù)的堆棧實際上是它們自身的地址,因而其堆棧深度為2,為了程序的簡便而直接填入。void main(void)OSInit(); *初始化OSTaskStackBcBotton隊列*TMOD=(TMOD&0XFO) 0XOl;TL0=0xBF;TH0=0xFC;TRO=1;ETO=1;TFO=O:OSTaskCreate(TaskA,NULL,0);OSTaskCreate(TaskBNULL,1);OSTaskCreate(TaskC,NULL,2);OSStart();上面這段代碼中,所有任務(wù)建立后,便調(diào)用OSStart()開始任務(wù)調(diào)度。OSStart()是一個宏定義,如下所示:#deflne OSStart() d0OSTaskCreate(TaskIdle,NULL,OS_MAX_TASKS);EA=l:return;while(O)首先,它創(chuàng)建了一個空閑任務(wù)并打開中斷,然后便返回。返回到哪里了呢?我們知道,空閑任務(wù)是優(yōu)先級最低的任務(wù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論