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了