📄 vectors.s
字号:
;;; Copyright ARM Ltd 1999. All rights reserved. PRESERVE8;/*************************************************************************/;/* INCLUDE FILE */;/*************************************************************************/;/* Define constants used in low-level initialization. */ INCLUDE platform_defs.s ;/*************************************************************************/;/* EXTERNAL VARIABLE/FUNCTION DECLARATIONS */;/*************************************************************************/ IMPORT ExceptionHandler [WEAK] ; Undef, data and prefetch Abort Highlevel Handler IMPORT ExceptionData [WEAK] ; Exception Information will be stored in this struct IMPORT interruptCount IMPORT rescheduleRequired IMPORT rescheduleFromInterrupt IMPORT handler_svc IMPORT interruptStackAddr IMPORT ISR_HandlerServe [WEAK] ; ISR function AREA Vect, CODE, READONLY;/*************************************************************************/;/* */;/* FUNCTION */;/* */;/* REENT_INT_IRQ */;/* */;/*************************************************************************/ EXPORT REENT_INT_IRQREENT_INT_IRQ SUB lr, lr, #4 ; construct the return address STMFD sp!, {lr} ; and push the adjusted lr_IRQ MRS r14, SPSR ; copy spsr_IRQ to r14 STMFD sp!, {r14} ; save spsr_IRQ (copied in r14) STMFD sp!, {r0-r12} ; save r0-r12 registers into irq_sp ; save user SP on IRQ stack STMFD sp, {r13}^ ; because we use another user_sp ; MDM: (point k:) NOP ; last instruction must not be followed by an instruction which accesses banked registers (a following NOP is a good way to ensure this) SUB sp, sp, #4 ; for sys_mode ; interruptCount++ LDR r0, =interruptCount ; r0 = &interruptCount LDR r1, [r0] ; r1 = *r0 ADD r1, r1, #1 ; r1 = r1 + 1 STR r1, [r0] ; *r0 = r1 ; if (interruptCount == 1) -> user sp = interruptStack; CMP r1, #1 BNE l0 LDR r0, =interruptStackAddr ; r0 = &interruptStackAddr LDR r0, [r0] ; r0 = interruptStackAddr STMDB sp, {r0} ; *(irq_sp-4) = interruptStackAddr LDMDB sp, {r13}^ ; user_sp = *(irq_sp-4)l0; MSR CPSR_c, #0xDF ; (11 0 11111) switch to SYS mode, FIQ and IRQ disabled. MSR CPSR_c, #0x9F ; (10 0 11111) switch to SYS mode, FIQ enabled and IRQ disabled. STMFD sp!, {lr} ; save lr into sys_sp ;// Disable interrupts in the EIC (all interrupts with lower priority) LDR r1, =(EIC_BASE_ADDR) ; get EIC BASE address ;MM-PATCHING LDR r2, [r1,#EIC_IVR] ; read EIC IVR to clear NIRQ line, vector itself will be discarded LDR r0, [r1,#EIC_CICR] ; get Current IRQ channel no. ; pass as first parameter channel number to ISR (a1 == r0) LDR r3, =ISR_HandlerServe ; base address of the IRQ vectors (the RAM table!) MOV lr,pc ; Move current program counter to link register ADD lr,lr,#0x8 ; Adjust link register value MSR CPSR_c, #0x1F ; FIQ and IRQ enabled. MOV pc, r3 ; jump to that ISR ;;//******************** Return from ISR ************************* LDMFD sp!, {lr} ; restore lr from sys_sp MSR CPSR_c, #0x92 ; switch to IRQ mode and disable IRQs. FIQ is still enabled. LDMFD sp, {r13}^ ; restore user_sp from irq_sp NOP ADD sp, sp, #4 ; restore sp ;// interruptCount-- LDR r1, =interruptCount ; r1 = &interruptCount LDR r2, [r1] ; r2 = *r1 SUB r2, r2, #1 ; r2 = r2 - 1 STR r2, [r1] ; *r1 = r2 ;// if (interruptCount == 0) ;// if (*IPR == 0 && rescheduleNeeded == 1) ;// restore register state ;// goto rescheduleFromInterrupt CMP r2, #0 ; r2-0 BNE notreschedule ; branch Z clear ;// if (EIC_IPR0) goto notreschedule - pending interrupts LDR r1, =(EIC_BASE_ADDR) ; get EIC BASE address LDR r1, [r1,#EIC_IPR0] ; Read EIC_IPR0 CMP r1, #0 ; r1-0 BNE notreschedule ; branch Z clear ;// if (!rescheduleRequired) goto notreschedule - nothing to reschedule LDR r1, =rescheduleRequired ; r1 = &rescheduleRequired LDR r2, [r1] ; r2 = *r1 CMP r2, #1 ; r2-1 BNE notreschedule ;//RESTORE CONTEXT LDMFD sp!, {r0-r12} ; restore r0-r12 registers from irq_sp LDMFD sp!, {r14} ; restore spsr_IRQ register MSR SPSR_csxf, r14 LDMFD sp!, {r14} ; restore lr from irq_sp B rescheduleFromInterrupt ; branch to rescheduleFromInterrupt routinenotreschedule ; return ;//RESTORE CONTEXT LDMFD sp!, {r0-r12} ; restore r0-r12 registers from irq_sp LDMFD sp!, {r14} ; restore spsr_IRQ register MSR SPSR_csxf, r14 LDMFD sp!, {pc}^ ; return from IRQ.;/* END: INT_IRQ */ END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -