国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

構造一個51單片機的實時操作系統的方法

發布時間:2010-11-3 12:49    發布者:eetech
目前,大多數的產品開發是在基于一些小容量的單片機上進行的。51系列單片機,是我目前使用最多的單片機系列之一,有非常廣大的應用環境與前景,多年來的資源積累,使51系列單片機仍是許多開發者的首選。針對這種情況,近幾年涌現出許多基于51內核的擴展芯片,功能越來越齊全,速度越來越快,也從一個側面說明了51系列單片機在國內的生命力。

多年來我們一直想找一個合適的實時操作系統,作為自己的開發基礎。根據開發需求,整合一些常用的嵌入式構件,以節約開發時間,盡最大可能地減少開發工作量;另外,要求這個實時操作系統能非常容易地嵌入到小容量的芯片中。畢竟,大系統是少數的,而小應用是多數而廣泛的。顯而易見,μC/OS—II是不太適合于以上要求的,而Keil C所帶的RTX Tiny不帶源代碼,不具透明性,至于其FULL版本就更不用說了。

1 KeiI C51與重入問題

說到實時操作系統,就不能不考慮重入問題。對于PC機這樣的大內存處理器而言,這似乎并不是一個很麻煩的問題,借用μC/OS—II RTOS的說法,即要求在重入的函數內,使用局部變量。但5l系列單片機堆棧空間很小,僅局限在256字節之內,無法為每個函數都分配一個局部堆空間。正是由于這個原因,Keil C51使用了所謂的可覆蓋技術:

①局部變量存儲在全局RAM空間(不考慮擴展外部存儲器的情況);
②在編譯鏈接時,即已經完成局部變量的定位;
③如果各函數之間沒有直接或間接的調用關系,則其局部變量空間便可覆蓋。

正是由于以上的原因,在Keil C51環境下,純粹的函數如果不加處理(如增加一個模擬棧),是無法重的。那么在Keil C5l環境下,如何使其函數具有可重人性呢?下面分析在實時操作系統下面,任務的基本結構與模式:

vold TaskA(void*ptr){
UINT8 vaL_a;
//其他一些變量定義
do{
//實際的用戶任務處理代碼
}while(1);
}
void TaskB(void*ptr){
UINT8 vaLb;
//其他一些變量定義
do{
Funcl();
//其他實際的用戶任務處理代碼
)while(1);
void Funcl(){
UlNT8 v al_fa;
//其他變量的定義
//函數的處理代碼
}

在上面的代碼中,TaskA與TaskB并不存在直接或間接的調用關系,因而其局部變量val_a與val_b便是可以被互相覆蓋的,即其可能都被定位于某一個相同的RAM空間。這樣,當TaskA運行一段時間,改變了val_a后,TaskB取得CPU控制權并運行時,便可能會改變val_b。由于其指向相同的RAM空間,導致TaskA重新取得CPU控制權時,val—a的值已經改變,從而導致程序運行不正確,反過來亦然。另一方面,Funcl()與TaskB有直接的調用關系,因而其局部變量val_fa與val_b不會被互相覆蓋,但也不能保證其局部變量val_fa不會與TaskA或其他任務的局部變量形成可覆蓋關系。

將val_a、val_b以及val_fa等局部變量定義為靜態變量(加上static指示符)可以解決這一問題。但問題是,定義大量的static類型變量,將導致RAM空間的大量占用,有可能直接導致RAM空間不夠用。尤其是在一些小容量的單片機內,一般只有128或256字節,大量的靜態變量定義,在如此小的RAM資源狀況下顯然就不太合適了。由此而有了另一種的解決方法,如下代碼所示:

void TaskC(void){
UINT8 x,v;
whlk(1){
OS_ENTER_CRITICAL();
x=GetX(); (1)
y=GetY(); (2)
//任務的其他代碼
OS_EXIT_CRITICAL(); (3)
0SSleep(100); (4)
}
}

以上代碼TaskC中使用了臨界保護的方法來保護代碼不被中斷占先,確實有效地解決了RAM空間太小,不宜大量定義靜態變量的問題。然而如果每個任務都采用此種結構,任務一開始,就關閉中斷,將使實時性得不到保證。事實證明,這種延時是相當可觀的。用一個實例來說明,如果想在系統中使用一個動態刷新的LED顯示器,就難以保證顯示的穩定與連續,哪怕在系統中是使用一個單獨的定時器來做這一工作(進入臨界區后,EA=0)。其次,這種結構事實上將占先的任務調度轉化為非占先的任務調度。實際上如果在(3)與(4)之間沒有碰巧發生中斷并導致一個任務調度,那就可以理解為是任務主動放棄CPU的控制。如果在(3)和(4)之間碰巧產生了一個中斷并導致了一個任務調度,只是執行了一次多余的任務調度而已,而且并不希望在(3)之后發生2次甚至多次的任務調度,相信讀者也有這一愿望。

除此之外,還可以發現任務的一個特點:當任務從(1)重新開始時,局部變量x和y是一個什么值并不在乎,即x和y即使在(3)之后改變了,也已經不再重要,不會影響程序的正確性。其實這一特點也是大部分任務,至少是太部分任務的大部分局部變量的一個共性——如果任務在整個執行過程中,不會(被占先)放棄CPU控制權,則其局部變量大多數并不需要進行特別的保護,即其作用域只是任務的當次執行,針對上面的代碼,就是臨界保護區內的代碼區域。

2 實時操作系統要不要占先

由上面的分析,如果要保持一個函數可重人,就得使用靜態變量,系統的RAM資源將是一個嚴峻的考驗;如果使用臨界區來保護運行環境,系統的實時性又得不到保證,而且有將占先式任務調度轉為非占先任務調度之虞。顯然,使用靜態變量簡單,但有更多的不適用性,對將來功能的調整也是一個阻礙,一般不被采用。那么,就只能從環境保護上來下功夫了,但是果真只能以進入臨界區犧牲系統的實時性來保證任務不被占先?下面看看臨界保護這一方法的基本思路:

①在一個任務中,如果局部變量在其作用域內不被占先切換,則這些變量在任務被剝奪了CPU控制權后,不關心其值也不會影響任務的正確執行;

②使用臨界區保護,可以達到上面所提到的要求;

③由此導致的實時性能與占先切換的減弱可以接受。由此可知,不被占先是任務保護局部變量的關鍵。既然如此,何不舍棄占先式的任務調度?這不失為一個好的出發點。針對Keil C51,非占先式任務調度,可能是一種更好的方法,更能協調51系列單片機的既定資源。下面編寫這樣一個系統:

①使用非占先式任務調度;

②可以在小容量的芯片中使用,開發目標是,即使是8051這樣小的芯片,也可使用這個實時操作系統;

③支持優先級調度,盡可能保證其實時性。

3 實時操作系統的實現

基于以上的分析與目的,近日完成了這個操作系統。在堆棧上借用RTx的管理方法,即當前任務使用全部的堆空間,如圖1所示。





3.1 堆棧的初始化與任務的創建

堆棧的初始化實際是初始化0STaskStackBotton數組,并將當前任務指定為空閑任務,下一個運行任務指定為最高優先級任務,即優先級為零的任務。初始化時,將SP的值存人OSTaslkStackBotton[O],SP+2的值存入OSTaskStacKBotton,依此類推。而任務是調用0STa-skCreate函數建立的。實際上只是將任務(假設為n號任務)的地址填人到對應OSTaskStackBotton[n]所指向的位置,并將SP向后移動2個字節,如圖2所示。





為什么要以這樣一種規律而不是其他的方式呢?這是由于在任務建立后,還未進行任務調度之前,各任務的堆棧實際上是它們自身的地址,因而其堆棧深度為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(TaskB.NULL,1);
OSTaskCreate(TaskC,NULL,2);
OSStart();

上面這段代碼中,所有任務建立后,便調用OSStart()開始任務調度。OSStart()是一個宏定義,如下所示:

#deflne OSStart() d0{\
OSTaskCreate(TaskIdle,NULL,OS_MAX_TASKS);\
EA=l:\
return;\
}while(O)

首先,它創建了一個空閑任務并打開中斷,然后便返回。返回到哪里了呢?我們知道,空閑任務是優先級最低的任務,當調OSTaskCreate建立時,會將其地址填人到SP的位置,并把SP向后移動2個字節(見圖2及說明),因而此時處在堆棧頂端的,一定是空閑任務Taslddle。這就使得這里的return一定會返回到空閑任務。至此,系統進入正常運行狀態。





3.2 任務的切換

任務的切換分兩種情況,在當前任務優先級低于下一個取得CPU控制權的任務時,將下一個取得CPU控制權的任務的棧頂到當前任務的棧頂之間的內容向RAM空間的高端搬移,以空出全部的RAM空間作下一個任務的堆空間,同時更新對應的OSTaskStackBotton,使其指向新的正確任務的堆棧棧底。如果當前任務的優先級高于下一個任務的優先級,則作相反的搬移,如圖3與圖4所示。

所有任務必須主動調用OSSleep,放棄CPU的控制權。任務調用OSSleep后,將選擇優先級最高的就緒任務運行。

結 語

系統完成后,內核的代碼量在400多個字節左右,占用1個定時器中斷及小量的內存空間。系統設置容量為8個任務,用戶實際可用任務為7個,能夠滿足一般需求,也達到了在小容量芯片中應用的開發要求。由于沒有采用占先式的任務調度,除開全程相關的個別任務的一些局部變量外,其他局部變量已經不存在覆蓋關系,由于是任務主動放棄CPU控制權,對于個別需要保護的變量單獨進行處理也變得容易。在系統中,全程不需要反復地開關中斷,實時性能也很好。對個別時序要求嚴格的外設(如DSl8820)除外。
本文地址:http://m.qingdxww.cn/thread-35975-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 探索PIC16F13145 MCU系列——快速概覽
  • 貿澤電子(Mouser)專區

相關在線工具

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美香蕉视频 | h视频在线观看免费 | 国产精品欧美视频另类专区 | 日日日夜夜夜夜 | 欧美日本一道道一区二区三 | 黄色欧美视频在线观看 | 丁香六月久久 | 四虎影视免费观看免费观看 | 亚洲区视频在线观看 | 国产精品1024 | 91久久精品国产91性色tv | 点击进入不卡毛片免费观看 | 999色色色 | 高清国产精品久久久久 | 91香蕉视频网 | 青青草原免费在线视频 | 成人窝窝午夜看片 | 91在线免费视频观看 | 国产成人在线观看免费网站 | 日本成人免费在线观看 | 一级性黄色 | 日本免费观看的视频在线 | 日韩精品一区二区三区不卡 | 羞羞视频导航 | 日本欧美一级 | 国产三级精品三级国产 | 日韩a级片在线观看 | 欧美整片在线 | 66久久| 欧美一区二区三区四区五区六区 | 麻豆短视频在线观看 | h版欧美一区二区三区四区 h版欧美大片免费观看 | 亚洲精品色婷婷在线影院麻豆 | 日韩精品欧美精品中文精品 | 免费观看国产精品视频 | 三级大片免费看 | 亚洲日韩视频免费观看 | 久久蜜桃亚洲一区二区 | 精品伊人久久久久网站 | 日本天堂免费 | 一区二区三区国产精品 |