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

📄 os_cpu_a.asm

📁 UCOS在51上的移植,绝对经典!可以较少开发人员的工作量
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;********************************************************************************************************
;                                               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,	<R7, R6, R5, R4, R3, R2, R1, R0>
	MOV	A,	REG
	PUSH	ACC
	ENDM
	ENDM

POPALL 	MACRO
	IRP	REG,	<R0, R1, R2, R3, R4, R5, R6, R7>
	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

⌨️ 快捷键说明

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