tiny rtos for 8051 using SDCC part 3

Posted by: 邱小新 at 上午11:46 in , ,

原始碼下載

前言

在前面一個 tiny rtos 裏只是簡單平均分配時間到每一個 task 裏,但這有一個缺點,就是當某一個 task 需要暫停一下時,無法把時間交給其它的 task,這個時間無形間就被浪費掉了。所以在這一次新的 task 裏,加入了 rtos_delay_10ms 函數,讓 task 可以暫停一段時間,並把時間讓出來給別的 task。

  1. 把 timer0 的時間都切成 10ms,每一個 task 的運行時間都變成 10ms。
  2. 多了一個 rtos_tick 變數做 delay 的計數,以 10ms 為單位。

rtos_start

  1. 原本儲放 stack 的變數多了一個,用來放置 rtos_idle 的 stack。
  2. 第一個執行的 task 改成 rtos_idle,而非 task1。
  3. 由於 rtos_idle 沒做什麼事,所以只留一份必要的 stack 空間給它,其它的都分給其它 task。
  4. 不可以在此函數裏呼叫任何函數,因為呼叫函數會變更 stack 裏的內容(有 push 動作),這樣會把 task1 的 stack 破壞,造成進入 task1 時位置被變更,而跑不到 task1。
  5. 如果按照之前的方式,直接跳到 task1 執行,而不是從 rtos_idle 執行,就可以在此函數內呼叫其它函數,因為 stack 被破壞並不會影嚮 task1 的執行。
#define PUSH_SIZE 14 void rtos_start(void) { unsigned char i, size; __idata unsigned char *sp; // init stack size = (255 - SP - PUSH_SIZE - 2) >> 2; sp = (__idata unsigned char *)SP; for (i=0; i<MAX_TASKS; i++) { rtos_tick[i] = 0; *++sp = (unsigned int)task_func[i] & 0xff; *++sp = (unsigned int)task_func[i] >> 8; rtos_stack[i] = (unsigned char)sp + PUSH_SIZE; sp = sp + size - 2; } rtos_stack[MAX_TASKS] = (unsigned char)sp; // variable init rtos_task_id = MAX_TASKS; SP = rtos_stack[MAX_TASKS]; // timer0 init TMOD = (TMOD & 0xF0) | 0x01; TH0 = 0; TL0 = 0; TF0 = LOW; ET0 = HIGH; TR0 = HIGH; // jump to idle task rtos_idle(); }

rtos_idle

  1. rtos_idle 裏其實不沒做什麼事,就是一直進入 idle 模式以利省電。
  2. rtos_idle 裏不可以呼叫任何函數,因為保留給它的 stack 空間只夠做 task 切換而已,容不下其它的 push 指令。
static void rtos_idle(void) { while (1) { PCON |= 1; } }

rtos_nexttask

  1. rtos_nexttask 新增了計數功能,用來計算每一個 task delay 時間,當 rtos_tick==0 時,該 task 才擁有執行時間。
  2. 如果所有 task 都處於閒置狀態,就進入 idle task 等待其它 task 被喚醒。
  3. rtos_nexttask 裏不可以呼叫任何函數,因為如果遇到從 rots_idle 進入的 stack,它的 stack 空間只夠做 task 切換而已,容不下其它的 push 指令。
void rtos_nexttask(void) __naked { unsigned char i; _asm clr ea _endasm; // save current stack rtos_stack[rtos_task_id] = SP; // check tick for (i=0; i<MAX_TASKS; i++) { if (rtos_tick[i] > 0) rtos_tick[i]--; } // load next stack for (i=0; i<MAX_TASKS; i++) { if (++rtos_task_id >= MAX_TASKS) rtos_task_id = 0; if (rtos_tick[rtos_task_id] == 0) break; } if (i == MAX_TASKS) rtos_task_id = MAX_TASKS; SP = rtos_stack[rtos_task_id]; // restore register _asm pop _bp pop ar7 pop ar6 pop ar5 pop ar4 pop ar3 pop ar2 pop ar1 pop ar0 pop psw pop dpl pop dph pop b pop acc setb ea ret _endasm; }

執行結果

ABCDEFGHIJKLMNOPabcdefghijklmnopqrstuvwxyzQRSTUVWXYZ0123456789(0)SP = '1A' (1)SP = '53' (2)SP = '8C' (3)SP = 'C5' (4)SP = 'FE' abcdefghijklmnopABCDEFGHIJKLMNOPQRSTUVWXYZqrstuvwxyz0123456789(0)SP = '1A' (1)SP = '53' (2)SP = '8C' (3)SP = 'C5' (4)SP = 'FE' ABCDEFGHIJKLMNOPabcdefghijklmnopqrstuvwxyzQRSTUVWXYZ0123456789(0)SP = '1A' (1)SP = '53' (2)SP = '8C' (3)SP = 'C5' (4)SP = 'FE'

0 意見

張貼留言