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

Cortex A9 MPCore Interrupts

I'm writing a bare metal code for handling interrupts on an iMX6Quad (NXP) so A9 MPCore core. I'm having difficultly having the core (just using core1) respond to an interrupt. I chose the local timer for simplicity. In the iMX6, it is vector 29. The pertinent code is shown in the file Interrupts.txt. After the code runs for awhile, I halted it to see what was going on. What was supposed to happen was the code would halt at a breakpoint set at the first instruction in irq_isr (which didn't happen). Most of the affected registers are shown in the file Interrupt 1.png. On the left you can see that EVENT_FLAG is set, as is the interrupt enable. In the GICD_CTLR reg, both secure and non-secure enables are set. In GICD_GROUPR0, vector 29 is set to group 1 (non-secure). The ISENABLER0 reg shows vector 29 is enabled. Vector 29 is "hard-targeted" to core 1 since it is a PPI. GICD_PRIORITY29 is set to 0xA0 (see Interrupts 2). The GICC_CTLR shows both secure and non-secure interrupts being forwarded. The PMR reg shows a priority of 0xFF which is the lowest priority. The IAR reg shows vector 29; and the RPR reg shows that it picked up the new priority of 0xA0. The function set_vbar WAS called in the boot up code. The "I" bit in the CPSR is set low to enable the IRQ exception.

Interrupts.txt
// This is the actual hardware exception table, the address of which is loaded
// into the VBAR. This section must be aligned on a 4-byte boundary (VBAR)
vector_tbl
     ldr pc, =__boot
     ldr pc, =undef_isr
     ldr pc, =svc_isr
     ldr pc, =prefetch_isr
     ldr pc, =abort_isr
     nop                     // reserved
     ldr pc, =irq_isr
     ldr pc, =fiq_isr


/*******************************************************************************
 * Set the location of the hardware vector table into the VBAR reg
 * On entry, r0 holds the location
 ******************************************************************************/
set_vbar
     ldr r0, =vector_tbl
     mcr p15, 0, r0, c12, c0, 0      //write VBAR register

     // SCTLR bit V - location of exception vectors -> 0x00000000-0x0000001C
     mrc p15, 0, r0, c1, c0, 0       //read SCTLR
     bic r0, r0, #0x2000             //clear V bit
     mcr p15, 0, r0, c1, c0, 0       //write SCTLR

     bx lr                           //return


/*******************************************************************************
 * Handle IRQ exception
 ******************************************************************************/
irq_isr
     // Save registers
     push   {r0-r12, lr}
     
     // Call the IRQ Exception handler
     ldr    r0, =irq_hnlr   //make sure bit0 is 0
     blx    r0
     
     // Return to normal program flow
     pop    {r0-r12, lr}
     subs   pc, lr, #4

What I expect should happen is that at this point, execution should jump to the IRQ exception, which would start execution at irq_isr, but this never happens. I'm sure I'm overlooking something, but I don't know what it is? Can anyone help?

  • So I've done some more work on this however, I'm having strange results. As you can see in registers.png, the GICC shows that the local timer (29 - 0x1D) is recognized as the highest priority interrupt in the GICC_IAR reg. The GICD shows vector 29 as pending, enabled, and non-secure. The CPSR shows that the CPU is in IRQ mode (10010) but the CPU actually takes the SVC address, going to the SVC handler. As you can see in Interrupts.txt, there's no mistake in the vector table, it's just the wrong vector taken. Any idea what's wrong?

    5543.Interrupts.txt
      507                              ASM_CODE_SECTION(vector_rom)
      508                           
      509                           // This is the actual hardware exception
                                     table, the address of which is loaded
      510                           // into the VBAR. This section must be aligned
                                     on a 4-byte boundary (VBAR)
      511                           _vector_tbl
      512    00000000 18F09FE5           ldr pc, reset_addr
      513    00000004 18F09FE5           ldr pc, undefined_addr
      514    00000008 18F09FE5           ldr pc, svc_addr
      515    0000000C 18F09FE5           ldr pc, prefetch_addr
      516    00000010 18F09FE5           ldr pc, abort_addr
      517    00000014 00F020E3           nop                 /* reserved */
      518    00000018 18F09FE5           ldr pc, irq_addr
      519    0000001C 18F09FE5           ldr pc, fiq_addr
      520                           
      521                           ASM_LABEL(_vector_addr)
      522    00000020 ........      ASM_LABEL_CONST32(reset_addr, __boot)
      523    00000024 ........      ASM_LABEL_CONST32(undefined_addr, undefined_handler
      524    00000028 ........      ASM_LABEL_CONST32(svc_addr, svc_handler)
      525    0000002C ........      ASM_LABEL_CONST32(prefetch_addr, prefetch_handler
      526    00000030 ........      ASM_LABEL_CONST32(abort_addr, abort_handler)
      527    00000034 00000000      ASM_LABEL_CONST32(resvd_addr, 0)
      528    00000038 ........      ASM_LABEL_CONST32(irq_addr, irq_handler)
      529    0000003C ........      ASM_LABEL_CONST32(fiq_addr, fiq_handler)
    
    
    /*******************************************************************************
     * Set the location of the hardware vector table into the VBAR reg
     * On entry, r0 holds the location
     ******************************************************************************/
    set_vbar
         ldr r0, =vector_tbl
         mcr p15, 0, r0, c12, c0, 0      //write VBAR register
    
         // SCTLR bit V - location of exception vectors -> 0x00000000-0x0000001C
         mrc p15, 0, r0, c1, c0, 0       //read SCTLR
         bic r0, r0, #0x2000             //clear V bit
         mcr p15, 0, r0, c1, c0, 0       //write SCTLR
    
         bx lr                           //return
    
    
    /*******************************************************************************
     * Handle IRQ exception
     ******************************************************************************/
    irq_isr
         // Save registers
         push   {r0-r12, lr}
         
         // Call the IRQ Exception handler
         ldr    r0, =irq_hnlr   //make sure bit0 is 0
         blx    r0
         
         // Return to normal program flow
         pop    {r0-r12, lr}
         subs   pc, lr, #4