This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Interrupts not through vector table ?

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.

    Regards Terje Bøhler

  • 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.