OS_CPU_ARM_ExceptHndlr_BrkExcept
STMFD SP!, {R1} ; Push exception's SPSR.
;luodefu add - 保存EXP现场堆栈指针,以便OS_CPU_ExceptHndlr输出异常时的寄存器信息
;堆栈存储信息为CPSR R0-R12 LR,没有PC
LDR R2, =OS_CPU_ExceptStkPtr ; OS_CPU_ExceptStkPtr = SP;
STR SP, [R2]
MRS R3, CPSR ; Push exception's CPSR.
STMFD SP!, {R3}
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; HANDLE NESTING COUNTER:
LDR R2, =OSIntNesting ; OSIntNesting++;
LDRB R4, [R2]
ADD R4, R4, #1
STRB R4, [R2]
MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE.
; EXECUTE EXCEPTION HANDLER:
LDR R2, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0);
MOV LR, PC
BX R2
;以下原始代码BUG - 切换到SVC模式操作OSIntNesting变量,然后通过SVC的SP恢复R3,而不是异常模式的SP,R3的值是未知的
MRS R3, CPSR;luodefu 保存当前异常模式
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; HANDLE NESTING COUNTER:
LDR R2, =OSIntNesting ; OSIntNesting--;
LDRB R4, [R2]
SUB R4, R4, #1
STRB R4, [R2]
MSR CPSR_cxsf, R3;luodefu 恢复当前异常模式,下面两行汇编代码除了将R3出栈,做了重复的恢复当前模式的工作
LDMFD SP!, {R3}
MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE.
; RESTORE INTERRUPTED EXCEPTIONS' CONTEXT:
LDMFD SP!, {R0} ; Pop exception's CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, PC}^ ; Pull working registers and return from exception.
|