原始碼下載
前言
在前面一個 tiny rtos 裏只是簡單平均分配時間到每一個 task 裏,但這有一個缺點,就是當某一個 task 需要暫停一下時,無法把時間交給其它的 task,這個時間無形間就被浪費掉了。所以在這一次新的 task 裏,加入了 rtos_delay_10ms 函數,讓 task 可以暫停一段時間,並把時間讓出來給別的 task。
- 把 timer0 的時間都切成 10ms,每一個 task 的運行時間都變成 10ms。
- 多了一個 rtos_tick 變數做 delay 的計數,以 10ms 為單位。
rtos_start
- 原本儲放 stack 的變數多了一個,用來放置 rtos_idle 的 stack。
- 第一個執行的 task 改成 rtos_idle,而非 task1。
- 由於 rtos_idle 沒做什麼事,所以只留一份必要的 stack 空間給它,其它的都分給其它 task。
- 不可以在此函數裏呼叫任何函數,因為呼叫函數會變更 stack 裏的內容(有 push 動作),這樣會把 task1 的 stack 破壞,造成進入 task1 時位置被變更,而跑不到 task1。
- 如果按照之前的方式,直接跳到 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> 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
- rtos_idle 裏其實不沒做什麼事,就是一直進入 idle 模式以利省電。
- rtos_idle 裏不可以呼叫任何函數,因為保留給它的 stack 空間只夠做 task 切換而已,容不下其它的 push 指令。
static void rtos_idle(void)
{
while (1)
{
PCON |= 1;
}
}
rtos_nexttask
- rtos_nexttask 新增了計數功能,用來計算每一個 task delay 時間,當 rtos_tick==0 時,該 task 才擁有執行時間。
- 如果所有 task 都處於閒置狀態,就進入 idle task 等待其它 task 被喚醒。
- 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 0) rtos_tick[i]--;
}
// load next stack
for (i=0; i= 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'
張貼留言