📄 os_cpu_a.asm
字号:
; Returns : none
;
; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below.
;
; Save all registers on the current task's stack;
; OSIntNesting++;
; if (OSIntNesting == 1) {
; OSTCBCur->OSTCBStkPtr = SS:SP
; }
; OSTickDOSCtr--;
; if (OSTickDOSCtr == 0) {
; OSTickDOSCtr = 11;
; INT 81H; Chain into DOS every 54.925 mS
; (Interrupt will be cleared by DOS)
; } else {
; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259
; PIC (Priority Interrupt Controller)
; }
; OSTimeTick(); Notify uC/OS-II that a tick has occured
; OSIntExit(); Notify uC/OS-II about end of ISR
; Restore all registers that were save on the current task's stack;
; Return from Interrupt;
;*********************************************************************************************************
;
_OSTickISR PROC FAR
;
PUSHA ; Save interrupted task's context
PUSH ES
PUSH DS
;
MOV AX, SEG(_OSIntNesting) ; Reload DS
MOV DS, AX
INC BYTE PTR DS:_OSIntNesting ; Notify uC/OS-II of ISR
;
CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1)
JNE SHORT _OSTickISR1
MOV AX, SEG(_OSTCBCur) ; Reload DS
MOV DS, AX
LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP
MOV ES:[BX+2], SS ;
MOV ES:[BX+0], SP ;
;
_OSTickISR1:
MOV AX, SEG(_OSTickDOSCtr) ; Reload DS
MOV DS, AX
DEC BYTE PTR DS:_OSTickDOSCtr
CMP BYTE PTR DS:_OSTickDOSCtr, 0
JNE SHORT _OSTickISR2 ; Every 11 ticks (~199.99 Hz), chain into DOS
;
MOV BYTE PTR DS:_OSTickDOSCtr, 11
INT 081H ; Chain into DOS's tick ISR
JMP SHORT _OSTickISR3
_OSTickISR2:
MOV AL, 20H ; Move EOI code into AL.
MOV DX, 20H ; Address of 8259 PIC in DX.
OUT DX, AL ; Send EOI to PIC if not processing DOS timer.
;
_OSTickISR3:
CALL FAR PTR _OSTimeTick ; Process system tick
;
CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR
;
POP DS ; Restore interrupted task's context
POP ES
POPA
;
IRET ; Return to interrupted task
;
_OSTickISR ENDP
;
END
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
;-------------------2006-12-20 17:54 新添加-----------------------------
RSEG ? PR? OSStartHighRdy? OS_CPU_A
OSStartHighRdy:
USING 0
LCALL _? OSTaskSwHook
OSCtxSw_in:
;OSTCBCur => DPTR 获得当前TCB指针
MOV R0,#LOW(OSTCBCur)
INC R0
MOV DPH,@R0
INC R0
MOV DPL,@R0
;任务堆栈映象指针=> DPTR
INC DPTR
MOVX A,@DPTR
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1
;任务堆栈映象长度*UserStkPtr => R5
MOVX A,@DPTR
MOV R5,A ;R5 = 任务堆栈映象长度
;把待运行任务堆栈映像的内容复制到系统堆栈
MOV R0,#OSStkStart
restore_stack:
INC DPTR
INC R0
MOVX A,@DPTR
MOV @R0,A
DJNZ R5,restore_stack
;恢复系统堆栈指针 ?C_XBP
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP,A
INC DPTR
MOVX A,@DPTR
MOV ?C_XBP+1,A
;OSRunning = TRUE
MOV R0,#LOW(OSRunning)
MOV @R0,#01
POPALL ;把系统堆栈内容弹入CPU
SETB EA
RETI ;利用中断返回指令,使系统切换至待运行状态
;----------------------------------------------------------------------------------------------------------
RSEG ?PR?OSCtxSw?OS_CPU_A
;任务切换函数入口
OSCtxSw:
PUSHALL ;把被中止运行任务的CPU内容压栈
OSIntCtxSw_in:
;获得堆栈长度和起始地址
MOV A,SP
CLR C
SUBB A,#OSStkStart
MOV R5,A ;获得堆栈长度
;OSTCBCur => DPTR ;获得当前任务TCB指针
MOV R0,#LOW(OSTCBCur)
INC R0
MOV DPH,@R0
INC R0
MOV DPL,@R0
;获得任务堆栈映像指针
INC DPTR
MOVX A,@DPTR
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:
INC DPTR
INC R0
MOV A,@R0
MOVX @DPTR,A
DJNZ R5,save_stack
;保存任务堆栈映像指针 ?C_XBP
INC DPTR
MOV A,?C_XBP
MOVX @DPTR,A
INC DPTR
MOV A,?C_XBP + 1
MOVX @DPTR,A
;调用用户程序
LCALL _?OSTaskSwHook
;获得最高级就绪任务的TCB
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
MOV R0,#OSPrioCur
MOV R1,#OSPrioHighRdy
MOV A,@R1
MOV @R0,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
;----------------------------------------------------------------------------------------------------------
;定义压栈出栈宏
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
;----------------------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -