Hello.
As stated previously, I'm not not very familiar with ARM/Keil uV4. My problem: My PIT interrupt service routine: "__irq ISR_Pit()" seems to: 1) Beeing executed WITHOUT beeing routed/executed through the VECTOR table. 2) When executed once, PC simply returns to start of ISR_Pit() for another round of execution (with "terrible consequences" thereafter ....).
Q1: Isn't ALL interrupts/exceptions to be executed via/through the VECTOR table ? Q2: I assume the definition/declaration "void __irq ISR_Pit(void)" is sufficient to ensure register bank switching so PC returns back to normal execution after executing this interrupt service routine?
Regards Terje Bøhler
By the way, the MCU used is AT91SAM7X512. Terje
Yes, the interrupts are now working/routed via the VECTOR table. The problem was that there were a branch and not a LDR in vector table. The branch did not work for our AT91SAM7X512 (ARM version: ARMv4T). The following is now OK:
Vectors LDR PC,Reset_Addr LDR PC,Undef_Addr LDR PC,SWI_Addr LDR PC,PAbt_Addr LDR PC,DAbt_Addr NOP ; Reserved Vector LDR PC,IRQ_Addr LDR PC,FIQ_Addr
But, nevertheless, my ISR is still entered twice (immediate return to my ISR after the termination of the 1st occurence/execution). Any idea why (interrupt IS turned OFF inside the ISR) ? Am I missing some asm- or C-code directives regarding stack-usage (stack-size should be OK) ? In case which ?
Regards Terje
So, can anyone see a reason for double execution of the ISR from the following irqHandler? I'm not an ARM asm-expert and cannot easily decode all details in the code below:
AT91C_BASE_AIC EQU 0xFFFFF000 ; (AIC) Base Address AIC_IVR EQU 0x00000100 ; (AIC_IVR) IRQ Vector Register AIC_EOICR EQU 0x00000130 ; (AIC_EOICR) End of Interrupt Command Register ARM_MODE_SVC EQU 0x13 ARM_MODE_IRQ EQU 0x12 I_BIT EQU 0x80 irqHandler ; Save interrupt context on the stack to allow nesting sub lr, lr, #4 stmfd sp!, {lr} mrs lr, SPSR stmfd sp!, {r0, lr} ; Write in the IVR to support Protect Mode ldr lr, =AT91C_BASE_AIC ldr r0, [r14, #AIC_IVR] str lr, [r14, #AIC_IVR] ; Branch to interrupt handler in Supervisor mode msr CPSR_c, #ARM_MODE_SVC stmfd sp!, {r1-r3, r4, r12, lr} mov lr, pc bx r0 ldmia sp!, {r1-r3, r4, r12, lr} ; msr CPSR_c, #ARM_MODE_IRQ | I_BIT msr CPSR_c, #ARM_MODE_IRQ:OR:I_BIT ; Acknowledge interrupt ldr lr, =AT91C_BASE_AIC str lr, [r14, #AIC_EOICR] ; Restore interrupt context and branch back to calling code ldmia sp!, {r0, lr} msr SPSR_cxsf, lr ldmia sp!, {pc}^
I'll very much appreciate your answers.
You think it might be helpful to provide both sides of the transaction? ie Where you set up the interrupt, and where you service it?
I'm pretty sure the ATMEL part acts very much like all the other ARM7 implementations with regards to registers, stacks, and interrupt context. Got to be a vast array of documentation and examples out there.