51單片機最簡單的多任務(wù)操作系統(tǒng)_第1頁
51單片機最簡單的多任務(wù)操作系統(tǒng)_第2頁
51單片機最簡單的多任務(wù)操作系統(tǒng)_第3頁
51單片機最簡單的多任務(wù)操作系統(tǒng)_第4頁
全文預(yù)覽已結(jié)束

下載本文檔

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

文檔簡介

1、/* 51單片機最簡單的多任務(wù)操作系統(tǒng)其實只有個任務(wù)調(diào)度切換,把說它是OS有點牽強,但它對于一些簡單的開發(fā)應(yīng)用來說,簡單也許就是最好的.盡情的擴展它吧 . 別忘了把你的成果分享給大家 .這是一個最簡單的OS,切以運行效率為重,經(jīng)測試,切換一次任務(wù)僅個機器周期,也就是在標(biāo)準(zhǔn)(工作于M晶振) 上uS.而為速度作出的犧牲是 , 為了給每個任務(wù)都分配一個私有堆棧 , 而占用了較多的內(nèi)存 . 作為補償 , 多任務(wù)更容易安 排程序邏輯 , 從而可以節(jié)省一些用于控制的變量 .任務(wù)槽越多 ,占用內(nèi)存越多 ,但任務(wù)也越好安排 ,以實際需求合理安排任務(wù)數(shù)目 .一般來說 ,4個已足夠 .況且可以 拿一個槽出來作為活

2、動槽 , 換入換入一些臨時任務(wù) .task_load( 函數(shù)名 , 任務(wù)槽號 )裝載任務(wù)os_start( 任務(wù)槽號 )啟動任務(wù)表 . 參數(shù)必須指向一個裝載了的任務(wù) , 否則系統(tǒng)會崩潰 .task_switch()切換到其它任務(wù). 編寫任務(wù)函數(shù)注意事項 :KEIL C編譯器是假定用戶使用單任務(wù)環(huán)境,所以在變量的使用上都未對多任務(wù)進(jìn)行處理,編寫任務(wù)時應(yīng)注意變量覆蓋和代碼重入問題 .1. 覆蓋:編譯器為了節(jié)省內(nèi)存 ,會給兩個沒用調(diào)用關(guān)系的函數(shù)分配同一內(nèi)存地址作為變量空間 .這在單任務(wù)下是 很合理的 , 但對于多任務(wù)來說 , 兩個進(jìn)程會互相干擾對方 .解決的方法是 : 凡作用域內(nèi)會跨越 task_s

3、witch() 的變量 , 都使用 static 前輟 , 保證其地址空間分配時的唯一性 .2. 重入:重入并不是多任務(wù)下獨有的問題,在單任務(wù)時 ,函數(shù)遞歸同樣會導(dǎo)致重入 ,即,一個函數(shù)的不同實例 (或者叫作 "復(fù)本 ") 之間的變量覆蓋問題 .解決的方法是:使用reentrant函數(shù)后輟(例如:void function1() reentrant.).當(dāng)然,根本的辦法還是避免重入 , 因為重入會帶來巨大的目標(biāo)代碼量 , 并極大降低運行效率 .3. 額外提醒一句 , 在本例中 , 任務(wù)函數(shù)必須為一個死循環(huán) . 退出函數(shù)會導(dǎo)致系統(tǒng)崩潰 . 任務(wù)函數(shù)如果是用匯編寫成或內(nèi)嵌匯編

4、, 切換任務(wù)時應(yīng)該注意什么問題 ?由于KEIL C編譯器在處理函數(shù)調(diào)用時的約定規(guī)則為”子函數(shù)有可能修改任務(wù)寄存器",因此編譯器在調(diào)用前已釋放所有寄存器 , 子函數(shù)無需考慮保護(hù)任何寄存器 .這對于寫慣匯編的人來說有點不習(xí)慣 : 匯編習(xí)慣于在子程序中保護(hù)寄存器 .請注意一條原則 : 凡是需要跨越 task_switch() 的寄存器 , 全部需要保護(hù) ( 例如入棧 ). 根本解決辦法還是 , 不要讓 寄存器跨越任務(wù)切換函數(shù) task_switch()事實上這里要補充一下 , 正如前所說 ,由于編譯器存在變量地址覆蓋優(yōu)化 ,因此凡是非靜態(tài)變量都不得跨越 task_switch().任務(wù)函數(shù)

5、的書寫 :void 函數(shù)名 (void)/ 任務(wù)函數(shù)必須定義為無參數(shù)型 while(1)/ 任務(wù)函數(shù)不得返回 , 必須為死循環(huán)/ 這里寫任務(wù)處理代碼task_switch();每執(zhí)行一段時間任務(wù),就釋放CPUH下,讓別的任務(wù)有機會運行 任務(wù)裝載 :task_load( 函數(shù)名 , 任務(wù)槽號 )裝載函數(shù)的動作可發(fā)生在任意時候 ,但通常是在 main() 中.要注意的是 ,在本例中由于沒考慮任務(wù)換出 所以在執(zhí)行 os_start() 前必須將所有任務(wù)槽裝滿 .之后可以隨意更換任務(wù)槽中的任務(wù) .啟動任務(wù)調(diào)度器 :os_start( 任務(wù)槽號 )調(diào)用該宏后 ,將從參數(shù)指定的任務(wù)槽開始執(zhí)行任務(wù)調(diào)度 .本

6、例為每切換一次任務(wù)需額外開銷個機器周期 ,用于遷 移堆棧.*/#include <reg51.h> /*=以下為任務(wù)管理器代碼 =*/#define MAX_TASKS 3/ 任務(wù)槽個數(shù) .在本例中并未考慮任務(wù)換入換出 ,所以實際運行的任務(wù)有多少個 ,就定義多 少個任務(wù)槽 , 不可多定義或少定義/ 任務(wù)的棧指針unsigned char idata task_spMAX_TASKS;#define MAX_TASK_DEP 12/ 最大棧深 . 最低不得少于個 , 保守值為 ./預(yù)估方法:以為基數(shù),每增加一層函數(shù)調(diào)用 ,加字節(jié).如果其間可能發(fā)生中斷 , 則還要再加上中斷需要的棧深

7、./ 減小棧深的方法 :1. 盡量少嵌套子程序 2. 調(diào)子程序前關(guān)中斷 .unsigned char idata task_stackMAX_TASKSMAX_TASK_DEP; / 任務(wù)堆棧 .unsigned char task_id; / 當(dāng)前活動任務(wù)號 / 任務(wù)切換函數(shù) ( 任務(wù)調(diào)度器 )void task_switch() task_sptask_id = SP;if (+task_id = MAX_TASKS)task_id = 0;SP = task_sptask_id;/ 任務(wù)裝入函數(shù) . 將指定的函數(shù) ( 參數(shù) ) 裝入指定 ( 參數(shù) ) 的任務(wù)槽中 . 如果該槽中原來就有任

8、務(wù) , 則原任務(wù)丟失 , 但系統(tǒng)本身不會發(fā)生錯誤 .void task_load( unsigned int fn, unsigned char tid) task_sptid = task_stacktid + 1;task_stacktid0 = (unsigned int )fn & 0xff;task_stacktid1 = (unsigned int )fn >> 8;/ 從指定的任務(wù)開始運行任務(wù)調(diào)度 . 調(diào)用該宏后 , 將永不返回 .#define os_start(tid) task_id = tid,SP = task_sptid;return ; unsi

9、gned char stra3, strb3; / 用于內(nèi)存塊復(fù)制測試的數(shù)組=以下為測試代碼=*/測試任務(wù):復(fù)制內(nèi)存塊.每復(fù)制一個字節(jié)釋放 CPUH次void task1()/每復(fù)制一個字節(jié)釋放CPUH次,控制循環(huán)的變量必須考慮覆蓋static unsigned char i; / 如果將這個變量前的 static 去掉 , 會發(fā)生什么事 ?i = 0;while (1) / 任務(wù)必須為死循環(huán) , 不得退出函數(shù) , 否則系統(tǒng)會崩潰strai = strbi;if (+i = sizeof (stra)i = 0;/ 變量 i 在這里跨越了 task_switch(), 因此它必須定義為靜態(tài) (

10、static), 否則它將會被其它進(jìn)程修改 , 因為在另一個進(jìn)程里也會用到該變量所占用的地址 .task_switch(); /釋放CPUH會兒,讓其它進(jìn)程有機會運行.如果去掉該行,則別的進(jìn)程永遠(yuǎn)不會被調(diào) 用到 /測試任務(wù):復(fù)制內(nèi)存塊.每復(fù)制一個字節(jié)釋放 CPUH次.void task2()/每復(fù)制一個字節(jié)釋放CPUH次,控制循環(huán)的變量必須考慮覆蓋static unsigned char i; /如果將這個變量前的 static 去掉,將會發(fā)生覆蓋問題.task1() 和task2()會被 編譯器分配到同一個內(nèi)存地址上 , 當(dāng)兩個任務(wù)同時運行時 ,i 的值就會被兩個任務(wù)改來改去i = 0;wh

11、ile (1) / 任務(wù)必須為死循環(huán) ,不得退出函數(shù) ,否則系統(tǒng)會崩潰strai = strbi;if (+i = sizeof (stra)i = 0;/ 變量 i 在這里跨越了 task_switch(), 因此它必須定義為靜態(tài) (static), 否則它將會被其它進(jìn)程修改 , 因為在另一個進(jìn)程里也會用到該變量所占用的地址 .task_switch(); /釋放CPUh會兒,讓其它進(jìn)程有機會運行.如果去掉該行,則別的進(jìn)程永遠(yuǎn)不會被調(diào)用到/測試任務(wù):復(fù)制內(nèi)存塊.復(fù)制完所有字節(jié)后釋放 CPU一次.void task3()/復(fù)制全部字節(jié)后才釋放CPU控制循環(huán)的變量不須考慮覆蓋unsigned c

12、har i; / 這個變量前不需要加 static, 因為在它的作用域內(nèi)并沒有釋放過 CPUwhile (1) / 任務(wù)必須為死循環(huán) ,不得退出函數(shù) , 否則系統(tǒng)會崩潰i = sizeof (stra);dostrai-1 = strbi-1; while (-i);/變量i在這里已完成它的使命,所以無需定義為靜態(tài).你甚至可以定義為寄存器型(regiter)task_switch(); /釋放CPU一會兒,讓其它進(jìn)程有機會運行.如果去掉該行,則別的進(jìn)程永遠(yuǎn)不會被調(diào) 用到 void main()/ 在這個示例里并沒有考慮任務(wù)的換入換出 , 所以任務(wù)槽必須全部用完 , 否則系統(tǒng)會崩潰 ./這里裝載了三個任務(wù),因此在定義MAX_TASKS也必須定義為task_load(task1,0)

溫馨提示

  • 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

提交評論