tiny rtos for 8051 part1

Posted by: 邱小新 at 下午3:50 in , ,
原始碼下載

最近有空去研究了一下陳明計的 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。很簡單吧,就如下面程式碼所列,並不會很難。

#define MAX_TASKS 2 unsigned char rtos_task_id; unsigned char rtos_stack[MAX_TASKS]; void (* const task_func[MAX_TASKS])(void)={ task1, task2 }; void rtos_isr(void) interrupt 1 { // save current stack rtos_stack[rtos_task_id] = SP; // load next stack if (++rtos_task_id >= MAX_TASKS) rtos_task_id = 0; SP = rtos_stack[rtos_task_id]; } void rtos_start(void) { xdata unsigned char i, size; xdata unsigned char idata *sp; rtos_task_id = 0; size = (256 - SP + 2) / MAX_TASKS; sp = (unsigned char idata *)SP; for (i=0; i<MAX_TASKS; i++) { *sp-- = ((unsigned int)(task_func[i])) / 256; *sp-- = ((unsigned int)(task_func[i])) % 256; rtos_stack[i] = sp + 15; sp += size + 2; } TMOD = (TMOD & 0xF0) | 0x01; TH0 = 0; TL0 = 0; TF0 = LOW; ET0 = HIGH; TR0 = HIGH; }

寫了二個測試函數,主要就是從 rs232 印出 1~9 及 a~i,如下所示。

void task1(void) { xdata unsigned char i=0x30; while(1) { if (++i>=0x3a) i=0x31; putchar(i); delay_1ms(50); } } void task2(void) { xdata unsigned char j=0x60; while(1) { if (++j>=0x6a) j=0x61; putchar(j); delay_1ms(50); } }

但是結果卻不如預期,跑出來的東西都是亂碼,傻眼。最後,經過了二天的努力,總算把結果正確無誤的弄出來了。主要有下列幾個地方要修改。

  1. 把 C51 的 Code Optimization Level 降成 1:Dead code elimination。因為 Data overlaying 的關係,造成 task1 的 i 變數跟 task2 的 j 變數共用同樣的位址,所以讓印出來的值都在 1~9 跳動。

  2. 原本 data overlaying 問題想要利用 reentrant 指令來建立可重入函數去解決,但最後發現仍然是無效。因為 keil 把變數都放在一個 ?C_IBP 的位址,仍然會造成共用的問題,這個問題真是難解啊,以後如果要寫複雜的 multi-task 函數有一定的難度,必須克服可重入函數及 data overlaying 造成的問題。

  3. 在 rtos_isr 函數裏加入 push 及 pop 指令,把 R0~R7,ACC,B,PSW,DPH,DPL 都丟到 stack 裏去。因為 keil 都會利用這些暫存器做一些運算,在進入 interrupt 時,也會主動 push 一些在 interrupt 會用到的暫存器到 stack 裏,但其它沒用到的暫存器就沒有主動 push,造成切換到其它 task 再切回原來 task 時,那些暫存器裏的值都被變更了,而造成運算錯誤。

  4. 另外在加入 assembly code 時,需把 Generate Assembler SRC File 及 Assemble SRC File 都打勾才可以,缺一不可。

1 意見

好強大阿~ 雖然我有看沒有懂 @@
有辦法指點迷津嗎 @@ 跪

張貼留言