📄 os_cpu_a.asm
字号:
NAME OS_CPU_A
;//----------------------------------------------------------------
;用于C函数调用的汇编代码
?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?_EXTERN_0_ISR_?OS_CPU_A SEGMENT CODE
;?PR?_EXTERN_1_ISR_?OS_CPU_A SEGMENT CODE
;?PR?_TIME_1_ISR_?OS_CPU_A SEGMENT CODE
?PR?_SERY_ISR_?OS_CPU_A SEGMENT CODE
;//----------------------------------------------------------------
;汇编调用外部C函数和变量
EXTRN IDATA (OSTCBCur)
EXTRN IDATA (OSTCBHighRdy)
EXTRN IDATA (OSRunning)
EXTRN IDATA (OSPrioCur)
EXTRN IDATA (OSPrioHighRdy)
;//--------------------------------------------------------
EXTRN CODE (OSTimeTick)
EXTRN CODE (_?OSTaskSwHook)
EXTRN CODE (OSIntExit)
;EXTRN CODE (OSTCBSWHook)
EXTRN CODE (OSIntEnter)
;EXTRN CODE (TickTime)
;//--------------------------------------------------------
;EXTRN CODE (ExternInt0)
;EXTRN CODE (ExternInt1)
;EXTRN CODE (Time1Int)
EXTRN CODE (SeryInt)
;//--------------------------------------------------------
;PUBLIC Extern_0_ISR
;PUBLIC Extern_1_ISR
;PUBLIC Time_1_ISR
PUBLIC Sery_ISR
;//--------------------------------------------------------
;EXTRN CODE (OSTickISRHook)
;//--------------------------------------------------------
PUBLIC OSTickISR
PUBLIC OSIntCtxSw
PUBLIC OSCtxSw
PUBLIC OSStartHighRdy
;//--------------------------------------------------------
?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
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
ENDM
;//----------------------------------------------------------------
;//----------------------------------------------------------------
PopAll MACRO
POP ACC
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 DPL
POP DPH
POP B
POP ACC
POP PSW
ENDM
;//----------------------------------------------------------------
RSEG ?PR?OSStartHighRdy?OS_CPU_A //起始调度程序
OSStartHighRdy:
USING 0 //多任务建立,当前TCB已指向最高优先级任务
//只需恢复堆栈即可
//所有的最高优先级就绪任务从此处恢复堆栈到系统栈
OSCtxSw_in:
MOV R0,#LOW (OSTCBCur)
INC R0
MOV DPH,@R0
INC R0
MOV DPL,@R0 //进入调度后取得当前任务TCB指针转装入DPTR
INC DPTR
MOVX A, @DPTR
MOV R1,A
INC DPTR
MOVX A, @DPTR
MOV R0,A
MOV DPH, R1
MOV DPL, R0 //取得当前任务的堆栈底指针装入DPTR
MOVX A, @DPTR
MOV R5,A //取得当前堆栈长度(有用)来自于用户堆栈
MOV R0,#OSStkStart //取得当前系统堆栈的更低一个地址放入R0
restore_stack:
INC DPTR
INC R0
MOVX A,@DPTR
MOV @R0,A
DJNZ R5,restore_stack //将当前任务堆栈拷贝到系统堆栈
MOV SP,R0 //恢复堆栈系统堆栈指针SP
;OSRunning=TRUE
MOV R0,#LOW (OSRunning)
MOV @R0,#01
POPALL //出栈寄存器数据恢复
SETB EA //开中断
RETI //任务地址恢复
;//----------------------------------------------------------------
;//----------------------------------------------------------------
RSEG ?PR?OSCtxSw?OS_CPU_A //任务切换程序
//当前任务的保护堆栈从这里开始
OSCtxSw:
PushAll //当前任务的寄存器入系统栈
OSIntCtxSw_in:
MOV A,SP
CLR C
SUBB A,#OSStkStart
MOV R5,A //获得当前系统栈的长度装入R5
;OSTCBCur ===> DPTR
MOV R0,#LOW (OSTCBCur)
INC R0
MOV DPH,@R0
INC R0
MOV DPL,@R0 //获得当前任务的TCB指针装入DPTR
;OSTCBCur->OSTCBStkPtr ===> DPTR
INC DPTR
MOVX A,@DPTR
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1 //获得当前任务堆栈的指针装入DPTR
MOV A,R5 //将系统堆栈长度(也即为当前任务栈长度)装入当前任务栈指针所指处
MOVX @DPTR,A //(任务栈指针永远指向这个位置)用于装栈大小
MOV R0,#OSStkStart //取得当前系统堆栈的更低一个地址放入R0
save_stack:
INC DPTR
INC R0
MOV A,@R0
MOVX @DPTR,A
DJNZ R5,save_stack //将系统栈拷贝到当前任务栈
LCALL _?OSTaskSwHook //最高优先级任务代替当前任务成为当前任务
LJMP OSCtxSw_in
;//------------------------------------------
;//----------------------------------------------------------------
;//----------------------------------------------------------------
RSEG ?PR?OSIntCtxSw?OS_CPU_A //中断返回时的任务调度
OSIntCtxSw:
CLR EA
MOV A, SP
CLR C
SUBB A, #4
MOV SP,A //由于之前调用了OSIntExit(),OSIntCtxSw()过程
//多压入堆栈,所以系统堆栈指针SP-4
LJMP OSIntCtxSw_in //中断结束保护堆栈
;//----------------------------------------------------------------
;//----------------------------------------------------------------
CSEG AT 0000BH //定时器中断处理程序
LJMP OSTickISR
RSEG ?PR?OSTickISR?OS_CPU_A
OSTickISR:
USING 0
PushAll //保存当前任务寄存器到系统堆栈
CLR TR0
MOV TH0,#70H
MOV TL0,#00H
SETB TR0
LCALL OSIntEnter
LCALL OSTimeTick
LCALL OSIntExit //比较当前任务的优先级与最高优先级
//如果相等退出系统直接出栈,(由下面继续的代码完成)
//任务继续运行
//如果不等调再用OSIntCtxSw,所以SP-4
PopAll
RETI
;//----------------------------------------------------------------
;//----------------------------------------------------------------
;CSEG AT 00003H
; LJMP Extern_0_ISR
; RSEG ?PR?_EXTERN_0_ISR_?OS_CPU_A
;Extern_0_ISR:
; USING 0
; PushAll
; LCALL OSIntEnter
; LCALL ExternInt0
; LCALL OSIntExit
; PopAll
; RETI
;//----------------------------------------------------------------
;//----------------------------------------------------------------
;CSEG AT 00013H
; LJMP Extern_1_ISR
; RSEG ?PR?_EXTERN_1_ISR_?OS_CPU_A
;Extern_1_ISR:
; USING 0
; PushAll
; LCALL OSIntEnter
; LCALL ExternInt1
; LCALL OSIntExit
; PopAll
; RETI
;//----------------------------------------------------------------
;//----------------------------------------------------------------
;CSEG AT 0001BH
; LJMP Time_1_ISR
; RSEG ?PR?_TIME_1_ISR_?OS_CPU_A
;Time_1_ISR:
; USING 0
; PushAll
; LCALL OSIntEnter
; LCALL Time1Int
; LCALL OSIntExit
; PopAll
; RETI
;//----------------------------------------------------------------
;//----------------------------------------------------------------
CSEG AT 00023H
LJMP Sery_ISR
RSEG ?PR?_SERY_ISR_?OS_CPU_A
Sery_ISR:
USING 0
PushAll
LCALL OSIntEnter
LCALL SeryInt
LCALL OSIntExit
PopAll
RETI
;//----------------------------------------------------------------
;//----------------------------------------------------------------
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -