📄 os_cpu_c.c
字号:
/*
中断中保存寄存器中的内容
*/
#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 + -