📄 os_cpu_a.s
字号:
; push lr_svc is lr, push lr and r0-r12
LDR lr, SAVED_LR_SVC
STMFD sp!, {r0-r12}
STMFD sp!, {lr}
LDR r4, SAVED_SPSR
STMFD sp!, {r4}
STMFD sp!, {r4}
B _OSCtxSw
] ;end of method 2
;**********************************************************
; INT_PORT_METHOD 3
;**********************************************************
[ INT_PORT_METHOD = 3
EInt0Isr
SUB lr, lr, #4
STMFD sp!, {r0-r12, lr}
bl OSIntEnter
; ClearPending(BIT_EINT0);
LDR r0, =SRCPND
LDR r1, =BIT_EINT0
STR r1, [r0]
LDR r0, =INTPND
STR r1, [r0]
; OSSemPost(mysem);
LDR r1, =mysem
LDR r0, [r1]
BL OSSemPost
SET_TIMER
BL OSIntExit
LDMFD sp!, {r0-r12, pc}^
OSTickISR
; lr - 4 will be the return address(pc). in all task stack we
; get r0-r12, pc(lr_irq), cpsr(spsr_irq), but now sp_svc, lr_svc, spsr_svc
; is not available.
SUB lr, lr, #4
STMFD sp!, {r0-r12, lr}
bl OSIntEnter
bl OSTimeTick
; ClearPending(BIT_TIMER0);
LDR r0, =SRCPND
LDR r1, =BIT_TIMER0
STR r1, [r0]
LDR r0, =INTPND
STR r1, [r0]
BL OSIntExit
LDMFD sp!, {r0-r12, pc}^
OSIntCtxSw
;**********************************************************
; adjust sp to just enter isr(after push registers)
;**********************************************************
add sp, sp, #0x10
;**********************************************************************
; save information before leave irq mode
;**********************************************************************
;save spsr_irq, sp_irq(need to copy to sp_svc)
MRS r0, spsr
MOV r2, sp
;**********************************************************************
; change to svc
;**********************************************************************
MRS r1, cpsr
ORR r1, r1, #1
MSR cpsr_cxsf, r1
;**********************************************************************
; copy sp_irq to svc_irq
;**********************************************************************
MOV sp, r2
;**********************************************************************
; push registers
;**********************************************************************
STMFD sp!, {lr}
STMFD sp!, {r0}
STMFD sp!, {r0}
B _OSCtxSw
] ;end of method 3
;**********************************************************
; INT_PORT_METHOD 4
;**********************************************************
[ INT_PORT_METHOD = 4
EInt0Isr
; ClearPending(BIT_EINT0);
LDR r0, =SRCPND
LDR r1, =BIT_EINT0
STR r1, [r0]
LDR r0, =INTPND
STR r1, [r0]
; re-enalbe the ISR bit in CPSR
msr cpsr_c, #0x00000053
bl OSIntEnter
; OSSemPost(mysem);
LDR r1, =mysem
LDR r0, [r1]
BL OSSemPost
SET_TIMER
BL OSIntExit
LDMFD sp!, {r0}
msr cpsr_cxsf, r0
LDMFD sp!, {lr}
LDMFD sp!, {r0-r12, pc}
OSTickISR
; before re-enable the ISR bit in CPSR ClearPending(BIT_TIMER0);
LDR r0, =SRCPND
LDR r1, =BIT_TIMER0
STR r1, [r0]
LDR r0, =INTPND
STR r1, [r0]
; re-enalbe the ISR bit in CPSR
msr cpsr_c, #0x00000053
bl OSIntEnter
bl OSTimeTick
BL OSIntExit
LDMFD sp!, {r0}
msr cpsr_cxsf, r0
LDMFD sp!, {lr}
LDMFD sp!, {r0-r12, pc}
OSIntCtxSw
;**********************************************************
; adjust sp to just enter isr(after push registers)
;**********************************************************
add sp, sp, #0x10
;**********************************************************************
; all other registers are pushed except the spsr
;**********************************************************************
mrs r0, spsr
STMFD sp!, {r0}
B _OSCtxSw
] ;end of method 4
;**********************************************************************
; void OS_TASK_SW(void)
;
; Perform a context switch.
;
; On entry, OSTCBCur and OSPrioCur hold the current TCB and priority
; and OSTCBHighRdy and OSPrioHighRdy contain the same for the task
; to be switched to.
;
; The following code assumes that the virtual memory is directly
; mapped into physical memory. If this is not true, the cache must
; be flushed at context switch to avoid address aliasing.
;**********************************************************************
OS_TASK_SW
;**********************************************************************
; push the cpu status registers
;**********************************************************************
STMFD sp!, {lr} ; save pc
STMFD sp!, {r0-r12} ; save registers and ret address
STMFD sp!, {lr} ; save lr
MRS r4, CPSR
STMFD sp!, {r4} ; save current PSR
MRS r4, SPSR
STMFD sp!, {r4} ; save SPSR
_OSCtxSw
;**********************************************************************
; store sp to OSTCBCur->OSTCBStkPtr
;**********************************************************************
; Get current task TCB address
LDR r4, =OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
;**********************************************************************
; store sp to OSTaskSwHook();
;**********************************************************************
;**********************************************************************
; OSTCBCur = OSTCBHighRdy;
; OSPrioCur = OSPrioHighRdy;
;**********************************************************************
; OSPrioCur = OSPrioHighRdy, this is a 8bit value
LDR r4, =OSPrioCur
LDR r5, =OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; OSTCBCur = OSTCBHighRdy
LDR r4, =OSTCBCur
LDR r5, =OSTCBHighRdy
LDR r6, [r5]
STR r6, [r4]
;**********************************************************************
; get sp in OSTCBHighRdy->OSTCBStkPtr;
;**********************************************************************
; Get highest priority task TCB address
LDR r6, =OSTCBHighRdy
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer
;**********************************************************************
; pop the cpu status registers
;**********************************************************************
; restore task's mode regsiters
LDMFD sp!, {r4}
MSR SPSR_cxsf, r4
LDMFD sp!, {r4}
MSR CPSR_cxsf, r4
; return in new task context
LDMFD sp!, {lr}
LDMFD sp!, {r0-r12, pc}
;************************************************
; void OSStartHighRdy(void)
;
; Start the task with the highest priority;
;************************************************
OSStartHighRdy
;***********************************************
; Call user definable OSTaskSwHook();
;***********************************************
;***********************************************
; Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
;***********************************************
LDR r5, =OSTCBHighRdy ; Get highest priority task TCB address, r5 = &OSTCBHighRdy
LDR r5, [r5] ; get stack pointer. r5 == OSTCBHighRdy
LDR sp, [r5] ; switch to the new stack. sp = *OSTCBHighRdy
; and is OSTCBHighRdy->OSTCBStkPtr, because OSTCBStkPtr is the first unit.
;***********************************************
;OSRunning = 1
;***********************************************
LDR r0, =OSRunning
LDR r1, =1
STRB r1, [r0] ;note: OSRunning is a bit8 value
;***********************************************
; OSTCBCur = OSTCBHighRdy
;***********************************************
LDR r4, =OSTCBCur ; Get current task TCB address
STR r5, [r4] ; set new current task TCB address
;***********************************************
; Restore all processor registers from the new task's stack;
; Execute a return from interrupt instruction;
;***********************************************
; get spsr and cpsr. the two registers is the fisrt two unit in the stack
LDMFD sp!, {r4} ; YYY
MSR SPSR_cxsf, r4
LDMFD sp!, {r4} ; get new state from top of the stack
MSR CPSR_cxsf, r4 ; CPSR should be SVC32Mode
; get other value in stack
LDMFD sp!, {lr}
LDMFD sp!, {r0-r12,pc } ; start the new task
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -