本帖最后由 nicholasldf 于 2013-11-9 19:28 编辑
OS_CPU_A.ASM文件 ---------------续-------------------
;********************************************************************************************************
; GLOBAL EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr
MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR).
; DETERMINE IF WE INTERRUPTED A TASK/IRQ OR ANOTHER LOWER PRIORITY EXCEPTION:
; SPSR.Mode = SVC : task or IRQ handled in SVC mode,
; SPSR.Mode = FIQ, IRQ, ABT, UND : other exceptions,
; SPSR.Mode = USR : *unsupported state*.
AND R3, R1, #OS_CPU_ARM_MODE_MASK
CMP R3, #OS_CPU_ARM_MODE_SVC
BNE OS_CPU_ARM_ExceptHndlr_BrkExcept
;********************************************************************************************************
; EXCEPTION HANDLER: EXCEPTION INTERRUPTED
;
; Register Usage: R0 Source ID
; R1
; R2
; R3
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr_BrkExcept
STMFD SP!, {R1} ; Push exception's SPSR.
MRS R3, CPSR ; Push exception's CPSR.
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
STMFD SP!, {R3}
; HANDLE NESTING COUNTER:
LDR R2, =OSIntNestingCtr ; OSIntNestingCtr++;
LDRB R4, [R2]
ADD R4, R4, #1
STRB R4, [R2]
MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE.
; EXECUTE EXCEPTION/INTERRUPT HANDLER:
LDR R2, =OS_CPU_IntHandler ; OS_CPU_IntHandler(src_id = R0);
MOV LR, PC
BX R2
; 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, =OSIntNestingCtr ; OSIntNestingCtr--;
LDRB R4, [R2]
SUB R4, R4, #1
STRB R4, [R2]
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.
;********************************************************************************************************
; EXCEPTION HANDLER: IRQ INTERRUPTED
;
; Register Usage: R0 Source ID
; R1
; R2
; R3
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr_BrkIRQ
MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE.
; EXECUTE EXCEPTION/INTERRUPT HANDLER:
LDR R1, =OS_CPU_IntHandler ; OS_CPU_IntHandler(src_id = R0);
MOV LR, PC
BX R1
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring IRQ context.
ADD SP, SP, #(14 * 4)
; 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, =OSIntNestingCtr ; OSIntNestingCtr--;
LDRB R4, [R2]
SUB R4, R4, #1
STRB R4, [R2]
; RESTORE IRQ'S CONTEXT:
OS_CPU_ARM_FP_REG_POP R0 ; Pop exception's FP context.
LDMFD SP!, {R0} ; Pop IRQ's CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ; Pop IRQ's context.
;********************************************************************************************************
; IRQ HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptIrqHndlr
SUB LR, LR, #4 ; LR offset to return from this exception: -4.
STMFD SP!, {R0-R3} ; Push working registers.
MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ.
MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR).
MOV R2, LR ; Save link register.
MOV R3, SP ; Save exception's stack pointer.
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; SAVE CONTEXT ONTO SVC STACK:
STMFD SP!, {R2} ; Push task's PC,
STMFD SP!, {LR} ; Push task's LR,
STMFD SP!, {R4-R12} ; Push task's R12-R4,
LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack.
STMFD SP!, {R5-R8}
STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR).
OS_CPU_ARM_FP_REG_PUSH R3 ; Push FP context
; if (OSRunning == 1)
LDR R3, =OSRunning
LDRB R4, [R3]
CMP R4, #1
BNE OS_CPU_ARM_IRQHndlr_BreakNothing
; HANDLE NESTING COUNTER:
LDR R3, =OSIntNestingCtr ; OSIntNestingCtr++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
CMP R4, #1 ; if (OSIntNestingCtr == 1)
BNE OS_CPU_ARM_IRQHndlr_BreakIRQ
;PAGE
;********************************************************************************************************
; IRQ HANDLER: IRQ INTERRUPTED
;
; Register Usage: R0 Source ID
; R1
; R2
; R3
;********************************************************************************************************
OS_CPU_ARM_IRQHndlr_BreakIRQ
LDR R3, =OS_CPU_ExceptStkPtr ; OS_CPU_ExceptStkPtr = SP;
STR SP, [R3]
; EXECUTE EXCEPTION/INTERRUPT HANDLER:
LDR R3, =OS_CPU_IntHandler ; OS_CPU_IntHandler(src_id = R0)
MOV LR, PC
BX R3
; Change to IRQ mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ)
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring task context.
ADD SP, SP, #(4 * 4)
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; HANDLE NESTING COUNTER:
LDR R3, =OSIntNestingCtr ; OSIntNestingCtr--;
LDRB R4, [R3]
SUB R4, R4, #1
STRB R4, [R3]
; RESTORE OLD CONTEXT:
OS_CPU_ARM_FP_REG_POP R0 ; Pop old FP context.
LDMFD SP!, {R0} ; Pop old CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception.
;PAGE
;********************************************************************************************************
; IRQ HANDLER: 'NOTHING' INTERRUPTED
;
; Register Usage: R0 Source ID
; R1
; R2
; R3
;********************************************************************************************************
OS_CPU_ARM_IRQHndlr_BreakNothing:
; EXECUTE EXCEPTION/INTERRUPT HANDLER:
LDR R3, =OS_CPU_IntHandler ; OS_CPU_IntHandler(src_id = R0)
MOV LR, PC
BX R3
; Change to IRQ mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ)
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring task context.
ADD SP, SP, #(4 * 4)
; Change to SVC mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)
; RESTORE OLD CONTEXT:
OS_CPU_ARM_FP_REG_POP R0 ; Pop old FP context.
LDMFD SP!, {R0} ; Pop old CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception.
END
|