📄 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_SYS ;//进入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 + -