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