ARM IAR, LPC2000, interrupt theory of op

gasilvis wrote on Sunday, April 19, 2009:

Could someone explain how the interrupts work in the demo project for the ARM7 LPC2000 IAR project?

From the cstart.s:
        ldr   pc,[pc,#+24]              ;; Reset
        ldr   pc,[pc,#+24]              ;; Undefined instructions
;;        ldr   pc,[pc,#+24]              ;; Software interrupt (SWI/SVC)
        b vPortYieldProcessor
        ldr   pc,[pc,#+24]              ;; Prefetch abort
        ldr   pc,[pc,#+24]              ;; Data abort
        DC32  0                         ;; RESERVED
        ldr   pc, [PC, #-0xFF0]         ;; IRQ
        ldr   pc,[pc,#+24]              ;; FIQ

The SWI interrupt calls vPortYieldProcessor.

What does the IRQ interrupt call? Does the "ldr   pc, [PC, #-0xFF0] "  also invoke the vPortYieldProcessor?

I don’t see how the TIMER0 interrupt and its calls to vPortPreemptiveTickEntry get called. Where is IRQ_Handler?

Is IRQ being routed to the SWI interrupt in order to get on the SVC_STACK?

If you have insight into this and can explain the strategy, I’d be obliged.


spacewrench wrote on Sunday, April 19, 2009:

> What does the IRQ interrupt call? Does the "ldr pc, [PC, #-0xFF0] " also invoke the vPortYieldProcessor?

ARM processors (at least, the ones we’re talking about here) place an interrupt table at the beginning of memory.  This table is different from a conventional interrupt vector table in that the table contains _instructions_, not the addresses of the ISRs.  So when an exception occurs (for example, when a peripheral raises an interrupt), the processor loads the constant value 0x00000018 into the instruction pointer, changes some state bits, and resumes executing (by fetching the instruction “LDR PC,[PC,#-0xFF0]” and executing it).

Now, on the LPC2K processors, the Vectored Interrupt Controller has a dynamic register at location 0xFFFFF030 that returns the address of an ISR that’s been set up to handle the highest-priority pending interrupt.  0xFFFFF030 just happens to be 0x00000018 - 0x00000FF0, so the LDR instruction causes the PC to be loaded with the address of this highest-priority interrupt ISR, and the ISR starts running.  (For those of you playing along at home, who have just gotten out your hex calculators and are about to tell me that 0x00000018-0x00000FF0 is not 0xFFFFF030, the difference is because of the way the instruction pipeline works.)

So the short answer is that the LDR instruction is slightly hackish magic, and it Does The Right Thing.  It may invoke vPortYieldProcessor if the VIC has been set up that way, but I don’t think that’s a common way of doing it.  I don’t remember what timer interrupt setup the FreeRTOS port uses.

When I was just starting out with the LPC processor, I couldn’t find a lot of this basic info online, and ended up buying the Steve Furber book, _ARM System-On-Chip Architecture_.  It’s not great, but it’s better than nothing.  (I’m using Luminary Cortex-M3 processors now, and there’s MUCH more info available for download.)

This is based on my slightly vague memories of the LPC.  It should be close enough to get you going, though.

gasilvis wrote on Monday, April 20, 2009:

Aha! So with this “LDR PC,[PC,#-0xFF0]” construct you don’t need:

__irq __arm void IRQ_Handler (void)
  void (*interrupt_function)();
  unsigned int vector;
  vector = VICVectAddr;     // Get interrupt vector.
  interrupt_function = (void(*)())vector;
  (*interrupt_function)();  // Call vectored interrupt function thru pointer
  VICVectAddr = 0;          // Clear interrupt in VIC

The correct interrupt_function will be called directly.   Though you would then need to make sure each of these functions were prefixed with __irq __arm.

Thanks for explanation!

gasilvis wrote on Monday, April 20, 2009:

Quick follow up:   You mentioned "instruction pipeline". Does the "LDR PC,[PC,#-0xFF0]" construct assume that the Memory Acceleration Module (MAM)  is activated at its full level?

Thanks again,

spacewrench wrote on Monday, April 20, 2009:

No, the CPU is set up to achieve the same results whether or not hardware acceleration is in operation.  There are some known bugs with the MAM, but I am not aware of any that would change things such as which memory location a PC-relative load reads from.  (Such a bug would be a showstopper of the finest water; if somebody released a chip with a bug like that, my guess would be that it’d be the last chip they every released.)