最近有空去研究了一下陳明計的 small rtos for 8051,看了老半天,還是看不懂他在寫什麼;尤其是他在 stack 的處理方式,實在是有看沒有懂。所以自己就自己來寫了一套 tiny rtos for 8051。沒有 semaphore,也沒有 task priority,什麼都沒有,只有簡單的時間分配,也就是所有工作時間都一致,current task 工作固定時間後,再換 next task 工作固定時間,如此循環工作。
工作原理也很簡單,如果有 n 個 tasks 就把 stack 分成 n 等份,讓每個 task 保有自己的 stack,不要互相干擾就可以。再利用 timer interrupt 來切換 task。很簡單吧,就如下面程式碼所列,並不會很難。
寫了二個測試函數,主要就是從 rs232 印出 1~9 及 a~i,如下所示。
但是結果卻不如預期,跑出來的東西都是亂碼,傻眼。最後,經過了二天的努力,總算把結果正確無誤的弄出來了。主要有下列幾個地方要修改。
- 把 C51 的 Code Optimization Level 降成 1:Dead code elimination。因為 Data overlaying 的關係,造成 task1 的 i 變數跟 task2 的 j 變數共用同樣的位址,所以讓印出來的值都在 1~9 跳動。
- 原本 data overlaying 問題想要利用 reentrant 指令來建立可重入函數去解決,但最後發現仍然是無效。因為 keil 把變數都放在一個 ?C_IBP 的位址,仍然會造成共用的問題,這個問題真是難解啊,以後如果要寫複雜的 multi-task 函數有一定的難度,必須克服可重入函數及 data overlaying 造成的問題。
- 在 rtos_isr 函數裏加入 push 及 pop 指令,把 R0~R7,ACC,B,PSW,DPH,DPL 都丟到 stack 裏去。因為 keil 都會利用這些暫存器做一些運算,在進入 interrupt 時,也會主動 push 一些在 interrupt 會用到的暫存器到 stack 裏,但其它沒用到的暫存器就沒有主動 push,造成切換到其它 task 再切回原來 task 時,那些暫存器裏的值都被變更了,而造成運算錯誤。
- 另外在加入 assembly code 時,需把 Generate Assembler SRC File 及 Assemble SRC File 都打勾才可以,缺一不可。
好強大阿~ 雖然我有看沒有懂 @@
回覆刪除有辦法指點迷津嗎 @@ 跪