You copied the Doc URL to your clipboard.

Interrupt prioritization

The following example dispatches up to 32 interrupt sources to their appropriate handlers. Because it is designed for use with the normal interrupt vector, IRQ, it is branched to from location 0x18.

Use external Vectored Interrupt Controller (VIC) hardware to prioritize the interrupt and present the high-priority active interrupt in an I/O register.

In the example code:


Holds the base address of the interrupt controller.


Holds the offset of the register containing the highest-priority active interrupt.


Is assumed to point to a small full descending stack.

Interrupts are enabled after ten instructions, including the branch to this code.

The specific handler for each interrupt is entered, with all registers preserved on the stack, after two more instructions.

In addition, the last three instructions of each handler are executed with interrupts turned off again, so that the SPSR can be safely recovered from the stack.

    ; first save the critical state
    SUB     lr, lr, #4              ; Adjust the return address
                                    ; before we save it.
    STMDB   sp!, {lr}               ; Stack return address
    MRS     lr, SPSR                ; get the SPSR ...
    PUSH    {R12,lr}                ; ... and stack that plus a
                                    ; working register too.
                                    ; Now get the priority level of the
                                    ; highest priority active interrupt.
    MOV     R12, #IntBase           ; Get the interrupt controller's
                                    ; base address.
    LDR     R12, [R12, #IntLevel]   ; Get the interrupt level (0 to 31).
                                    ; Now read-modify-write the CPSR
                                    ; to enable interrupts.
    MRS     lr, APSR                ; Read the status register.
    BIC     lr, lr, #0x80           ; Clear the I bit
                                    ; (use 0x40 for the F bit).
    MSR     CPSR_c, lr              ; Write it back to re-enable
                                    ; interrupts and
    LDR     pc, [pc, R12, LSL #2]   ; jump to the correct handler.
                                    ; PC base address points to this
                                    ; instruction + 8
    NOP                             ; pad so the PC indexes this table.
                                    ; Table of handler start addresses
    DCD     Priority0Handler
    DCD     Priority1Handler
    DCD     Priority2Handler
; ...
    PUSH    {R0-R11}                ; Save other working registers.
                                    ; Insert handler code here.
; ...
    POP     {R0-R11}                ; Restore working registers (not R12).
                                    ; Now read-modify-write the CPSR
                                    ; to disable interrupts.
    MRS     R12, APSR               ; Read the status register.
    ORR     R12, R12, #0x80         ; Set the I bit
                                    ; (use 0x40 for the F bit).
    MSR     CPSR_c, R12             ; Write it back to disable interrupts.
                                    ; Now that interrupt disabled, can safely
                                    ; restore SPSR then return.
    POP     {r12,lr}                ; Restore R12 and get SPSR.
    MSR     SPSR_cxsf, lr           ; Restore status register from R14.
    LDM     sp!, {pc}^              ; Return from handler.
; ...