⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu_c.c

📁 我移植的uCos 2.86 版本,可以在单片51上运行,在AT89C51ED2上测试过.
💻 C
📖 第 1 页 / 共 2 页
字号:

/*
中断中保存寄存器中的内容
*/
#if 1
#pragma ASM
SaveSFR MACRO   REG
	PUSH 	ACC
	PUSH 	B
	PUSH 	DPH
	PUSH 	DPL
	XRL  	AUXR1,#01H
	PUSH 	DPH
	PUSH 	DPL
	PUSH 	PSW
	MOV  	PSW,#00H
	PUSH 	AR0
	PUSH 	AR1
	PUSH 	AR2
	PUSH 	AR3
	PUSH 	AR4
	PUSH 	AR5
	PUSH 	AR6
	PUSH 	AR7
	ENDM
#pragma ENDASM

#pragma ASM
PopSFR MACRO   REG
	POP  	AR7
	POP  	AR6
	POP  	AR5
	POP  	AR4
	POP  	AR3
	POP  	AR2
	POP  	AR1
	POP  	AR0
	POP  	PSW
	POP  	DPL
	POP  	DPH
	XRL  	AUXR1,#01H
	POP  	DPL
	POP  	DPH
	POP 	B
	POP  	ACC
	ENDM
#pragma ENDASM

#endif
extern void SaveCtx(INT8U XDAT *xRam,INT8U IDAT *iRam,INT8U n);
extern void LoadCtx(INT8U XDAT *xRam,INT8U IDAT *iRam,INT8U n);
#define Push(A)  *(EX_Stk++) = ((INT8U)(A))
//sfr16  DPTR		 =   0x81;
INT8U RDAT PCH,PCL;

OS_STK  *OSTaskStkInit (void (CDAT *task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
{
INT8U XDAT * RDAT EX_Stk;
/* 
调用void Task(void *p_arg)  时,代码如下
	MOV  	R3,#01H			//类型值,见far
	MOV  	R2,#HIGH (b)	//
	MOV  	R1,#LOW (b)		//
	LCALL	_Task1	进入函数后保存R1,R2,R3
中断时
	SP+1→SP,
	PCL→(SP),
	SP+1→SP, 
	PCH→(SP),
	addr16→PC
IRS 会做以下动作
	PUSH 	ACC,B,DPH,DPL, 
	XRL AUXR1,#01H
	PUSH 	DPH,DPL,PSW
	MOV  	PSW,#00H	
	PUSH 	AR0....AR7
注意: MCS51 分别有硬件栈及软件栈,硬件栈SP,软件栈有C_IBP,C_PBP,C_XBP,
        由不同的编译模式决定,均为从高向低生长,所以在切换任务
        时,应注意保护其它的堆栈做法是 --xBP,data -> *xbp.
        当然,你还可以保存更多的东西
*/
			   /* C_IBP  *--CIBP */
	//Ext_Stack_Top = ptos;
	EX_Stk = ptos;
	//EX_Stk+=18;
	Push(17);		// HW to SP	
	Push(0);		// number of SW_STK	 
	
	Push(task);
	Push((INT16U)task >> 8);	
	Push(0x0A);				// ACC
	Push(0x0B);				// B
	Push(0x1D);				//DPTH
	Push(0x0D);				//DPTL
	//AUXR1^=01;
	Push(0x4D);				//DPTH2
	Push(0x3D);				//DPTL2
	Push(PSW);				//PSW
	//PSW = 00H;
	Push(0x10);				//R0 to R7
	Push(ptos);
	Push((INT16U)ptos >> 8);
	Push(0x01);				//R3
	Push(0x14);
	Push(0x15);
	Push(0x16);
	Push(0x17);

	  	

    return (ptos);
                                                    /* Return the stack pointer to the new tasks stack          */
}

//extern void LoadCtx();   /* Save the current working registers to stack, defined in OS_CPU_A.ASM */

/**********************************************************************************************************
这两个函数是做堆栈切换的,不同的是一个是从中断中调用的
另一个是从中断外调用的,所以从中断外调用的要比中断中调用的多
一个把相关寄存器保存的过程
***********************************************************************************************************/
void OSCtxSw(void)    
{
	INT8U RDAT HW_Cnt,SW_Cnt;
// 1 保存相关的寄存器内容,因为C中难操作所以用汇编
#pragma ASM
;	POP	PCH
;	POP	PCL
	SaveSFR
#pragma ENDASM	
// 2 转存硬件堆栈
	
	HW_Cnt = SP - (INT8U)(HW_STAKE-1);
	*Ext_Stack_Top = HW_Cnt;	// get the point
	SaveCtx(Ext_Stack_Top+2,HW_STAKE,HW_Cnt);
// 3 转存软件堆栈
	//SW_Cnt = 0 - (INT8U)C_IBP;
	#pragma ASM
	MOV  	A,?C_IBP
	CPL  	A
	INC  	A
	#pragma ENDASM
	SW_Cnt = ACC;
	*(Ext_Stack_Top+1) = SW_Cnt;	//// save the number of the HW_STKs 
	SaveCtx(Ext_Stack_Top+2+HW_Cnt,-SW_Cnt,SW_Cnt);
// 4 得到新的堆栈指针
    OSTCBCur->OSTCBStkPtr = Ext_Stack_Top;	//分配给任务的空间,用于保存硬件栈及软件栈
	OSTaskSwHook();
    OSTCBCur  = OSTCBHighRdy;
    OSPrioCur = OSPrioHighRdy;
    Ext_Stack_Top = OSTCBCur->OSTCBStkPtr;
// 5 载入新的软件堆栈	
	HW_Cnt = *Ext_Stack_Top;
	SW_Cnt = *(Ext_Stack_Top+1); 
	//C_IBP = (INT8U IDAT *) (-SW_Cnt);
	ACC = SW_Cnt;
	#pragma ASM	
	CPL  	A
	INC  	A
	MOV  	?C_IBP,A
	#pragma ENDASM
	LoadCtx(Ext_Stack_Top+2+HW_Cnt,-SW_Cnt,SW_Cnt);
// 6 截入新的硬件堆栈
	SP = HW_Cnt + (INT8U)(HW_STAKE-1);	
	LoadCtx(Ext_Stack_Top+2,SP-HW_Cnt+1,HW_Cnt);
//	ACC = B;	 
// 7 载入新的寄存器内容
#pragma ASM
	PopSFR
;	PUSH PCL
;	PUSH PCH
#pragma ENDASM	
}

void OSIntCtxSw(void) 
{
	INT8U RDAT HW_Cnt,SW_Cnt;
#pragma ASM
	POP	PCH
	POP	PCL
	POP	PCH
	POP	PCL
#pragma ENDASM	

// 2 转存硬件堆栈	
	HW_Cnt = SP - (INT8U)(HW_STAKE-1);
	*Ext_Stack_Top = HW_Cnt;	// get the point
	SaveCtx(Ext_Stack_Top+2,HW_STAKE,HW_Cnt);
// 3 转存软件堆栈
	//SW_Cnt = 0 - (INT8U)C_IBP;
	#pragma ASM
	MOV  	A,?C_IBP
	CPL  	A
	INC  	A
	#pragma ENDASM
	SW_Cnt = ACC;
	*(Ext_Stack_Top+1) = SW_Cnt;	//// save the number of the HW_STKs 
	SaveCtx(Ext_Stack_Top+2+HW_Cnt,-SW_Cnt,SW_Cnt);
// 4 得到新的堆栈指针
    OSTCBCur->OSTCBStkPtr = Ext_Stack_Top;	//分配给任务的空间,用于保存硬件栈及软件栈
	OSTaskSwHook();
    OSTCBCur  = OSTCBHighRdy;
    OSPrioCur = OSPrioHighRdy;
    Ext_Stack_Top = OSTCBCur->OSTCBStkPtr;
// 5 载入新的软件堆栈	
	HW_Cnt = *Ext_Stack_Top;
	SW_Cnt = *(Ext_Stack_Top+1); 
	//C_IBP = (INT8U IDAT *) (-SW_Cnt);	
	ACC = SW_Cnt;
	#pragma ASM	
	CPL  	A
	INC  	A
	MOV  	?C_IBP,A
	#pragma ENDASM
	LoadCtx(Ext_Stack_Top+2+HW_Cnt,-SW_Cnt,SW_Cnt);
// 6 截入新的硬件堆栈
	SP = HW_Cnt + (INT8U)(HW_STAKE-1);	
	LoadCtx(Ext_Stack_Top+2,SP-HW_Cnt+1,HW_Cnt);
#pragma ASM
	PopSFR
	RETI
#pragma ENDASM	

}

/*
***********************************************************************************************************
* OSStartHighRdy: START MULTITASKING
*     
* Duty:     a) Call OSTaskSwHook() then,
*           b) Set OSRunning to TRUE,
*           c) Switch to the highest priority task.
*
***********************************************************************************************************
*/

void OSStartHighRdy(void)
{
	INT8U RDAT HW_Cnt,SW_Cnt;
    OSTaskSwHook();
	OSRunning=1;
	Ext_Stack_Top = OSTCBHighRdy->OSTCBStkPtr;
	// 5 载入新的软件堆栈	
	HW_Cnt = *Ext_Stack_Top;
	SW_Cnt = *(Ext_Stack_Top+1); 
	//C_IBP = (INT8U IDAT *) (-SW_Cnt);			
	ACC = SW_Cnt;
	#pragma ASM	
	CPL  	A
	INC  	A
	MOV  	?C_IBP,A
	#pragma ENDASM
	LoadCtx(Ext_Stack_Top+2+HW_Cnt,-SW_Cnt,SW_Cnt);
// 6 截入新的硬件堆栈
	SP = HW_Cnt + (INT8U)(HW_STAKE-1);	
	LoadCtx(Ext_Stack_Top+2,SP-HW_Cnt+1,HW_Cnt);
//	ACC = B;
#pragma ASM
	PopSFR
	RETI
#pragma ENDASM	
}

void OSTickISR(void) interrupt BSP_OS_TMR_SEL
{
TH0=(OS_Time_Count)>>8;
TL0+=OS_Time_Count;
/* Do this first */
    OSIntNesting++;                      /* Increment ISR nesting level directly to speed up processing */
//	OSIntEnter();					/* Must be called first at every hardware interrupt entry point */
//    if(OSIntNesting==1)                     /* Only at the outerest interrupt we do these. */
//		{
//       OSTCBCur->OSTCBStkPtr = Ext_Stack_Top;	/* OSTCBCur->OSTCBStkPtr is free now, so it can be used to story the value of SP */
//    	}
   	OSTimeTick();					/* Must be called during tick isr */
   	OSIntExit();					/* Must be called finally at every hardware interupt exit point */		
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -