?? os_cpu_a.s
字號:
;/********************************************************************************************************/
;/* 文件 os_cpu_a.s
;/* 作者 焦進星
;/* 時間 2008年1月29日
;/* 描述 ucosii 2.85 在GBA上與CPU有關的移植代碼
;/* QQ 376637405
;/* E_mail wyoujtg@163.com
;/* 用VisualBoyAdvance 模擬器仿真
;/********************************************************************************************************/
;//模式與標志定義
ARM_MODE_USER EQU 0x10
ARM_MODE_FIQ EQU 0x11
ARM_MODE_IRQ EQU 0x12
ARM_MODE_SVC EQU 0x13
ARM_MODE_ABORT EQU 0x17
ARM_MODE_UNDEF EQU 0x1B
ARM_MODE_SYS EQU 0x1F
I_BIT EQU 0x80
F_BIT EQU 0x40
T_BIT EQU 0x20
EXTERN OSRunning ;//聲名輸入
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXPORT OS_CPU_SR_Save ;//聲名輸出
EXPORT OS_CPU_SR_Restore
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
;/*******************************************************************************************************/
;/* 第三種臨界處理方式 */
;/*******************************************************************************************************/
AREA |.text|, CODE, READONLY
CODE32
OS_CPU_SR_Save
MRS R0,CPSR ;//保存CPSR到R0并禁止IRQ和FIQ中斷
ORR R1,R0,#(I_BIT | F_BIT)
MSR CPSR_c,R1
BX LR
OS_CPU_SR_Restore ;//將R0恢復到CPSR
MSR CPSR_c,R0
BX LR
;/********************************************************************************************************/
;/* void OSStartHighRdy(void) */
;/* 進入最高級就緒任務 */
;/********************************************************************************************************/
AREA |.text|, CODE, READONLY
CODE32
OSStartHighRdy
MSR CPSR_c, #(I_BIT | F_BIT| ARM_MODE_SYS) ;//進入系統模式并禁止IRQ和FIQ中斷
LDR R4, OS_Running ;//設定多任務開始標志
MOV R5, #1
STRB R5, [R4]
;
LDR R4, OS_TCBHighRdy ;//得到最高優先級任務的TCB地址
LDR R6, [R4] ;//得到該任務堆棧指針
LDR R4, [R6] ;//R4(SP) = OSTCBHighRdy->OSTCBStkPtr
MOV SP, R4
;//恢復新任務上下文
LDMFD SP!, {R4}
MSR CPSR_c, R4 ;//恢復新任務CPSR
LDMFD SP!, {R0-R12,LR,PC} ;//恢復新任務上下文
;/********************************************************************************************************/
;/* void OSCtxSw(void) */
;/* 任務級任務切換函數 */
;/********************************************************************************************************/
AREA |.text|, CODE, READONLY
CODE32
OSCtxSw ;//保存任務上下文
STMFD SP!, {LR} ;//保存返回地址(LR代替PC)
STMFD SP!, {R0-R12, LR} ;//保存寄存器
MRS R4, CPSR ;//保存CPSR
STMFD SP!, {R4}
OSCtxSw1
LDR R4, OS_TCBCur ;//OSTCBCur->OSTCBStkPtr = SP
LDR R5, [R4]
STR SP, [R5]
LDR R4, OS_PrioCur ;//OSPrioCur = OSPrioHighRdy
LDR R5, OS_PrioHighRdy
LDRB R6, [R5]
STRB R6, [R4]
LDR R4, OS_TCBCur ;//OSTCBCur = OSTCBHighRdy
LDR R6, OS_TCBHighRdy
LDR R6, [R6]
STR R6, [R4]
OSCtxSw2
LDR R4, [R6] ;//R4(SP) = OSTCBHighRdy->OSTCBStkPtr
MOV SP, R4
;//恢復新任務上下文
LDMFD SP!, {R4}
MSR CPSR_c, R4 ;//恢復新任務CPSR
LDMFD SP!, {R0-R12,LR,PC} ;//恢復新任務上下文
;/********************************************************************************************************/
;/* void OSIntCtxSw(void) */
;/* 中斷級任務切換函數 */
;/********************************************************************************************************/
AREA |.text|, CODE, READONLY
CODE32
OSIntCtxSw
;/********************************************************************
; IRQ STACK <LOW> R4 R14 | SPSR R0 R1 R2 R3 R11 R12 LR(PC) <HIGH>
;********************************************************************/
ADD SP, SP, #(0+8)*4 ;//因不在IRQ模式保存上下文,先調整IRQ模式堆棧指針
SUB R0, SP, #3*4
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_SYS) ;// 進入系統模式
;//作堆棧轉換
LDMIA R0, {R1-R3} ;// R11,R12,LR(PC)=>R1,R2,R3
SUB R0, R0, #5*4 ;// Moving (SPSR, R3-R0)
STMFD SP!, {R3} ;// R3(PC)=>[SP]
STMFD SP!, {R1-R2, LR} ;// R1(R11),R2(R12),LR=>[SP]
STMFD SP!, {R4-R10} ;// R4-R10=>[SP]
LDMIA R0, {R4-R8} ;// SPSR,R0-R3=>R4-R8
STMFD SP!, {R4-R8} ;// R4(SPSR),R5-R8(R0-R3)=>[SP]
B OSCtxSw1 ;//恢復新任務上下文
;/**********************************************************************************************************/
;/* 中斷向量 */
;/**********************************************************************************************************/
IMPORT IntrTable ;//聲名輸入
EXPORT intr_main ;//聲名輸出
AREA |.text|, CODE, READONLY
CODE32
intr_main
SUB LR, LR, #4 ;//調整和保存 LR_irq 在IRQ 堆棧
STMFD SP!, {R0-R3, R11, R12, LR} ;//保存用到的寄存器和LR到IRQ堆棧
;//保存R11是為了用其暫存LR_svc
MRS R14, SPSR ;//保存SPSR
STMFD SP!, {R14}
LDR R11, =OSIntNesting ;//OSIntNesting++,跟蹤中斷嵌套
LDRB R12, [R11]
ADD R12, R12,#1
STRB R12, [R11]
mov r3, #0x4000000 ;// REG_BASE
ldr r2, [r3,#0x200]! ;// Read REG_IE
and r1, r2, r2, lsr #16 ;// r1 = IE & IF
ldr r2, =IntrTable
ands r0, r1, #1 ;// V-Blank Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #2 ;// H-Blank Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #4 ;// V Counter Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #8 ;// Timer 0 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x10 ;// Timer 1 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x20 ;// Timer 2 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x40 ;// Timer 3 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x80 ;// Serial Communication Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x100 ;// DMA0 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x200 ;// DMA1 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x400 ;// DMA2 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x800 ;// DMA3 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x1000 ;// Key Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x2000 ;// Cart Interrupt
jump_intr
strh r0, [r3, #2] ;// IF Clear
ldr r0, [r2] ;// Jump to user IRQ process
MSR CPSR_c, #ARM_MODE_SVC ;//進入SVC模式 開IRQ和FIQ中斷
MOV R11, LR ;//R11<-LR_svc,暫存LR_svc
MOV LR, PC ;//中斷服務例程返回用
BX r0 ;//執行中斷服務例程
MOV LR, R11 ;//恢復LR
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_IRQ) ;//進入IRQ模式 禁止IRQ和FIQ中斷
BL OSIntExit ;//調用中斷退出處理 OSIntExit()
LDR R0, =OSPrioCur ;//if (OSPrioCur != OSPrioHighRdy) 需要調度
LDR R1, =OSPrioHighRdy
LDRB R0, [R0]
LDRB R1, [R1]
CMP R0, R1
BNE OSIntCtxSw ;//執行中斷任務切換OSIntCtxSw()
LDMFD SP!, {R14} ;//恢復SPSR_irq from從IRQ堆棧
MSR SPSR_cxsf, R14
LDMFD SP!, {R0-R3, R11, R12, PC}^ ;//恢復調整后的LR_irq,直接恢復PC返回,執行原子操作恢復新任務CPSR
;/********************************************************************************************************/
;/* 指針變量 */
;/********************************************************************************************************/
OS_IntExit
DCD OSIntExit
OS_IntNesting
DCD OSIntNesting
OS_PrioCur
DCD OSPrioCur
OS_PrioHighRdy
DCD OSPrioHighRdy
OS_Running
DCD OSRunning
OS_TCBCur
DCD OSTCBCur
OS_TCBHighRdy
DCD OSTCBHighRdy
END
;/********************************************************************************************************/
;/* 結束文件 */
;/********************************************************************************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -