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

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