📄 os_cpu_a.a51
字号:
;/*
;*********************************************************************************************************
;* uC/OS-II
;* 实时内核
;*
;* (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
;* 版权所有
;*
;* MCU-51 专用代码
;* KEIL C51小模式编译
;*
;* 文件名 : OS_CPU_A.ASM
;* 作者 : Jean J. Labrosse
;* 改编 : 杨屹 gdtyy@ri.gdt.com.cn 巨龙公司系统集成开发部 2002.09.27
;*********************************************************************************************************
;*/
$NOMOD51
EA BIT 0A8H.7
SP DATA 081H
B DATA 0F0H
ACC DATA 0E0H
DPH DATA 083H
DPL DATA 082H
PSW DATA 0D0H
TR0 BIT 088H.4
TF0 BIT 088H.5
TH0 DATA 08CH
TL0 DATA 08AH
NAME OS_CPU_A ;模块名
;定义重定位段
?PR?OSStartHighRdy?OS_CPU_A SEGMENT CODE
?PR?OSCtxSw?OS_CPU_A SEGMENT CODE
?PR?OSIntCtxSw?OS_CPU_A SEGMENT CODE
?PR?OSTickISR?OS_CPU_A SEGMENT CODE
;声明引用全局变量和外部子程序
EXTRN DATA (?C_XBP) ;仿真堆栈指针用于重入局部变量保存
EXTRN IDATA (STACK)
EXTRN DATA (OSTCBCur)
EXTRN DATA (OSTCBHighRdy)
EXTRN DATA (OSRunning)
EXTRN DATA (OSPrioCur)
EXTRN DATA (OSPrioHighRdy)
EXTRN CODE (_?OSTaskSwHook)
EXTRN CODE (_?OSIntEnter)
EXTRN CODE (_?OSIntExit)
EXTRN CODE (_?OSTimeTick)
;对外声明4个不可重入函数
PUBLIC OSStartHighRdy
PUBLIC OSCtxSw
PUBLIC OSIntCtxSw
PUBLIC OSTickISR
;PUBLIC SerialISR
;定义压栈出栈宏
;-------------------------------------------------------------------------
PUSHALL MACRO
IRP REG, <PSW, ACC, B, DPL, DPH, 0, 1, 2, 3, 4, 5, 6, 7>
PUSH REG
ENDM
ENDM
POPALL MACRO
IRP REG, <7, 6, 5, 4, 3, 2, 1, 0, DPH, DPL, B, ACC, PSW>
POP REG
ENDM
ENDM
;子程序
;-------------------------------------------------------------------------
RSEG ?PR?OSStartHighRdy?OS_CPU_A
OSStartHighRdy:
;上电后51自动关中断,此处不必用CLR EA指令,因为到此处还未开中断,本程序退出后,开中断。
LCALL _?OSTaskSwHook
OSCtxSw_in:
;OSTCBCur ===> DPTR 获得当前TCB指针,详见C51.PDF第178页
MOV DPH,(OSTCBCur+1)
MOV DPL,(OSTCBCur+2)
MOVX A,@DPTR ;.OSTCBStkPtr是xadta指针
MOV B,A
INC DPTR
MOVX A,@DPTR
MOV DPL,A
MOV DPH,B ;此时PDTR指向用户堆栈
;*UserStkPtr ===> R5 用户堆栈起始地址内容(即用户堆栈长度放在此处) 详见文档说明 指针用法详见C51.PDF第178页
MOVX A,@DPTR ;用户堆栈中是unsigned char类型数据
MOV R5,A ;R5=用户堆栈长度
;恢复现场堆栈内容
MOV R0,#STACK-1
L00: INC DPTR
INC R0
MOVX A,@DPTR
MOV @R0,A
DJNZ R5,L00
;恢复堆栈指针SP
MOV SP,R0
;恢复仿真堆栈指针?C_XBP
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP,A
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP+1,A
;OSRunning=TRUE
MOV A,#1
MOV OSRunning,A
POPALL
SETB EA ;开中断
RETI
;-------------------------------------------------------------------------
RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
PUSHALL
OSIntCtxSw_in:
;OSTCBCur ===> DPTR 获得当前TCB指针,详见C51.PDF第178页
MOV DPH,OSTCBCur+1
MOV DPL,(OSTCBCur+2)
;OSTCBCur->OSTCBStkPtr ===> DPTR 获得用户堆栈指针
MOVX A,@DPTR ;.OSTCBStkPtr是void指针
MOV B,A
INC DPTR
MOVX A,@DPTR
MOV DPL,A
MOV DPH,B
;获得堆栈长
MOV A,SP
CLR C
SUBB A,#STACK-1
MOV R5,A
;保存堆栈长度
MOVX @DPTR,A
;获得堆栈起址
MOV R0,#STACK-1
L12:
INC DPTR
INC R0
MOV A,@R0
MOVX @DPTR,A
DJNZ R5,L12
;保存C_XBP 到堆栈中
INC DPTR
MOV A,?C_XBP
MOVX @DPTR,A
MOV A,?C_XBP+1
INC DPTR
MOVX @DPTR,A
;调用用户程序
LCALL _?OSTaskSwHook
;OSTCBCur = OSTCBHighRdy
MOV A,OSTCBHighRdy
MOV OSTCBCur,A
MOV A,OSTCBHighRdy+1
MOV OSTCBCur+1,A
MOV A,OSTCBHighRdy+2
MOV OSTCBCur+2,A
;OSPrioCur = OSPrioHighRdy 使用这两个变量主要目的是为了使指针比较变为字节比较,以便节省时间。
MOV A,OSPrioHighRdy
MOV OSPrioCur,A
LJMP OSCtxSw_in
;-------------------------------------------------------------------------
RSEG ?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
;调整SP指针去掉在调用OSIntExit(),OSIntCtxSw()过程中压入堆栈的多余内容
;SP=SP-4
MOV A,SP
CLR C
SUBB A,#4
MOV SP,A
LJMP OSIntCtxSw_in
;-------------------------------------------------------------------------
CSEG AT 000BH ;OSTickISR
LJMP OSTickISR ;使用定时器0
RSEG ?PR?OSTickISR?OS_CPU_A
OSTickISR:
USING 0
PUSHALL
MOV A,#063H
MOV TH0,A
MOV A,#0C0H
MOV TL0,A
CLR TF0
LCALL _?OSIntEnter
LCALL _?OSTimeTick
LCALL _?OSIntExit
POPALL
RETI
;-------------------------------------------------------------------------
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -