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

📄 os_cpu_a.asm

📁 一个UC/OS的小应用
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	;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
;**********************************************************************************************************
;					文件结束
;**********************************************************************************************************

⌨️ 快捷键说明

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