rpi-hal 0.2.0

Hardware abstraction layer for Raspberry Pi boards using the BCM2836/BCM2837 SoC (Pi 2, Pi 3)
Documentation
// ARM exception vector table + IRQ trampoline. Installed via VBAR
// (see boot.s) rather than relying on the fixed low-vectors address
// 0x00000000, so this works the same regardless of where this code is
// linked/loaded.
//
// Standard 8-entry ARM vector table: each slot is a PC-relative load
// from a nearby literal (the assembler manages the exact offset/pool
// placement for `ldr pc, =label`), so unlike the rest of this
// project's hand-computed addressing, there's no manual offset to get
// wrong here.
.section ".text.vectors"
.align 5
.global __vectors
__vectors:
    ldr     pc, =_start                   // Reset (unused: VBAR is
                                           // programmed by boot.s
                                           // before this table is
                                           // reachable)
    ldr     pc, =__unhandled_exception    // Undefined instruction
    ldr     pc, =__unhandled_exception    // Supervisor call (SWI)
    ldr     pc, =__unhandled_exception    // Prefetch abort
    ldr     pc, =__unhandled_exception    // Data abort
    .word   0                             // Reserved, never taken
    ldr     pc, =__irq_trampoline         // IRQ
    ldr     pc, =__unhandled_exception    // FIQ (never unmasked)
.ltorg

.global __unhandled_exception
__unhandled_exception:
    wfe
    b       __unhandled_exception

.global __irq_trampoline
__irq_trampoline:
    // The IRQ return address is one instruction ahead of where
    // execution should resume (architectural quirk of this exception
    // type); back it up before saving so `movs pc, lr` below resumes
    // at the correct instruction.
    sub     lr, lr, #4
    push    {{r0-r12, lr}}
    bl      __irq_handler
    pop     {{r0-r12, lr}}
    // Copies SPSR_irq back into CPSR and branches to lr in one step —
    // the standard ARM idiom for returning from an exception handler.
    movs    pc, lr

// Weak default so examples that never enable IRQ (the vast majority)
// don't need to define this themselves — a strong `__irq_handler`
// defined elsewhere (e.g. in an example, as an ordinary `#[no_mangle]
// extern "C" fn`) overrides this at link time, standard ELF weak-symbol
// semantics. Never actually reached unless something unmasks IRQ and
// enables a source without registering a real handler.
.weak __irq_handler
__irq_handler:
    bx      lr