Small RTOS OSStart 函式解析
Small RTOS 是在 Keil C51 上面 編譯的。
看如下程式碼:
#include "config.h"
void main(void)
{
TMOD = (TMOD & 0XF0) | 0X01;
TL0 = 0x0;
TH0 = 0x0;
TR0 = 1;
ET0 = 1;
OSStart();
}
Keil C51 編譯器 在 程式進入main函式之前,會做如下的工作,
進入 main函式之後 ,
進入 OSStart() 函式:
程式碼如下:
void OSStart(void) { uint8 idata *cp; uint8 i; uint8 tmp ; cp = STACK; OSTsakStackBotton[0] = STACK; OSTsakStackBotton[OS_MAX_TASKS + 1] = (uint8 idata *)(IDATA_RAM_SIZE % 256); /* 初始化優先順序最高的任務堆疊,使返回地址為任務開始地址 */ /*SP PCL 然後 SP+1 PCH*/ tmp = cp ; *cp++ = ((uint16)(TaskFuction[0])) % 256; //低8位位元組 tmp = cp ; *cp = ((uint16)(TaskFuction[0])) / 256; //高8位位元組 /* 初始化優先順序最低的任務堆疊 */ cp = (uint8 idata *)(IDATA_RAM_SIZE - 1) ; tmp = cp ; *cp-- = 0; tmp = cp ; *cp-- = ((uint16)(OSIdle)) / 256; tmp = cp ; OSTsakStackBotton[OS_MAX_TASKS] = cp; *cp-- = ((uint16)(OSIdle)) % 256; tmp = cp ; /* 初始化其它優先順序的任務堆疊 */ for(i = OS_MAX_TASKS - 1; i > 0; i--) { *cp-- = 0; tmp = cp ; *cp-- = ((uint16)(TaskFuction[i])) / 256; tmp = cp ; OSTsakStackBotton[i] = cp; *cp-- = ((uint16)(TaskFuction[i])) % 256; tmp = cp ; } /* 允許中斷 */ Os_Enter_Sum = 1; OS_EXIT_CRITICAL(); /* 函式返回優先順序最高的任務 */ }
其中的
cp = STACK;
STACK 是經過C51 初始化之後,sp堆疊指標指向的RAM地址。
這樣 cp指標 也指向堆疊指標指向的RAM地址了。
Keil C51 在編譯的時候,會將全域性變數,區域性變數等都分配到RAM的某一個地址上去。
之後,RAM剩餘的地址,才會指定給sp指標,作為棧使用。
/* 初始化優先順序最高的任務堆疊,使返回地址為任務開始地址 */ /*SP PCL 然後 SP+1 PCH*/ tmp = cp ; *cp++ = ((uint16)(TaskFuction[0])) % 256; //低8位位元組 tmp = cp ; *cp = ((uint16)(TaskFuction[0])) / 256; //高8位位元組
這一部分程式碼的作用是 將 void TaskA(void) 函式的地址,放入堆疊中,
首先將地址的低8位位元組放入sp指向的地址,
然後sp+1 ,
將地址ide高8位位元組放入sp指向的地址。
這樣做的目的是 OSStart 返回之後,會執行 RET 彙編指令。
RET指令的作用如下:
這樣OSStart 會首先跳轉到 TaskA 函式中去。
檢視一下 :test.m51
OSTsakStackBotton 的地址:
D:0010H PUBLIC OSTsakStackBotton
I:0021H PUBLIC STACK
#define IDATA_RAM_SIZE 0x100
cp = (uint8 idata *)(IDATA_RAM_SIZE - 1) ;
cp指標指向了RAM的0xFF地址
函式指向完畢 跳轉到TaskA 去執行 :
void TaskA(void)
{
while (1)
{
OSWait(K_TMO,5);
}
}
進入 OSWait(K_TMO,5);
uint8 data OSTaskID = 0;
OSWaitTick[OSTaskID] = ticks; //ticks = 5
case K_TMO: /* 等待超時,即延時一段時間 */
OS_ENTER_CRITICAL();
while (OSWaitTick[OSTaskID] != 0) /* 判斷超時時間是否到 */
{
OSClearSignal(OSTaskID); /* 任務進入等待狀態 */
OSSched(); /* 執行下一個任務 */
}
OS_EXIT_CRITICAL();
return TMO_EVENT;
uint8 OSTaskRuning = 0xff; // 初始值
uint8 const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00};
OSTaskRuning &= ~OSMapTbl[TaskId]; //將對應的bit位清零
變為:0xfe了