Interrupts
Interrupts
Interrupt Controller
Events, Exceptions (faults), and Interrupts
Events are expected or unexpected signals that indicate a new situation may
need immediate attention. Events include:
Fault conditions, like a processor trying to read or write non-existent
memory, or trying to execute an illegal or unimplemented instruction.
Some events do not require immediate attention. These events may set a
status bit, or record some data, and remain “pending” (or awaiting service)
until the processor gets around to checking on and servicing them.
Interrupts generally arise from peripheral circuits that have produced new
data that needs to be consumed in a timely fashion (i.e., before another new
data point comes along), or that need new data to continue operations.
Consider a keyboard key press. If a new keypress arrives every 250ms, the
ARM processor running at 600MHz can do roughly 150 million instructions
between key presses.
I2C has one master and up to 1000 “slaves”, and can run up to 5MHz (most
run < 100KHz). That’s a data rate of 500Kbytes to 10Kbytes per second.
Common uses include low-rate sensors, motor controllers, channel setup
interrupts. 51
IRQ
50 GIC
GPIO
MIO
FPGA-based IP blocks
can also generate 18
17
16
interrupts. 2
1
0
FPGA
Fault conditions can also cause interrupts.
Faults are unexpected events that occur during instruction execution. For
example, a program could attempt to read or write a non-existent memory
location, or attempt to execute and unimplemented instruction.
In many contexts, faults that occur during instruction stream execution are
called exceptions or traps. There is no “standard” definition for these terms
– you must refer to the devices data sheet.
Software can also “force” an interrupt by executing an SVC (service call), or
sometimes by writing the same data that hardware would otherwise have
produced.
Exceptions and Interrupts
ARM presents exceptions and interrupts in a unified way (and they are similar),
and generally refers to both as exceptions.
ARM DDI 0406C.c “ARM Architecture Reference Manual ARM v7-A/R” page B1-1137
Exception Handling
More than one exception might be generated at the same time, and a new
exception can be generated while the processor is handling an exception.
The ARM processor has eight exception vectors stored in eight consecutive
memory locations starting at an exception base address. These form a vector
table.
Application View User System Hypervisor Supervisor Abort Undefined Monitor IRQ FIQ
R0 R0_usr
R1 R1_usr
R2 R2_usr
R3 R3_usr
R4 R4_usr
R5 R5_usr
R6 R6_usr
R7 R7_usr
R8 R8_usr R8_fiq
R9 R9_usr R9_fiq
R10 R10_usr R10_fiq
R11 R11_usr R11_fiq
R12 R12_usr R12_fiq
SP SP_usr SP_hyp SP_svc SP_abt SP_und SP_mon SP_irq SP_fiq
LR LR_usr LR_svc LR_abt LR_und LR_mon LR_irq LR_fiq
PC PC_usr
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
CPSR N Z C V Q IT J RSRV GE IT E A I F T M
When an Exception is taken, a privileged mode is entered
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
CPSR N Z C V Q IT J RSRV GE IT E A I F T M
Privileged modes
User mode is for applications. It is the only unprivileged mode, and has restricted access to system
resources. Typically, a processor spends more than 99% of its time in user mode.
Supervisor mode has unrestricted access to all resources. Entered on reset or power-up, or when
software executes a Supervisor Call instruction (SVC). Typically used by OS’s managing kernel or
other protected files.
System mode is entered from another non-user mode by writing the CPSR. Same GPRs as user
mode, but can access protected resources (recently added to aid in dealing with nested IRQs)
Abort mode is entered if a program attempts to access a non-existing memory location or execute
an undefined instruction.
IRQ mode is entered in response to a normal interrupt request from an external device.
FIQ mode is entered in response to a fast interrupt request from an external device and offers faster
service for more urgent requests. Dates from 8MHz/floppy disk days. FIQ automatically masks IRQ.
Every processor mode except user mode can change to a new mode by writing the CPSR
When an Exception is taken…
The appropriate exception vector is loaded
Address
Asserting IRQ input causes ARM to change modes (to IRQ mode) Offset
and load PC with IRQ vector address. A branch instruction at that ...00 Not Used
address will branch to IRQHandler ...04 B Undefined
...08 B SVCHandler
...0C B PFAbortHandler Vector
...10 B DAbortHandler Table
GIC ARM
...14 Not Used
PL ...18 B IRQHandler
On-board Interrupt Sources
FPGA
Interrupts ...1C B FIQHandler
IRQ
Timer PC ...18
Timers FIQ
Interrupts
Memory Memory AXI Bus
Controller Interrupts
On-board IRQHandler stmdb sp! {r0-r3,
SPI, I2C, Peripheral
CAN, Etc. push {r1}
Interrupts
LDR r2, =gpio_Int
ZYNQ Main
Memory
When an Exception is taken…
00100000 <_vector_table>:
100000: ea000049 b 10012c <_boot>
The code shown is auto-generated 100004: ea000025 b 1000a0 <Undefined>
by SDK and taken from an .elf file. 100008: ea00002b b 1000bc <SVCHandler>
10000c: ea00003b b 100100 <PrefetchAbortHandler>
100010: ea000032 b 1000e0 <DataAbortHandler>
Note the vector table and the 100014: e320f000 nop {0}
B 100020 instruction. The auto- 100018: ea000000 b 100020 <IRQHandler>
10001c: ea00000f b 100060 <FIQHandler>
generated IRQHandler can be
modified to call your IRQ handler 00100020 <IRQHandler>:
function. 100020: e92d500f push {r0, r1, r2, r3, ip, lr}
100024: ed2d0b10 vpush {d0-d7}
100028: ed6d0b20 vpush {d16-d31}
SDK provides a simple way to .
branch to your IRQ handler .
.
When an Exception is taken…
00100000 <_vector_table>:
100000: ea000049 b 10012c <_boot>
You must include 100004: ea000025 b 1000a0 <Undefined>
100008: ea00002b b 1000bc <SVCHandler>
include xil_exception.h 10000c: ea00003b b 100100 <PrefetchAbortHandler>
100010: ea000032 b 1000e0 <DataAbortHandler>
In your source file. 100014: e320f000 nop {0}
100018: ea000000 b 100020 <IRQHandler>
10001c: ea00000f b 100060 <FIQHandler>
Then you can use the function:
“Xil_ExceptionRegisterHandler” 00100020 <IRQHandler>:
with parameters ‘5’ (for IRQ vector), 100020: e92d500f push {r0, r1, r2, r3, ip, lr}
100024: ed2d0b10 vpush {d0-d7}
the name of your C function, and 100028: ed6d0b20 vpush {d16-d31}
NULL. .
.
.
00100020 <IRQHandler>:
100020: e92d500f push {r0, r1, r2, r3, ip, lr}
100024: ed2d0b10 vpush {d0-d7}
100028: ed6d0b20 vpush {d16-d31}
.
.
.
Callee-saved Registers xuartps_hw.c: Disassembly
Reference:
1. IHI0042F ARM Procedure Call Standard for the ARM Architecture (AAPCS)
Section 5.1
2. Wikipedia: Calling Convention – ARM(A32)
19
Programming Model for Using Interrupts
Initialization
• Vector table setup (done automatically by SDK, but can be changed)
• Configure GIC (default done automatically, but app must customize)
• Establish priorities for selected interrupts; select sensitivity; enable source and CPU
• Configure source to produce interrupts (User app must do)
• Select sensitivity; select polarity; enable source
21
GIC Registers
ICCPMR 1 8 0x0F8F0 0104 CPU priority mask defines minimum priority interrupts must need to be taken
ICDISER 3 32 0x0F8F0 1100 Enable interrupt sources to be forwarded to CPU (1 bit per interrupt)
ICDICER 3 32 0x0F8F0 1180 Turn on or off interrupt sources (1 bit per interrupt)
ICDIPR 24 32 0x0F8F0 1400 Priority fields (8 bits per interrupt). Must be > ICCPMR for interrupt to be taken
ICDIPTR 24 8 0x0F8F0 1800 Processor targets (2 bits per interrupt). Must set to “01”
ICDICFR 6 32 0x0F8F0 1C00 Sensitivity (2-bits per interrupt). “01” for level sensitivity; “11” for edge
22
Enabling Interrupts
To enable interrupts, the I or F bit in the CSPR must be set (for IRQ or FIQ). The
CPSR cannot be accessed from user mode, except by two special instructions.
The “Move Special to Register” (MSR) instruction can move the CPSR to a GPR,
and the “Move Register to Special” (MRS) can move from GPR to CPSR. These
special instructions have no “C” correlate, so they must be “passed through”
using a special C syntax:
void disable_ARM_A9_interrupts(){
uint32_t mode = 0xDF; // System mode [4:0] and IRQ disabled [7]
uint32_t read_cpsr=0; // used to read previous CPSR value
uint32_t bit_mask = 0xFF; // used to clear bottom 8 bits
__asm__ __volatile__("mrs %0, cpsr\n" : "=r" (read_cpsr) );
__asm__ __volatile__("msr cpsr,%0\n" : : "r" ((read_cpsr & (~bit_mask))| mode));
return; } 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
23
CPSR N Z C V Q IT J RSRV GE IT E A I F T M
Enabling Interrupts
The GIC can be configured following the 9-step procedure in the Project 4
description.
After the GIC is configured, the interrupt source must be configured as well.
Typically, every peripheral that can generate interrupts will have one to several
registers that must be properly configured to enable interrupts.
24
Interrupt Handler
Interrupt handlers run at unscheduled times, and disrupt unknown programs.
They must be sure to save and restore all context.
When writing in assembly, all context should be stored on the stack. When
writing in C, the compiler will do that for you. The LR and CPSR are automatically
saved in local registers (and restored on exit) during mode changes.
Since the ARM has only one interrupt signal (or two if you count FIQ), the
handler must determine the interrupt ID#, and then branch appropriatly.
The IRQ handler for each ID# can perform it’s task and then return.
25
Interrupt Handler
In general, you should spend as little time as possible in the handler.
You must decide if you want to allow other (or higher priority) interrupts to
interrupt your handler, and enable or disable interrupts as appropriate.
26
Interrupts: General Concepts
Latency
Priority (NMI)
(Note if two interrupts share the same priority, the lowest ID# wins).
27
Interrupts: Source Name ID# Source Name ID#
CAN 0 60
28