Alright folks,
I'm attempting to cut my teeth on ARM assembly, but I can't quite grasp the concept of interrupts. Prior to this, I've worked with AVR interrupts, where code was written to explicitly link the interrupt vector to the subroutine or segment being jumped into:
.ORG $0022
RJMP TIMER_INTERRUPT
However, in working with the Atmel SAMA5D3 series, I can't figure out how to accomplish something similar. I understand that the first 8 interrupt vectors lie in the first 8 program counter addresses (reset
at 0x00
to fiq
at 0x1C
), but I haven't been able to find a good, no-nonsense, easy-to-understand resource on how the individual peripheral interrupts (SPI, UART, TC modules) map into the standardized ARM vector table.
That is, suppose in the code I configure the UART to be able to throw interrupts. What occurs when it throws an interrupt? Does the address for the irq
entry (0x18
) contain the location of a table of the device-specific vectors? How does the vendor- and device-specific peripherals assert interrupts via the core-standardized table?
I've consulted with the datasheet for the SAMA5D3 as well as the ARM ARM and I haven't found much that makes it easier on the part of a beginner. My apologies if anything is unclear, and shame on the world for eschewing assembly.
EDIT:
From the SAMA5D3 datasheet, page 118, it states that:
It is assumed that:
- The Advanced Interrupt Controller has been programmed, AIC_SVR registers are loaded with corresponding interrupt service routine addresses and interrupts are enabled.
- The instruction at the ARM interrupt exception vector address is required to work with the vectoring:
LDR PC, [PC, # -&F20]
When
nIRQ
is asserted, if the bit āIā ofCPSR
is 0, the sequence is as follows:
- The
CPSR
is stored inSPSR_irq
, the current value of the Program Counter is loaded in the Interrupt link register (R14_irq
) and the Program Counter (R15
) is loaded with 0x18. In the following cycle during fetch at address 0x1C, the ARM core adjustsR14_irq
, decrementing it by four.- The ARM core enters Interrupt mode, if it has not already done so.
- When the instruction loaded at address 0x18 is executed, the program counter is loaded with the value read in
AIC_IVR
.
This is understandable. From reading this plus looking at the register numbers, I put the peripheral interrupt source (i.e. SPI0/1
) number into the INTSEL
field of AIC_SSR
, and then it sounds like I store the address of the ISR into AIC_SVR
.
There are two problems, one of which is that I don't understand the vectoring instruction (LDR PC, [PC, # -&F20]
) that needs to be present and compatible with the irq
vector address at 0x18
.
The other problem being, how does one enable multiple interrupts? There is only one INTSEL
field and source vector register, so how would one run multiple interrupt handlers on this system?
My continued apologies, folks, if I'm not getting this, but I at least try to do my homework on it.