基于时间片的52操作系统
本帖最后由 zjsxwc 于 2013-3-21 16:53 编辑今天在看了rainyss大神的帖子后,在我的52上写了个调度器。#include <reg52.h>
#define MAX_TASKS 3
#define MAX_TASK_DEP 24
unsigned char idata task_stack={0};
unsigned char idata * task_sp;
unsigned char idatatask_old={0};
unsigned char task_id;
unsigned char idata task_die={0};
unsigned char task_time_slice={
{0xC0,0xFF},//ʱ¼äƬ
{0xC2,0xFF},
{0xC1,0xFF},
};
void Task_clear_REG(){
ACC=0;
B=0;
PSW=0;
}
void Start_Timer2(){
EXEN2=0;
C_T2=0;
RCLK=0;
TCLK=0;
CP_RL2=0;
RCAP2L=task_time_slice;
RCAP2H=task_time_slice;
TL2=task_time_slice;
TH2=task_time_slice;
PT2=1;
TR2=1;
ET2=1;
EA=1;
}
void Init_OS(){
Start_Timer2();
}
void Kill_task(unsigned char tid){
task_die=1;
}
void Revive_task(unsigned char tid){
task_die=0;
}
void task_load(unsigned int fn, unsigned char tid){
task_sp = task_stack + 1;
task_stack = (unsigned int)fn & 0xff;
task_stack = (unsigned int)fn >> 8;
}
#define os_start(tid) {task_id = tid,SP = task_sp;return;}
void task1()
{
static unsigned char i;
while(1){
i++;
}
}
void task2()
{
static unsigned char j;
while(1){
j+=1;
j+=2;
j+=3;
j+=4;
j+=5;
j+=6;
j+=7;
j*=8;
j+=9;
j+=10;
j+=55;
j+=767;
j+=2;
j+=2;
j+=44;
j*=3;
j+=1;
j+=66;
j*=43;
j+=7;
j+=98;
j*=7;
j+=332;
j+=44;
j+=33;
j+=324;
Kill_task(1);//finish task2,and suicide
}
}
void task3(){
static unsigned char k;
while(1){
k+=3;
}
}
void main(){
task_load(task1, 0);
task_load(task2, 1);
task_load(task3, 2);
Init_OS();
os_start(0);
}
void task_switch() interrupt 5
{
unsigned charR={0};//let keil C51 know that R0--R7/B/acc/psw/dptr must be push\pop in the stack!
TR2=0;
task_old=1;
task_sp=SP;
while(1){
if(++task_id == MAX_TASKS)
task_id = 0;
if (task_die!=1) break;
}
if (task_old)
SP=task_sp;
else{
*(task_sp+1)=0;//acc
*(task_sp+2)=0;//B
*(task_sp+3)=0;//dpoh
*(task_sp+4)=0;//dpol
*(task_sp+5)=0;//psw
*(task_sp+6)=0;//r0
*(task_sp+7)=0;//r1
*(task_sp+8)=0;//r2
*(task_sp+9)=0;//r3
*(task_sp+10)=0;//r4
*(task_sp+11)=0;//r5
*(task_sp+12)=0;//r6
*(task_sp+13)=0;//r7
task_sp=task_sp+13;
SP = task_sp;
}
TF2=0;
TL2=task_time_slice;
TH2=task_time_slice;
TR2=1;
return;
}已改,由于使用中断服务函数时C51会自动保持ACC\PSW\B\R0--R7\dptr到相应任务堆栈所以省下了开辟空间保证这些寄存器的事情. 移植了操作系统吗 本帖最后由 zjsxwc 于 2013-3-20 21:39 编辑
占用了52的T2计时器 以及 level 1特权的中断。 沙漏 发表于 2013-3-20 18:26 static/image/common/back.gif
移植了操作系统吗
只是由原来手动切任务,变成按时间片自动切任务,利用了52多出来的T2计数器。 R0~R7、PSW、ACC等重要寄存器没保存,任务切换会死人的。
你的测试程序例子太简单,所以你没看出来问题。 本帖最后由 zjsxwc 于 2013-3-21 16:30 编辑
barryliu 发表于 2013-3-21 09:42 static/image/common/back.gif
R0~R7、PSW、ACC等重要寄存器没保存,任务切换会死人的。
你的测试程序例子太简单,所以你没看出来问题。 ...
多谢提醒,
已修改源程序 本帖最后由 zjsxwc 于 2013-3-21 16:48 编辑
实现了寄存器组的保存,防止了寄存器不同任务间的重用。
剩下的问题就是函数重入问题,对于函数重入问题也只能以宏代替或者使用那个重用函数关键字reentrant 在我的52上测试,基本没有问题了,不过每个task中的变量都要是static的,否则keil生成汇编时可能会为不同变量分配相同地址。
页:
[1]