n久前的51_rtos原理实现测试源码

10 篇文章 2 订阅

初学时期写的代码,比较乱,希望对阅读本文的读者有所帮助。

代码是撇开了效率问题,为了方便理解任务切换过程,故都尽可能的使用了c实现的,而非汇编。

main.c

 

#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define TaskNumSize	3 
#define RamSize	255
uchar idata Wait[TaskNumSize+2];
uchar TaskRdy=0xff,CurTask,NxtTask;
uchar IntNestNum,CurTaskIsIdle,IntRetBit=0;


void IntCtxSw(uchar f);
void WaitDly(uint dly);
extern void RetiIns();
extern void PopIns();

void delay(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}

void taskA()
{
	static uchar temp,i;
	while(1)
	{
		temp=0x01;
		for(i=0;i<8;i++)
		{
			P1=temp;
			temp=temp<<1;
			WaitDly(10);
		}
	}
}
void taskB()
{
	static uchar temp;
	uchar i;	 //该局部变量不是局部静态变量,使该任务为不可重入函数
	P2=0;
	while(1)
	{
/*		temp=0x01;
		for(i=0;i<8;i++)
		{
			P2=temp;
			temp=temp<<1;
			WaitDly(20);
		}
*/		
		P2=0;
		if(i++>0x0f) i=0;
		P2=P2|i;
		WaitDly(30);
		if(temp++>0x0f) temp=0;
		P2=P2|(temp<<4);
		WaitDly(30);

	}
}
void taskC()
{
	static uchar temp,i;//各任务的局部变量设置为静态变量,使各任务的局部变量不受其它任务变量的影响而具有可重入性。
	uchar t;  			//该局部变量会和taskB中的局部变量i覆盖,从而t的值会影响taskB中的i值
	while(1)
	{
		temp=0x01;
		for(i=0;i<8;i++)
		{
			P3=temp;
			temp=temp<<1;
			WaitDly(50);
			P3=0;
			WaitDly(5);
			t++;
			P3=t;
			WaitDly(50);
			P3=0;
			WaitDly(5);
		}
	}
}


void InitTimer0()
{
	TMOD=0x01;//方式1,16位模式,不会自动清零。
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	TR0=1;
	ET0=1;
	EA=0;
}


void * const func[TaskNumSize]={taskA,taskB,taskC};
uchar idata *stk[TaskNumSize+1];


 void InitStartTask()
{
	uchar idata *sspp,i;
	sspp = (uchar idata *)SP+1;
	stk[0] = (uchar idata *)SP+1;			   
	stk[TaskNumSize] = (uchar idata *)RamSize;
	*sspp++ = ((uint)(func[0]))%256;
	*sspp = ((uint)(func[0]))/256;
	SP = (uchar)sspp;

	sspp = (uchar idata *)(RamSize-1);
	for(i=TaskNumSize-1;i>0;i--)
	{
		*sspp--=((uint)(func[i]))/256;
		stk[i]=sspp;
		*sspp--=((uint)(func[i]))%256;
	}
}

main()
{
	InitTimer0();
	InitStartTask();
//	while(1);
}

void IdleTask()
{
    while(1)
    {
        PCON = PCON | 0x01;                     /* CPU进入休眠状态 */
    }	
}

void IntCtxSw(uchar f)
{
	uchar idata *sp1,idata *sp2;
	uchar temp,i;		   
	uchar svsp;

	temp=TaskRdy;
	for(NxtTask=0;NxtTask<TaskNumSize;NxtTask++)
	{
		if((temp & 0x80)!=0)
			break;
		temp=temp<<1;
	}
	
	if(CurTaskIsIdle) SP=SP-19;

	svsp=(uchar)SP;

	if(!CurTaskIsIdle) //如果当前任务不是空闲任务时,才去设置中断返回标志位
	{
		if(f)
			IntRetBit |= (0x80>>CurTask);	
		else
			IntRetBit &= ~(0x80>>CurTask);
	}

	if(NxtTask<TaskNumSize)
	{	
		sp1=(uchar *)SP+1;
		sp2=stk[CurTask+1];	
		temp=(uchar)stk[NxtTask+1];
	
		if(NxtTask>CurTask)
		{
			while(sp2!=(uchar idata *)temp)
			{
				*sp1++=*sp2++;
			}
			SP=(uchar)sp1-1;
			temp=stk[CurTask+1]-(uchar idata *)svsp-1;
			for(i=CurTask+1;i<NxtTask+1;i++)
			{
				stk[i]-=temp;
			}	
		}
	 	if(NxtTask<CurTask)
		{
			sp1--;sp2--;
			while(sp1!=((uchar idata *)temp-1))
			{
				*sp2--=*sp1--;
			}
			SP=(uchar)stk[NxtTask+1]-1;
			temp=stk[CurTask+1]-(uchar idata *)svsp-1;
			for(i=NxtTask+1;i<CurTask+1;i++)
			{
				stk[i]+=temp;
			}	
		}
		if(NxtTask==CurTask)
			SP=svsp;	
		CurTask=NxtTask;
		CurTaskIsIdle=0;

		/*下面为4种不同的函数返回方式*/
		EA=1;
		if(f)	
		{
			if(IntRetBit & (0x80>>CurTask))
				return;
			else
				RetiIns();
		}
		else
		{
		 	if(IntRetBit & (0x80>>CurTask))
			{
				SP=SP-4;
				PopIns();
			}
			else
				return;
		}

	}

 	CurTaskIsIdle=1;	
	*((uchar idata *)++SP)=(uint)IdleTask%256;
	*((uchar idata *)++SP)=(uint)IdleTask/256;
	EA=1;
	if(f)	RetiIns();
		 
}

void WaitDly(uint dly)
{
	 Wait[CurTask]=dly;
	 while(Wait[CurTask]!=0)
	 {
	 	TaskRdy &= ~(0x80>>CurTask);
		EA=0;
	 	IntCtxSw(0);
	 }
}

void Tick()
{
	uchar prio;
	for(prio=0;prio<TaskNumSize;prio++)
	{
		if(Wait[prio]>0)
		{
			Wait[prio]--;
			if(Wait[prio]==0)
				TaskRdy |= (0x80>>prio);
		 }
	}
}

void IntExitSw()
{
	if(IntNestNum>0)
		IntNestNum--; 
	if(IntNestNum==0)
		IntCtxSw(1);	
}
void EnterInt()
{
	if(IntNestNum<255)
		IntNestNum++;
}
void timer0() interrupt 1
{
	EA=0;
	EnterInt();	
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	Tick();
	IntExitSw();	
}

int.s

	NAME    EX_ASM

?PR?RETIINS?EX                     SEGMENT CODE
?PR?POPINS?EX                     SEGMENT CODE

PUBLIC  RETIINS
PUBLIC  POPINS


RSEG  ?PR?RETIINS?EX
RetiIns:	   
	MOV	A,#(-2)
	ADD	A,SP
	MOV	SP,A 
	RETI


RSEG  ?PR?POPINS?EX
PopIns:	   
	MOV	A,#(-2)
	ADD	A,SP
	MOV	SP,A
	POP 7
	POP 6
	POP 5
	POP 4
	POP 3
	POP 2
	POP 1
	POP 0
	POP PSW
	POP DPL
	POP DPH
	POP B
	POP	ACC

	RET

END

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值