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

📄 os_cpu_a.asm

📁 本文面向首次接触uC/OS-II的程序员
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;********************************************************************************************************
;                                               uC/OS-II
;                                         The Real-Time Kernel
;
;                          (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
;                                          All Rights Reserved
;
;                                        AT89C/S5x Specific Code
;                                           LARGE MEMORY MODEL
;
;                                            Keil C/C++ V7.09
;
; 文件名 : OS_CPU_A.ASM
; 作者   : Jean J. Labrosse
; 改编   : 华歆 Huaxin@wxzte.com 中兴光电子 研发一部 2005.06
;********************************************************************************************************
#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)

	    ?STACK	SEGMENT IDATA
		RSEG	?STACK

	    Stack:
		DS	40	

            EXTRN BIT 	(OSRunning)
            EXTRN XDATA (OSIntNesting)
            EXTRN XDATA (OSPrioHighRdy)
            EXTRN XDATA (OSPrioCur)
	    EXTRN XDATA (OSTCBCur)		
            EXTRN XDATA (OSTCBHighRdy)

;********************************************************************************************************
;                                    	       MACRO DEFINE
;********************************************************************************************************
PUSHALL	MACRO

	PUSH	ACC
	PUSH	B
	PUSH	DPH
	PUSH	DPL
	PUSH	PSW
	IRP	REG,	<R0, R1, R2, R3, R4, R5, R6, R7>
	MOV	A,	REG
	PUSH	ACC
	ENDM
	ENDM

POPALL 	MACRO
	IRP	REG,	<R7, R6, R5, R4, R3, R2, R1, R0>
	POP	ACC
	MOV	REG,	A
	ENDM
	POP	PSW
	POP	DPL
	POP	DPH
	POP	B
	POP	ACC

	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	 向下

⌨️ 快捷键说明

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