uc/os-II 原理及应用(八) 系统裁减以及移植到51单片机-下
现在说明几个重要的点,
- OSStartHighRdy 的作用就是把任务栈复制到系统栈上面,再利用RET的时候会从系统栈上到一个地址放到PC寄存器上来实现任务运行。
- OSCtxSw是任务切换,把系统栈全部备份到当前任务栈映射上,然后改OSTCBCur,调用OSStartHighRdy跳到新任务上来。
- OSIntCtxSw是在中断函数中来任务切换的
- 需要明确知道系统栈SP的初始值,也可以自己定义,参考C51定义SP初值
- OSIntCtxSw要明确清晰的知道系统栈中哪些内容需要丢弃。
- 要明确知道系统栈是如何工作的,像51单片机的栈是增长式的,压栈时是先加1,再存内容。出栈时是先取内容,再减1。
- 要明确知道51单片机call时,会先将下个执行的地址的低8位先压栈,高8位后压栈。
; void OSStartHighRdy(void)
RSEG ?PR?OSStartHighRdy?OS_CPU_A
OSStartHighRdy:
clr EA
mov DPTR, #OSTCBCur ; DPTR = &OSTCBCur
;; DPTR = OSTCBCur
movx A,@DPTR
mov R0,A
INC DPTR
movx A,@DPTR
mov R1,A
INC DPTR
movx A, @DPTR
mov R2,A
mov DPH, R1
mov DPL, R2
;; OSTCBCur->OSTCBStkPtr
movx A,@DPTR
mov R0,A
INC DPTR
movx A, @DPTR
mov R1,A
INC DPTR
movx A, @DPTR
mov R2,A
;; DPTR = OSTCBCur->OSTCBStkPtr
mov DPH,R1
mov DPL,R2
;; 在这里任务栈第一个数据是栈长度
movx A,@DPTR
mov R7,A ; R7 = DPTR[0] = len
INC DPTR
taskstk_copyto_sysstk: ; DPTR:taskptr, R7:len
movx A,@DPTR
push ACC
INC DPTR
DJNZ R7, taskstk_copyto_sysstk
; #if OS_TASK_SW_HOOK_EN > 0u
; OSTaskSwHook();
; #endif
;; OSRunning = OS_TRUE;
MOV DPTR,#OSRunning
MOV A,#01H
MOVX @DPTR,A
?C0003:
popall
SETB EA
RETI
; END OF OSStartHighRdy
; void OSIntCtxSw(void)
RSEG ?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
mov A,SP
clr C
subb A,#17
mov SP,A
LJMP OSCtxSw
; END OF OSIntCtxSw
这里丢弃了栈后面的17个数据,其中栈顶两是调用OSIntCtxSw产生,再前面两个是调用OSIntExit产生,
再前面13个是进入tmr0_func时pushall保护现场产生。
; void OSCtxSw(void)
RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
pushall
mov A, #SysStackStart
mov R6,A
mov A,SP
clr C
subb A,R6
mov R7,A ; R7 = SP - SysStackStart ; system stack length at now
mov DPTR,#OSTCBCur ; DPTR = &OSTCBCur
;; *(&OSTCBCur)
movx A, @DPTR ; A = OSTCBCur
mov R0, A
INC DPTR
movx A, @DPTR
mov R1, A
INC DPTR
movx A, @DPTR
mov R2, A
;; DPTR = OSTCBCur
mov DPH,R1
mov DPL,R2
;; OSTCBCur->OSTCBStkPtr
movx A, @DPTR
mov R0, A
INC DPTR
movx A, @DPTR
mov R1, A
INC DPTR
movx A, @DPTR
mov R2, A
;; DPTR = OSTCBCur->OSTCBStkPtr
mov DPH,R1
mov DPL,R2
;; DPTR[0] = len = R7
mov A,R7
movx @DPTR,A
inc DPTR
mov R0,#SysStackStart ; 这里是自己定义的栈初始位置
save_sysstack_to_taskstack:
inc R0 ; 在这里51单片机的系统栈是先+1再存内容的
mov A,@R0
movx @DPTR,A
inc DPTR
DJNZ R7,save_sysstack_to_taskstack
;; OSPrioCur = OSPrioHighRdy
mov DPTR,#OSPrioHighRdy
movx A,@DPTR
mov DPTR,#OSPrioCur
movx @DPTR,A
;; OSTCBCur = OSTCBHighRdy;
MOV DPTR,#OSTCBHighRdy
MOVX A,@DPTR
MOV R1,A
INC DPTR
MOVX A,@DPTR
MOV R2,A
INC DPTR
MOVX A,@DPTR
MOV DPTR,#OSTCBCur
XCH A,R1
MOVX @DPTR,A
INC DPTR
MOV A,R2
MOVX @DPTR,A
INC DPTR
MOV A,R1
MOVX @DPTR,A
;; SP = SysStackStart
mov A,#SysStackStart
mov SP,A
; OSStartHighRdy();
LJMP OSStartHighRdy
; END OF OSCtxSw