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.
// 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?
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