本帖最后由 machunshui 于 2009-10-13 09:23 编辑
UCOS for lpc2000 arm 移植中断入口代码分析
arm由于有多种运行模式,导致ucos在arm上移植时,中断入口处理比别的MCU复杂不少,现试作以下分析。
这是一段基于IAR的ucos 在lpc2000 arm上的移植。
;*********************************************************************************************************
; IRQ Interrupt Service Routine
;*********************************************************************************************************
RSEG CODE:CODE:NOROOT(2)
CODE32
OS_CPU_IRQ_ISR
STMFD SP!, {R1-R3} ; 下面要用到r1,r2,r3,先入中断模式堆栈保护
MOV R1, SP ; 中断模式SP--->r1
ADD SP, SP,#12 ; 调整中断模式SP,使之指向r1,r2,r3入栈前的位置
SUB R2, LR,#4 ; 调整中断返回地址
MRS R3, SPSR ; 中断模式spsr--->r3,中断模式spsr即发生中断前的任务代码的cpsr
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; 转换到管理模式(即任务代码的运行模式)
; SAVE TASK'S CONTEXT ONTO TASK'S STACK
STMFD SP!, {R2} ; 中断返回地址入管理模式堆栈
STMFD SP!, {LR} ; 任务的LR入管理模式堆栈
STMFD SP!, {R4-R12} ; R4-R12入管理模式堆栈
LDMFD R1!, {R4-R6} ; 由中断模式的堆栈弹出先前保存的r1,r2,r3
STMFD SP!, {R4-R6} ; 入管理模式堆栈
STMFD SP!, {R0} ; r0入管理模式堆栈
STMFD SP!, {R3} ; 中断模式spsr入管理模式堆栈,中断模式spsr即即发生中断前的任务代码的cpsr
;
LDR R0, ??OS_IntNesting ; OSIntNesting++;
LDRB R1, [R0]
ADD R1, R1,#1
STRB R1, [R0]
CMP R1, #1 ; if (OSIntNesting == 1) {
BNE OS_CPU_IRQ_ISR_1
LDR R4, ??OS_TCBCur ; 非嵌套中断, OSTCBCur->OSTCBStkPtr = SP
LDR R5, [R4]
STR SP, [R5] ; }
OS_CPU_IRQ_ISR_1
MSR CPSR_c, #(NO_INT | IRQ32_MODE) ; 切换到IRQ模式
LDR R0, ??OS_CPU_IRQ_ISR_Handler ; 调用用户中断处理
MOV LR, PC
BX R0
MSR CPSR_c, #(NO_INT | SVC32_MODE) ; 切换到管理模式
LDR R0, ??OS_IntExit ; OSIntExit(),任务切换代码在其中
MOV LR, PC
BX R0
; 返回到新任务
LDMFD SP!, {R4} ; 任务代码的cpsr出管理模式堆栈
MSR SPSR_cxsf, R4 ;存入当前管理模式的SPSR
LDMFD SP!, {R0-R12,LR,PC}^ ; 任务环境出管理模式堆栈,中断退出,注意:指令最后的^ ,在出出栈列表里面有PC的时候表示,把SPSR复制到CPSR |