📄 os_cpu_a.asm
字号:
;********************************************************************************************************
; 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 + -