我們繼續(xù)上篇。上篇我漏了個開總中斷忘說了。

開中斷。 對了調(diào)試的時候吧任務A的睡眠給隱掉。因為一步一步來學習嘛! 當開了中斷,于是開始執(zhí)行定時器0中斷,定時器中的代碼一個是OSTimeTick(); 執(zhí)行任務時間片的分配。這里注意了,我自個寫的時候調(diào)試出現(xiàn)問題才發(fā)現(xiàn)的。他是先判斷是否有時間片,有則--,然后再判斷是否為0為0則 OSIntSendSignal(TaskId)。 OSIntSendSignal就是把任務置為就緒的沒什么,有必要提的就是關中斷和開中斷。這個為了避免產(chǎn)生中斷導致不可預知的錯誤。 然后回到定時器0的中斷服務程序中,執(zhí)行OSIntExit()。然后轉(zhuǎn)到==》OSIntCtxSw ==》 C_OSCtxSw ==》LoadCtx 然后就切換到任務B ,F(xiàn)在我開始慢慢的分析這幾個函數(shù),因為這里是需要慢慢講解的。首先從原理上講下。定時器中斷時依次把
中斷后 然后查看 內(nèi)存 按推斷應該是sp-15 個字節(jié) =i:0x16 如圖
你可以看出 中斷服務程序保存環(huán)境是按什么次序入棧的。帥吧~~~
然后執(zhí)行OSIntExit()壓入 0x0256
15+2 =17個字節(jié)然后 再跳轉(zhuǎn)到 OSIntCtxSw
這里開始用51
匯編寫的,這里是經(jīng)常執(zhí)行的代碼必須有效率。 在OSIntCtxSw 判斷當前任務是什么性質(zhì)的,現(xiàn)在這個是任務A隨意是sp=sp-4 并置中斷類型標志位,清任務運行標志位,LMJP OSCtxSw 首先壓入一個中斷計數(shù),然后開始吧 【前任務+1的存放地址 ----下個任務+1的地址】 這里有個第優(yōu)先級上還存放了個任務就是為符合這個處理方式。吧括號中的數(shù)據(jù)整個搬到上圖sp后面,然后吧修改后的函數(shù)首地址重新分配 OSTsakStackBotton存放 然后把下個任務切換成當前任務,他的內(nèi)存空間就是現(xiàn)在SP ---任務+1之間的空間。 這里的堆棧是從低到高分配的和PC里不一樣。然后還做了個清中斷標志的操作 壓入 LoadCtx 的函數(shù)地址的棧然后RETI 這個主要是清掉中斷標志,然后跳轉(zhuǎn)到環(huán)境加載函數(shù) 。然后LoadCtx 就把堆棧中下個任務的地址直接RET返回給$P于是就切換到下個任務了。 優(yōu)先級低的也差不對這樣處理的。
為了模擬跳轉(zhuǎn)到任務B 在中斷前加 extern uint8 OSTaskRuning; 在 OSIntExit(); 前+OSTaskRuning &=~OSMapTbl[0]; 這樣就模擬跳轉(zhuǎn)到任務B
嘿嘿,不好意思 +了那么入棧的數(shù)據(jù)就有變化了。但是數(shù)目應該沒變,我就不重新截圖了。
OSIntCtxSw 執(zhí)行后SP-4
放B的地址可以通過
看到i:0xF7是存儲的B的首地址,
數(shù)據(jù)塊應該是 【A+1】- 【B+1】之間的數(shù)據(jù)整個搬到當前sp+1后面 搬移后的內(nèi)存分布
后面 中斷計數(shù) 00 +搬過來的B-C間的2個字節(jié) C7 03這個正好是B任務的首地重新修改存放函數(shù)首地址的數(shù)組
這里可以跳轉(zhuǎn)到LoadCtx 吧任務切到任務B中。
至此通過中斷任務切換已經(jīng)完畢,此時可以向下如果任務中有數(shù)據(jù)在其中,那么這樣做會不會丟失數(shù)據(jù),其實仔細想想就可以了解,不會的。
本例源代碼下載:http://www.torrancerestoration.com/f/small_rtos1.12.1.zip
接下篇: