?? os_cpu_a.s
字號:
;-+---+---++-+--+-++-+++--++--+++
;* File: os_cpu_a.s
;* (c) Copyright ARM Limited 1999. All rights reserved.
;* ARM Specific code
; Functions defined in this module:
;
; void ARMDisableInt(void) /* disable interrupts when in SVC */
; void ARMEnableInt(void) /* enable interrupts when in SVC */
; void OSStartHighRdy(void) /* start highest priority task */
; OS_TASK_SW /* Context Switch*/
; ARMDisableINT & ARMEnableINT
; OSIntCtxSw
AREA OS_CPU_A, CODE, READONLY
; External symbols we need the addresses of
IMPORT OSTCBCur
addr_OSTCBCur DCD OSTCBCur
IMPORT OSTCBHighRdy
addr_OSTCBHighRdy DCD OSTCBHighRdy
IMPORT OSPrioCur
addr_OSPrioCur DCD OSPrioCur
IMPORT OSPrioHighRdy
addr_OSPrioHighRdy DCD OSPrioHighRdy
;-+---+---++-+--+-++-+++--++--+++
EXPORT OSStartHighRdy
;示例
;SP=OSTCBHighRdy->OSTCBStkPtr
;OSTCBCur=OSTCBHighRdy
;彈出現場
OSStartHighRdy
LDR r4, addr_OSTCBCur ; Get current task TCB address
LDR r5, addr_OSTCBHighRdy ; Get highest priority task TCB address
LDR r5, [r5] ; get stack pointer
LDR sp, [r5] ; switch to the new stack
;SP=OSTCBHighRdy->OSTCBStkPtr
STR r5, [r4] ; set new current task TCB address
;OSTCBCur=OSTCBHighRdy
LDMFD sp!, {r4} ; YYY
MSR CPSR_cxsf, r4
LDMFD sp!, {r4} ; get new state from top of the stack
MSR CPSR_cxsf, r4 ; CPSR should be SYS32Mode
LDMFD sp!, {r0-r12, lr, pc } ; start the new task
;-+---+---++-+--+-++-+++--++--+++
EXPORT OS_TASK_SW
;示例
;現場壓棧
;OSPrioCur = OSPrioHighRdy
;OSTCBCur->OSTCBStkPtr=SP 保存SP到當前任務控制塊
;SP=OSTCBHighRdy->OSTCBStkPtr
;OSTCBCur=OSTCBHighRdy
;彈出現場
OS_TASK_SW
STMFD sp!, {lr} ; save pc
STMFD sp!, {lr} ; save lr
;分析:OS_TASK_SW是個函數,在任務間接的調用它時會在最后失去CPU,再次
;獲得CPU時,其恰好在OS_TASK_SW調用完畢后的那個位置,因此,lr被放入pc
;在棧中的位置;此外,lr放入lr在棧中的位置也是無關緊要的,因為,子函數
;返回時的lr是無意義的。
STMFD sp!, {r0-r12} ; save register file and ret address
MRS r4, CPSR
STMFD sp!, {r4} ; save current PSR
;MRS r4, SPSR ; YYY+ 這里屏蔽掉是因為任務運行的
;模式是SYS,沒有SPSR,棧中的CPSR與SPSR相同
STMFD sp!, {r4} ; YYY+ save SPSR
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; OSPrioCur = OSPrioHighRdy
; Get current task TCB address
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
;OSTCBCur->OSTCBStkPtr=SP 保存SP到當前任務控制塊
; Get highest priority task TCB address
LDR r6, addr_OSTCBHighRdy
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer
;SP=OSTCBHighRdy->OSTCBStkPtr 更新SP為即將運行的任務
STR r6, [r4] ; set new current task TCB address
; OSTCBCur = OSTCBHighRdy
LDMFD sp!, {r4} ; YYY+
;MSR SPSR_cxsf, r4 ; YYY+運行在sys模式下,無需SPSR的更新
LDMFD sp!, {r4} ; YYY+
MSR CPSR_cxsf, r4 ; YYY+
LDMFD sp!, {r0-r12, lr, pc} ; YYY+
;現場恢復完畢
;-+---+---++-+--+-++-+++--++--+++
EXPORT ARMDisableInt
ARMDisableInt
STMFD sp!, {r0}
MRS r0, CPSR
ORR r0, r0, #0x80
MSR CPSR_c, r0
LDMFD sp!, {r0}
MOV pc, lr
EXPORT ARMEnableInt
ARMEnableInt
STMFD sp!, {r0}
MRS r0, CPSR
BIC r0, r0, #0x80
MSR CPSR_c, r0
LDMFD sp!, {r0}
MOV pc, lr
;-+---+---++-+--+-++-+++--++--+++
IMPORT IRQ_STACK
EXPORT OSIntCtxSw
OSIntCtxSw
;新的代碼,實現了中斷的嵌套
;該函數被OSIntExit調用,OSIntExit在ISR_IrqHandler中被
;調用(而不是以前在安裝后的向量中,這是為了簡化堆棧處理)
;該函數運行依賴于調用ISR_IrqHandler之前的模式轉換和棧構造
;運行于SYS模式,其首先調整SP_sys指針到下圖中SPSR處
;后半部分與OSCtxSw相同
;
;該函數是不返回的,進入時堆棧結構是已知的,除了原來的構造的
;標準棧,還壓入了r4 r14(可以參看編譯后的匯編代碼)
;irq的棧結構,進入OSIntExit()時,sp指向的恰好是標準棧頂,但是,由于
;函數中又調用了函數,起始第一句便是一個stmfd sp!,{r4,r14},于是進入
;OSIntCtxSw后還得我們來調整
;-+---+---++-+--+-++-+++--++--+++-+---+---++-+--+-++-+++--++--+++
;低 r4 r14 spsr cpsr r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 lr PC 高
;-+---+---++-+--+-++-+++--++--+++-+---+---++-+--+-++-+++--++--+++
ldmfd sp!,{r0,r1} ;我們的sp_sys已經指向標準棧結構
;后面的內容和OSCtxSw的后半部分相同,依次為
;OSPrioCur = OSPrioHighRdy
;OSTCBCur->OSTCBStkPtr=SP 保存SP到當前任務控制塊
;SP=OSTCBHighRdy->OSTCBStkPtr
;OSTCBCur=OSTCBHighRdy
;彈出現場
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; OSPrioCur = OSPrioHighRdy
; Get current task TCB address
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
;OSTCBCur->OSTCBStkPtr=SP 保存SP到當前任務控制塊
; Get highest priority task TCB address
LDR r6, addr_OSTCBHighRdy
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer
;SP=OSTCBHighRdy->OSTCBStkPtr 更新SP為即將運行的任務
STR r6, [r4] ; set new current task TCB address
; OSTCBCur = OSTCBHighRdy
LDMFD sp!, {r4} ; YYY+
;MSR SPSR_cxsf, r4 ; YYY+運行在sys模式下,無需SPSR的更新
LDMFD sp!, {r4} ; YYY+
MSR CPSR_cxsf, r4 ; YYY+
LDMFD sp!, {r0-r12, lr, pc} ; YYY+
;現場恢復完畢
END
;-+---+---++-+--+-++-+++--++--+++
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -