📄 os_cpu_a.asm
字号:
;/*
;*********************************************************************************************************
;* uC/OS-II
;* The Real-Time Kernel
;*
;* (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
;* All Rights Reserved
;*
;*
;* uCOS_51 for MCS-51
;*
;* File : OS_CPU_A.ASM
;* By : Jean J. Labrosse
;* From : chen shi zhi
;* Last modified by : QQ 591881218
;*********************************************************************************************************
;*/
$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
EX0 BIT 0A8H.0
EX1 BIT 0A8H.2
ES BIT 0A8H.4
TH0 DATA 08CH
TL0 DATA 08AH
TIMER_20MS_TH0 EQU 070H ;CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TH0=0x70
TIMER_20MS_TL0 EQU 000H ;CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TL0=0x00
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
?PR?_?Serial?OS_CPU_A SEGMENT CODE
;声明引用全局变量和外部子程序
EXTRN DATA (?C_XBP) ;仿真堆栈指针用于可重入局部变量保存
EXTRN IDATA (OSTCBCur)
EXTRN IDATA (OSTCBHighRdy)
EXTRN IDATA (OSRunning)
EXTRN IDATA (OSPrioCur)
EXTRN IDATA (OSPrioHighRdy)
EXTRN CODE (_?OSTaskSwHook)
EXTRN CODE (_?OSIntEnter)
EXTRN CODE (_?OSIntExit)
EXTRN CODE (_?OSTimeTick)
EXTRN CODE (_?Serial)
;对外声明4个不可重入函数
PUBLIC OSStartHighRdy
PUBLIC OSCtxSw
PUBLIC OSIntCtxSw
PUBLIC OSTickISR
;PUBLIC SerialISR
;分配堆栈空间。只关心大小,堆栈起点由keil决定,通过标号可以获得keil分配的SP起点
?STACK SEGMENT IDATA
RSEG ?STACK
OSStack:
DS 40H ;分配硬件堆栈的大小
OSStkStart IDATA OSStack-1
;定义压栈出栈宏
PUSHALL MACRO
PUSH PSW
PUSH ACC
PUSH B
PUSH DPL
PUSH DPH
MOV A,R0 ;R0~R7入栈
PUSH ACC
MOV A,R1
PUSH ACC
MOV A,R2
PUSH ACC
MOV A,R3
PUSH ACC
MOV A,R4
PUSH ACC
MOV A,R5
PUSH ACC
MOV A,R6
PUSH ACC
MOV A,R7
PUSH ACC
;PUSH SP ;不必保存SP,任务切换时由相应程序调整
ENDM
POPALL MACRO
;POP ACC ;不必保存SP,任务切换时由相应程序调整
POP ACC ;R0~R7出栈
MOV R7,A
POP ACC
MOV R6,A
POP ACC
MOV R5,A
POP ACC
MOV R4,A
POP ACC
MOV R3,A
POP ACC
MOV R2,A
POP ACC
MOV R1,A
POP ACC
MOV R0,A
POP DPH
POP DPL
POP B
POP ACC
POP PSW
ENDM
;--------------------
;子程序
;--------------------
; --------------------------------------------------
; ---------------- OSStartHighRdy() ----------------
; --------------------------------------------------
RSEG ?PR?OSStartHighRdy?OS_CPU_A
OSStartHighRdy:
USING 0 ;上电后51自动关中断,此处不必用CLR EA指令,因为到此处还未开中断,本程序退出后,开中断
LCALL _?OSTaskSwHook
;OSRunning=TRUE
MOV R0,#LOW (OSRunning)
MOV @R0,#01
;--------------------
;OSCtxSw_in
;--------------------
OSCtxSw_in:
;OSTCBHighRdy ==> DPTR 获得当前就绪的最高优先级任务的TCB指针
MOV R0,#LOW (OSTCBHighRdy) ;获得OSTCBHighRdy指针低地址,指针占3B。+0类型 +1高8位数据 +2低8位数据
INC R0
MOV DPH,@R0 ;全局变量OSTCBHighRdy在IDATA中
INC R0
MOV DPL,@R0
;OSTCBHighRdy->OSTCBStkPtr ==> DPTR 获得用户堆栈指针
INC DPTR ;指针占3B。+0类型 +1高8位数据 +2低8位数据
MOVX A,@DPTR ;OSTCBStkPtr是void指针
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1
;*UserStkPtr ==> R5 用户堆栈起始地址内容(即用户堆栈长度放在此处)
MOVX A,@DPTR ;用户堆栈中是unsigned char类型数据
MOV R5,A ;R5=用户堆栈长度
;恢复现场堆栈内容
MOV R0,#OSStkStart
;--------------------
;restore_stack
;--------------------
restore_stack:
INC DPTR
INC R0
MOVX A,@DPTR
MOV @R0,A
DJNZ R5,restore_stack
;恢复堆栈指针SP
MOV SP,R0
;恢复仿真堆栈指针?C_XBP
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP,A ;?C_XBP 仿真堆栈指针高8位
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP+1,A ;?C_XBP 仿真堆栈指针低8位
POPALL
SETB EA ;开中断
RETI
; --------------------------------------------------
; ------------------- OSCtxSw() --------------------
; --------------------------------------------------
RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
USING 0
PUSHALL
;获得堆栈长度和起始地址
MOV A,SP
CLR C
SUBB A,#OSStkStart
MOV R5,A ;获得堆栈长度
;OSTCBCur ==> DPTR 获得当前TCB指针
MOV R0,#LOW (OSTCBCur) ;获得OSTCBCur指针低地址,指针占3B。+0类型 +1高8位数据 +2低8位数据
INC R0
MOV DPH,@R0 ;全局变量OSTCBCur在IDATA中
INC R0
MOV DPL,@R0
;OSTCBCur->OSTCBStkPtr ==> DPTR 获得用户堆栈指针
INC DPTR ;指针占3B。+0类型 +1高8位数据 +2低8位数据
MOVX A,@DPTR ;OSTCBStkPtr是void指针
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1
;保存堆栈长度
MOV A,R5
MOVX @DPTR,A
MOV R0,#OSStkStart ;获得堆栈起始地址
;--------------------
;save_stack
;--------------------
save_stack:
INC DPTR
INC R0
MOV A,@R0
MOVX @DPTR,A
DJNZ R5,save_stack
;保存仿真堆栈指针?C_XBP
INC DPTR
MOV A,?C_XBP ;?C_XBP 仿真堆栈指针高8位
MOVX @DPTR,A
INC DPTR
MOV A,?C_XBP+1 ;?C_XBP 仿真堆栈指针低8位
MOVX @DPTR,A
;调用用户程序
LCALL _?OSTaskSwHook
;--------------------
;OSIntCtxSw_in
;--------------------
OSIntCtxSw_in:
;OSTCBCur = OSTCBHighRdy
MOV R0,#OSTCBCur
MOV R1,#OSTCBHighRdy
MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,@R1
MOV @R0,A
;OSPrioCur = OSPrioHighRdy 使用这两个变量主要目的是为了使指针比较变为字节比较,以便节省时间
MOV R0,#OSPrioCur
MOV R1,#OSPrioHighRdy
MOV A,@R1
MOV @R0,A
LJMP OSCtxSw_in
; -------------------------------------------
; --------------- OSIntCtxSw() --------------
; -------------------------------------------
RSEG ?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
USING 0
LCALL _?OSTaskSwHook
LJMP OSIntCtxSw_in
; -------------------------------------------
; --------------- OSTickISR() ---------------
; -------------------------------------------
CSEG AT 000BH ;定时器T0中断
LJMP OSTickISR
RSEG ?PR?OSTickISR?OS_CPU_A
OSTickISR:
USING 0 ;工作寄存器0
CLR EA ;关中断,防止中断嵌套
PUSHALL ;现场保护
LCALL _?OSIntEnter ;通知内核进入中断
CLR TR0
MOV TH0,#TIMER_20MS_TH0 ;定义Tick=50次/秒,即0.02秒/次
MOV TL0,#TIMER_20MS_TL0 ;OS_CPU_C.C 和 OS_TICKS_PER_SEC
SETB TR0
LCALL _?OSTimeTick ;调用中断服务子程序
LCALL _?OSIntExit ;通知内核退出中断
POPALL ;恢复现场
SETB EA ;开中断
RETI
;--------------------
;SerialISR
;--------------------
CSEG AT 0023H ;串口中断
LJMP SerialISR
RSEG ?PR?_?serial?OS_CPU_A
SerialISR:
USING 0
CLR EA ;关中断,防止中断嵌套
PUSHALL
LCALL _?OSIntEnter ;通知内核进入中断
CLR ES
LCALL _?Serial ;调用中断服务子程序
SETB ES
LCALL _?OSIntExit ;通知内核退出中断
POPALL
SETB EA
RETI
;--------------------
END
;--------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -