uCOS移植代码 for 8051
OS_CPU_C.C
/*
********************************************************************************
* INItiALIZE A TASK'S STACK
* Description: This function is called by either OSTaskCreate() or
OSTaskCreateExt() to initialize the
* stack frame of the task being created. This function is highly
processor specific.
* Arguments : task is a pointer to the task code
* os_pdata is a pointer to a user supplied data area that
will be passed to the task
* when the task first executes.
* ptos is a pointer to the top of stack. It is assumed
that 'ptos' points to
* a 'free' entry on the task stack. If
OS_STK_GROWTH is set to 1 then
* 'ptos' will contain the HIGHEST valid address of
the stack. Similarly, if
* OS_STK_GROWTH is set to 0, the 'ptos' will
contains the LOWEST valid address
* of the stack.
* opt specifies options that can be used to alter the
behavior of OSTaskStkInit().
* (see uCOS_II.H for OS_TASK_OPT_???).
* Returns : Always returns the location of the new top-of-stack' once the
processor registers have
* been placed on the stack in the proper order.
* Note(s) : Interrupts are enabled when your task starts executing. You can
change this by setting the
* PSW to 0x0002 instead. In this case, interrupts would be
disabled upon task startup. The
* application code would be responsible for enabling interrupts at
the beginning of the task
* code. You will need to modify OSTaskIdle() and OSTaskStat() so
that they enable
* interrupts. Failure to do this will make your system crash!
********************************************************************************
*/
/*
at89c55wd PDL(sp form LOW to HIGH): (堆栈指针所指的栈顶数据为有效数据)
装入堆栈指针ptos到stkstk--> 入栈:task底高 (高内存)
入 || 入栈:ACC
栈 || 入栈:B
顺 || 入栈:DPH
//暂时忽略第二指针
序 || 入栈:DPL
| / | 入栈:PSW
| | 入栈:R7-
R4
|______| 入栈:os_pdata(R3,R2,R1)用寄存器传递os_pdata
入栈:R0 (底内存)
// 入栈:
DPS?? //双数据指针选择寄存器??
// 入栈:PC
自己应该参照编译器定义入栈/出栈顺序,写出来备以后查阅
*/
OS_STK *OSTaskStkInit (void (*task)(void *pd)LG_REENTRANT, void *os_pdata,
OS_STK *ptos, INT16U opt) LG_REENTRANT
{
//INT16U *stk;
OS_STK *stk;
opt = opt; /* 'opt' is not used, prevent
warning */
stk = (OS_STK *)ptos; /* Load stack
pointer */
//装入堆栈指针ptos到stk
*stk = 0;
//入栈:R0
stk -= sizeof(void *);
*(void **)stk = (void *)os_pdata; //用寄存器传递
os_pdata
*--stk = 4;
//入栈:R4-R7
*--stk = 5;
*--stk = 6;
*--stk = 7;
*--stk = PSW;
//入栈:PSW
*--stk = 'L';
//入栈:DPL
*--stk = 'H';
//入栈:DPH //暂时忽略第二指针
*--stk = 'B';
//入栈:B
*--stk = 'A';
//入栈:ACC
*--stk = ((INT16U)task & 0xff00) >> 8; //保存任务地址
*--stk = (INT16U)task & 0x00ff;
*--stk = 15;
//入栈个数
//END
return ((OS_STK *)stk);
}
/*$PAGE*/
/*
********************************************************************************
* INITIALIZE A TASK'S STACK FOR FLOATING POINT EMULATION
********************************************************************************
*/
/*$PAGE*/
//void OSTaskStkInit_FPE_x86 (OS_STK **pptos, OS_STK **ppbos, INT32U *psize)
//{
//}
/*$PAGE*/
/*
********************************************************************************
* TASK SWITCH HOOK
*
* Description: This function is called when a task switch is performed. This
allows you to perform other
* operations during a context switch.
*
* Arguments : none
*
* Note(s) : 1) Interrupts are disabled during this call.
* 2) It is assumed that the global pointer 'OSTCBHighRdy' points
to the TCB of the task that
* will be 'switched in' (i.e. the highest priority task)
and, 'OSTCBCur' points to the
* task being switched out (i.e. the preempted task).
********************************************************************************
*************************
*/
#if OS_CPU_HOOKS_EN > 0
void OSTaskSwHook (void) LG_REENTRANT
{
}
#endif
/*
********************************************************************************
* OSTCBInit() HOOK
*
* Description: This function is called by OS_TCBInit() after setting up most of
the TCB.
*
* Arguments : ptcb is a pointer to the TCB of the task being created.
*
* Note(s) : 1) Interrupts may or may not be ENABLED during this call.
********************************************************************************
*************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSTCBInitHook (OS_TCB *ptcb) LG_REENTRANT
{
ptcb = ptcb; /* Prevent Compiler
warning */
}
#endif
/*
********************************************************************************
* TICK HOOK
*
* Description: This function is called every tick.
*
* Arguments : none
*
* Note(s) : 1) Interrupts may or may not be ENABLED during this call.
********************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0
void OSTimeTickHook (void) LG_REENTRANT
{
}
#endif
/*
********************************************************************************
*************************
*
中断服务程序外挂
* NOTE : 注意:所有中断外挂都在临界区之外,用户可以自行控制进/退
临界区
********************************************************************************
*/
#if OS_ISR_T1_EN > 0
void OSISR_T1HOOK (void) LG_REENTRANT
{
/* 请在这里输入中断服务程序
*/
}
#endif
#if OS_ISR_INT0_EN > 0
void OSISR_INT0HOOK (void) LG_REENTRANT
{
/* 请在这里输入中断服务程序
*/
}
#endif
#if OS_ISR_INT1_EN > 0
void OSISR_INT1HOOK (void) LG_REENTRANT
{
/* 请在这里输入中断服务程序
*/
}
#endif
#if OS_ISR_S0_EN > 0
void OSISR_S0HOOK (void) LG_REENTRANT
{
/* 请在这里输入中断服务程序
*/
}
#endif
----------------
*******************************************************************************
*************************
uC/OS-II
The Real-Time Kernel
(c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
All Rights Reserved
at89c55wd Specific code
LARGE MEMORY MODEL
keil C/C++ V7.2
(at89c55wd Compatible Target)
File : OS_CPU_A.ASM
By : Jean J. Labrosse
Port by : 牛毅 2005-04-25->2005-04-28
QQ:75011221 niuyimail@126.com
修补 : 2005-05-02-01:30 (增加了中断管理和临界区宏)
修补 : 2005-05-16-13:00 (修补_CopySPtoC_XBP的漏洞, 有标记
处%%%%????%%%%%%)
*******************************************************************************
*************************
#include "OS_CFG.H"
NAME OS_CPU_A
*******************************************************************************
*************************
要使用的外部函数和公共数据
*******************************************************************************
*************************
EXTRN CODE (_?OSIntExit)
EXTRN CODE (_?OSTimeTick)
EXTRN CODE (_?OSTaskSwHook)
IF OS_ISR_T1_EN <> 0
EXTRN CODE (_?OSISR_T1HOOK)
ENDIF
IF OS_ISR_INT0_EN <> 0
EXTRN CODE (_?OSISR_INT0HOOK)
ENDIF
IF OS_ISR_INT1_EN <> 0
EXTRN CODE (_?OSISR_INT1HOOK)
ENDIF
IF OS_ISR_S0_EN <> 0
EXTRN CODE (_?OSISR_S0HOOK)
ENDIF
EXTRN DATA (?C_XBP)
DT?C_XBP SEGMENT DATA
RSEG DT?C_XBP
?C_XBP:
C_XBP:
DS 1
?STACK SEGMENT IDATA
RSEG ?STACK
?STACK:
Stack:
DS 40
EXTRN BIT (OSRunning)
EXTRN XDATA (OSIntNesting)
EXTRN XDATA (OSTickDOSCtr)
EXTRN XDATA (OSPrioHighRdy)
EXTRN XDATA (OSPrioCur)
EXTRN XDATA (OSTCBCur)
EXTRN XDATA (OSTCBHighRdy)
*******************************************************************************
*************************
MACRO DEFINE
*******************************************************************************
*************************
PUSHALL MACRO
PUSH PC
PUSH ACC
PUSH B
PUSH DPH
PUSH DPL
PUSH PSW
IRP REG,
MOV A, REG
PUSH ACC
ENDM
ENDM
POPALL MACRO
IRP REG,
POP ACC
MOV REG, A
ENDM
POP PSW
POP DPL
POP DPH
POP B
POP ACC
RET/RETI
ENDM
OS_ENTER_CRITICAL MACRO
MOV B,IE ;因为所有程序没有使用
B寄存器,所以使用了B寄存器作为IE暂存
CLR EA
ENDM
OS_EXIT_CRITICAL MACRO
MOV IE,B ;因为所有程序没有使用
B寄存器,所以使用了B寄存器作为IE暂存
ENDM
*******************************************************************************
*************************
供外部使用的函数
*******************************************************************************
*************************
PUBLIC _?OSTickISR
PUBLIC _?OSStartHighRdy
PUBLIC _?OSCtxSw
PUBLIC _?OSIntCtxSw
/*$PAGE*/
*******************************************************************************
*************************
函数体段
*******************************************************************************
*************************
*******************************************************************************
**************************
用户中断程序区 之 定时器中断
1 OSISR_T1()
*******************************************************************************
**************************
IF OS_ISR_T1_EN <> 0
CSEG AT 001BH ;设置T0中断向量
LJMP _OSISR_T1
?PR?_OSISR_T1?OS_CPU_A SEGMENT CODE
RSEG ?PR?_OSISR_T1?OS_CPU_A
_OSISR_T1:
OS_ENTER_CRITICAL
(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
PUSHALL
LCALL _CopySPtoC_XBP ;COPY SP 的内容到?
C_XBP
(2)记忆中断的嵌套层OSIntNesting++ 进入中断
(3) if (OSIntNesting == 1)
OSTCBCur->OSTCBStkPtr <= ?C_XBP
LCALL _Enter_INT
OS_EXIT_CRITICAL
(4)调用中断服务外挂
LCALL _?OSISR_T1HOOK ;在这里进行中断服务
OS_ENTER_CRITICAL
(5) Call OSTimeTick();
LCALL _?OSTimeTick
(6) Call OSIntExit();
LCALL _?OSIntExit
(7) 恢复处理器寄存器 ;没有高优先级任务在就
绪队列中
LCALL _ComCtxSw2
LCALL _CopyC_XBPtoSP
POPALL
OS_EXIT_CRITICAL
RETI
ENDIF
*******************************************************************************
**************************
用户中断程序区 之 外部中断0
OSISR_INT0()
*******************************************************************************
**************************
IF OS_ISR_INT0_EN <> 0
CSEG AT 0003H ;设置T0中断向量
LJMP _OSISR_INT0
?PR?_OSISR_INT0?OS_CPU_A SEGMENT CODE
RSEG ?PR?_OSISR_INT0?OS_CPU_A
_OSISR_INT0:
OS_ENTER_CRITICAL
(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
PUSHALL
LCALL _CopySPtoC_XBP ;COPY SP 的内容到?
C_XBP
(2)记忆中断的嵌套层OSIntNesting++ 进入中断
(3) if (OSIntNesting == 1)
OSTCBCur->OSTCBStkPtr <= ?C_XBP
LCALL _Enter_INT
OS_EXIT_CRITICAL
(4)调用中断服务外挂
LCALL _?OSISR_INT0HOOK ;在这里进行中断服务
OS_ENTER_CRITICAL
(5) Call OSTimeTick();
LCALL _?OSTimeTick
(6) Call OSIntExit();
LCALL _?OSIntExit
(7) 恢复处理器寄存器 ;没有高优先级任务在就绪队列中
LCALL _ComCtxSw2
LCALL _CopyC_XBPtoSP
POPALL
OS_EXIT_CRITICAL
RETI
ENDIF
*******************************************************************************
**************************
用户中断程序区 之 外部中断1
OSISR_INT1()
*******************************************************************************
**************************
IF OS_ISR_INT1_EN <> 0
CSEG AT 0013H ;设置T0中断向量
LJMP _OSISR_INT1
?PR?_OSISR_INT1?OS_CPU_A SEGMENT CODE
RSEG ?PR?_OSISR_INT1?OS_CPU_A
_OSISR_INT1:
OS_ENTER_CRITICAL
(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
PUSHALL
LCALL _CopySPtoC_XBP ;COPY SP 的内容到?
C_XBP
(2)记忆中断的嵌套层OSIntNesting++ 进入中断
(3) if (OSIntNesting == 1)
OSTCBCur->OSTCBStkPtr <= ?C_XBP
LCALL _Enter_INT
OS_EXIT_CRITICAL
(4)调用中断服务外挂
LCALL _?OSISR_INT1HOOK ;在这里进行中断服务
OS_ENTER_CRITICAL
(5) Call OSTimeTick();
LCALL _?OSTimeTick
(6) Call OSIntExit();
LCALL _?OSIntExit
(7) 恢复处理器寄存器 ;没有高优先级任务在就绪队列中
LCALL _ComCtxSw2
LCALL _CopyC_XBPtoSP
POPALL
OS_EXIT_CRITICAL
RETI
ENDIF
*******************************************************************************
**************************
用户中断程序区 之 串口中断0
OSISR_S0()
*******************************************************************************
**************************
IF OS_ISR_S0_EN <> 0
CSEG AT 0023H ;设置T0中断向量
LJMP _OSISR_S0
?PR?_OSISR_S0?OS_CPU_A SEGMENT CODE
RSEG ?PR?_OSISR_S0?OS_CPU_A
_OSISR_S0:
OS_ENTER_CRITICAL
(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP
PUSHALL
LCALL _CopySPtoC_XBP ;COPY SP 的内容到?
C_XBP
(2)记忆中断的嵌套层OSIntNesting++ 进入中断
(3) if (OSIntNesting == 1)
OSTCBCur->OSTCBStkPtr <= ?C_XBP
LCALL _Enter_INT
OS_EXIT_CRITICAL
(4)调用中断服务外挂
LCALL _?OSISR_S0HOOK ;在这里进行中断服务
OS_ENTER_CRITICAL
(5) Call OSTimeTick();
LCALL _?OSTimeTick
(6) Call OSIntExit();
LCALL _?OSIntExit
(7) 恢复处理器寄存器 ;没有高优先级任务在就绪队列中
LCALL _ComCtxSw2
LCALL _CopyC_XBPtoSP
POPALL
OS_EXIT_CRITICAL
RETI
ENDIF
*******************************************************************************
**************************
START MULTITASKING
void OSStartHighRdy(void) LG_REENTRANT
出栈后就意味着启动了第一个任务
The stack frame is assumed to look as follows:
出 / 出栈:task
底高 (高内存)
栈 || 出栈:ACC
顺 || 出栈:B
序 || 出栈:DPH
//暂时忽略第二指针
| || | 出栈:DPL
| | 出栈:PSW
|______________| 出栈:R7-R4
出栈:
os_pdata(R3,R2,R1)用寄存器传递os_pdata
OSTCBHighRdy->OSTCBStkPtr --> 出栈:R0
(底内存)
Note : OSStartHighRdy() MUST:
a) Call OSTaskSwHook() then,
b) Set OSRunning to TRUE,
c) Switch to the highest priority task.
*******************************************************************************
**************************
?PR?_?OSStartHighRdy?OS_CPU_A SEGMENT CODE
第3个问号表示重入函
数
RSEG ?PR?_?OSStartHighRdy?OS_CPU_A ;函数体段
_?OSStartHighRdy:
USING 0
OS_ENTER_CRITICAL
LCALL _?OSTaskSwHook ;调用OSTaskSwHook();
SETB OSRunning ;OSRunning= TRUE;
切换到最高优先级的任务
JMP CtxSw ;MOV ?C_XBP,0
*******************************************************************************
**************************
PERFORM A CONTEXT SWITCH (From task level)
void OSCtxSw(void)
Note(s): 1) Upon entry,
OSTCBCur points to the OS_TCB of the task to suspend
OSTCBHighRdy points to the OS_TCB of the task to resume
2) The stack frame of the task to suspend looks as follows:
SP -> OFFSET of task to suspend (Low memory)
SEGMENT of task to suspend
PSW of task to suspend (High memory)
3) The stack frame of the task to resume looks as follows:
出 / 用RET 出栈:task底高地址 (高内存)
栈 || 出栈:ACC
顺 || 出栈:B
序 || 出栈:DPH
//暂时忽略第二指针
| || | 出栈:DPL
| | 出栈:PSW
|______________| 出栈:R0
出栈:os_pdata
(R1,R2,R3)用寄存器传递os_pdata
OSTCBHighRdy->OSTCBStkPtr --> 出栈:R4-R7
(底内存)
Flags to load in
PSW (High memory)
任务级切换:
1:PUSHALL
2:?C_BXP<=(SP)
3:OSTCBCur->OSTCBStkPtr<=?C_BXP
4: ...
5:?C_BXP<=OSTCBHighRdy->OSTCBStkPtr
6:(SP)<=?C_BXP
7:POPALL
8:RET
*******************************************************************************
**************************
?PR?_?OSCtxSw?OS_CPU_A SEGMENT CODE
RSEG ?PR?_?OSCtxSw?OS_CPU_A
_?OSCtxSw:
USING 0
OS_ENTER_CRITICAL
(1)保存处理器的寄存器
PUSHALL
(2)拷贝SP(系统)堆栈中的内容到?C_XBP, SP 满向上
然后清空它(即MOV SP,#?STACK-1) ?C_XBP 满向下
LCALL _CopySPtoC_XBP ;COPY SP 的内容到?
C_XBP
(3)在当前任务的任务控制块中保存当前任务(旧任务)的堆栈指针
OSTCBCur->OSTCBStkPtr=?C_XBP
MOV DPH,#HIGH(OSTCBCur)
MOV DPL, #LOW(OSTCBCur)
INC DPTR ;指针是3字节的
把我害死了
MOVX A,@DPTR
MOV R1,A
INC DPTR
MOVX A,@DPTR
MOV DPH,R1
MOV DPL,A
INC DPTR ;指针是3字节的
把我害死了
MOV A,?C_XBP
MOVX @DPTR,A
INC DPTR
MOV A,?C_XBP+1
MOVX @DPTR,A
IntCtxSw:
(4)调用OSTaskSwHook();
(5)OSTCBCur = OSTCBHighRdy;
(6)OSPrioCur = OSPrioHighRdy;
LCALL _ComCtxSw1
(7)得到将要重新开始运行的任务(新任务)的堆栈指针
?C_XBP = OSTCBHighRdy->OSTCBStkPtr;(0x0217)
(8)拷贝原任务(新任务)中的?C_XBP到SP(系统)堆栈中 SP 满向上
然后清空它(即?C_XBP中的原堆栈内容) ?C_XBP
满向下
CtxSw:
LCALL _ComCtxSw2
LCALL _CopyC_XBPtoSP
(9)从新任务堆栈中恢复处理器所有寄存器的值
POPALL
OS_EXIT_CRITICAL
(10)执行返回指令
SETB EA ;强行开中断!!!!!!
RET
/*$PAGE*/
*******************************************************************************
**************************
PERFORM A CONTEXT SWITCH (From an ISR)
void OSIntCtxSw(void)
;中断级切换:在OSInExit()中已判断了有高优先级的任务在就绪队列中,所以直接切
换到高优先级任务
*******************************************************************************
**************************
?PR?_?OSIntCtxSw?OS_CPU_A SEGMENT CODE
RSEG ?PR?_?OSIntCtxSw?OS_CPU_A
_?OSIntCtxSw:
USING 0
OS_ENTER_CRITICAL
ACALL _IntRETI
JMP IntCtxSw
_IntRETI:
RETI
*******************************************************************************
**************************
HANDLE TICK ISR
*******************************************************************************
**************************
CSEG AT 000BH ;设置T0中断向量
LJMP _?OSTickISR
?PR?_?OSTickISR?OS_CPU_A SEGMENT CODE
RSEG ?PR?_?OSTickISR?OS_CPU_A
_?OSTickISR:
USING 0
CLR EA
(1)保存处理器寄存器 先PUSH到SP在COPY到?C_XBP OSTCBHighRdy
PUSHALL
LCALL _CopySPtoC_XBP ;COPY SP 的内容到?
C_XBP
(2)记忆中断的嵌套层OSIntNesting++ 进入中断
(3) if (OSIntNesting == 1)
OSTCBCur->OSTCBStkPtr <= ?C_XBP
LCALL _Enter_INT
(4)Clear inter
CLR TR0 ;TR0;清中断
(5)[TH0,TL0]<= New Value
MOV TH0,#3CH ;TH0=0x3ch;
MOV TL0,#0B0H ;TL0=0x0b0h;
SETB TR0
MOV P1,0
(6) Call OSTimeTick();
LCALL _?OSTimeTick
(7) Call OSIntExit();
LCALL _?OSIntExit
(8) 恢复处理器寄存器 ;没有高优先级任务在就绪队列中
LCALL _ComCtxSw2
LCALL _CopyC_XBPtoSP
POPALL
SETB EA
(9) 执行中断返回指令
RETI
*******************************************************************************
***************************
内部函数 : ComCtxSw1()
;(4)调用OSTaskSwHook();
;(5)OSTCBCur = OSTCBHighRdy;
;(6)OSPrioCur = OSPrioHighRdy;
*******************************************************************************
***************************
?PR?_ComCtxSw1?OS_CPU_A SEGMENT CODE
RSEG ?PR?_ComCtxSw1?OS_CPU_A
_ComCtxSw1:
调用OSTaskSwHook();
LCALL _?OSTaskSwHook ;中断是关着的
OSTCBCur = OSTCBHighRdy;
MOV DPH,#HIGH(OSTCBHighRdy)
MOV DPL, #LOW(OSTCBHighRdy)
MOVX A,@DPTR
MOV R3,A
INC DPTR
MOVX A,@DPTR
MOV R2,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,#HIGH(OSTCBCur)
MOV DPL, #LOW(OSTCBCur)
MOV A,R3
MOVX @DPTR,A
INC DPTR
MOV A,R2
MOVX @DPTR,A
INC DPTR
MOV A,R1
MOVX @DPTR,A
OSPrioCur = OSPrioHighRdy;
MOV DPH,#HIGH(OSPrioHighRdy)
MOV DPL, #LOW(OSPrioHighRdy)
MOVX A,@DPTR
MOV R7,A
MOV DPH,#HIGH(OSPrioCur)
MOV DPL, #LOW(OSPrioCur)
MOV A,R7
MOVX @DPTR,A
RET
*******************************************************************************
内部函数 : ComCtxSw2()
;(7)得到将要重新开始运行的任务(新任务)的堆栈指针
;?C_XBP = OSTCBHighRdy->OSTCBStkPtr;(0x0217)
*******************************************************************************
?PR?_ComCtxSw2?OS_CPU_A SEGMENT CODE
RSEG ?PR?_ComCtxSw2?OS_CPU_A
_ComCtxSw2:
POP ACC ;因为函数调用而调整
SP,并保存到R1,R2
MOV R1,ACC
POP ACC
MOV R2,ACC
得到将要重新开始运行的任务(新任务)的堆栈指针
C_XBP = OSTCBHighRdy->OSTCBStkPtr;(0x0217)
MOV DPH,#HIGH(OSTCBCur) ;结构:OSTCBHighRdy-
>OSTCBStkPtr{[][H][L]}->?C_XBP
MOV DPL, #LOW(OSTCBCur)
INC DPTR ;跳过指针类型编号
MOVX A,@DPTR
INC DPTR
MOV R3,A ;读出高字节 为
了得到新任务的任务栈指针
MOVX A,@DPTR ;读出底字节
MOV DPH,R3
MOV DPL,A
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP,A
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP+1,A
MOV ACC,R2 ;从R1,R2中恢复SP
PUSH ACC
MOV ACC,R1
PUSH ACC
RET
*******************************************************************************
内部函数 : CopyC_XBPtoSP()
?C_XBP => SP
;拷贝原任务(新任务)中的?C_XBP到SP(系统)堆栈中 SP 满向上
;然后清空它(即?C_XBP中的原堆栈内容) ?C_XBP 满向下
*******************************************************************************
?PR?_CopyC_XBPtoSP?OS_CPU_A SEGMENT CODE
RSEG ?PR?_CopyC_XBPtoSP?OS_CPU_A
_CopyC_XBPtoSP:
OSTCBHighRdy
POP ACC ;因为函数调用而调整
SP,并保存到R1,R2
MOV R1,ACC
POP ACC
MOV R2,ACC
MOV DPH,?C_XBP
MOV DPL,?C_XBP+1
MOVX A,@DPTR
MOV R7,A ;读出SP栈元素的总数
MOV SP,#?STACK-1
COPYCXBP_TO_SP: ;拷贝?C_XBP的内容到SP中
INC DPTR
MOVX A,@DPTR
PUSH ACC
DJNZ R7,COPYCXBP_TO_SP
INC DPTR
MOV A,DPH
MOV ?C_XBP,A
MOV A,DPL
MOV ?C_XBP+1,A
MOV ACC,R2 ;从R1,R2中恢复SP
PUSH ACC
MOV ACC,R1
PUSH ACC
RET
*******************************************************************************
内部函数 : CopySPtoC_XBP()
?C_XBP <= SP
;(2)拷贝SP(系统)堆栈中的内容到?C_XBP, SP 满向上
;然后清空它(即MOV SP,#?STACK-1) ?C_XBP 满向下
*******************************************************************************
?PR?_CopySPtoC_XBP?OS_CPU_A SEGMENT CODE
RSEG ?PR?_CopySPtoC_XBP?OS_CPU_A
_CopySPtoC_XBP: ;OSTCBHighRdy
POP ACC ;因为函数调用而调整
SP,并保存到R1,R2
MOV R1,ACC
POP ACC
MOV R2,ACC
MOV DPH,?C_XBP
MOV DPL,?C_XBP+1
MOV R7,#?STACK-1
MOV A,SP
SUBB A,R7 ;因为SP-(?STACK-1)不
可能为零所以不用判断0
MOV R7,A
MOV R6,A
INC DPTR;%%%%????%%%%%% ;不用防止!!! 以前的注释:防止
多减一个单元
COPYSP_TO_CXBP: ;拷贝SP的内容到?C_XBP中
MOV A,DPL
SUBB A,0
JNZ NOZERO
DEC DPH
NOZERO:
DEC DPL
POP ACC
MOVX @DPTR,A
DJNZ R7,COPYSP_TO_CXBP
MOV A,DPL
SUBB A,0
JNZ NOZERO2
DEC DPH
NOZERO2:
DEC DPL
MOV A,R6
MOVX @DPTR,A ;?C_XBP栈顶保存的是
SP栈元素的总数
MOV A,DPH ;?C_XBP是满向下不用
减了
MOV ?C_XBP,A
MOV A,DPL
MOV ?C_XBP+1,A
MOV ACC,R2 ;从R1,R2中恢复SP
PUSH ACC
MOV ACC,R1
PUSH ACC
RET
*******************************************************************************
内部函数 : Enter_INT
()
;(2)记忆中断的嵌套层OSIntNesting++ 进入中断
;(3) if (OSIntNesting == 1)
; OSTCBCur->OSTCBStkPtr <= ?C_XBP
*******************************************************************************
***************************
?PR?_Enter_INT?OS_CPU_A SEGMENT CODE
RSEG ?PR?_Enter_INT?OS_CPU_A
_Enter_INT:
(2)记忆中断的嵌套层OSIntNesting++ 进入中断
MOV DPH,#HIGH(OSIntNesting)
MOV DPL, #LOW(OSIntNesting)
MOVX A,@DPTR
INC A
MOVX @DPTR,A
(3) if (OSIntNesting == 1)
OSTCBCur->OSTCBStkPtr <= C_XBP
DEC A
JNZ NOONE
MOV DPH,#HIGH(OSTCBCur)
MOV DPL, #LOW(OSTCBCur)
INC DPTR ;指针是3字节的
把我害死了
MOVX A,@DPTR
MOV R1,A
INC DPTR
MOVX A,@DPTR
MOV DPH,R1
MOV DPL,A
INC DPTR ;指针是3字节的
把我害死了
MOV A,?C_XBP
MOVX @DPTR,A
INC DPTR
MOV A,?C_XBP+1
MOVX @DPTR,A
NOONE:
RET
END
*******************************************************************************
文件结束
*******************************************************************************
0