# Interrupt management

On ARM, the interrupt vectors live either at $00000000 or $ffff0000 depending
on the value of SCTLR.V. Those vectors are executable code organized as follow:

+00 Reset
+04 Undefined
+08 Supervisor call
+0c Prefetch abort
+10 Data abort
+14 Not used
+18 IRQ
+1c FIQ

In Dusk OS, that vector is managed in unit [drv/rpi/intr.fs] and has that vector
live at $00000000. We set those vectors as indirect jumpsto address defined $20
bytes later, which is where "intrtbl" lives. It's the "intr$ ( -- )" word that
sets up such vectors and table. By default, all "intrtbl" entries point to
"noopisr".

Under the BCM2835, we reserve memory $40-$5f for the IRQ stack and $60-$7f for
the FIQ stack.

This unit also defines "isrsave," [doc/intr] sets rSP to $60 and saves r0 and
r1 to it. "isrrestore," pops r0 and r1 back.

On the BCM2835, interrupts are managed through registers living at MMIO_BASE +
$b200, which go as follow:

+00 IRQ pending basic
+04 IRQ pending 1
+08 IRQ pending 2
+0c FIQ control
+10 IRQ enable 1
+14 IRQ enable 2
+18 IRQ enable basic
+1c IRQ disable 1
+20 IRQ disable 2
+24 IRQ disable basic

## Intrs struct

The unit at [drv/rpi/intr.fs] defines the Intrs struct which wraps the register
described above in the following fields:

pendingb, pending1, pending2, fiqctrl, enable1, enable2, enableb, disable1,
disable2, disableb

The unit also creates a structbind of that struct to MMIO_BASE+$b200 named
"intrs".

## API

intr$ ( -- )
  Setup "intrtbl" rows to point to "noopisr", then set up a the vector table at
  $00000000 to point to "intrtbl" rows.

intrtbl ( -- a )
  Yield the address of the indirect interrupt vector table.

.intr ( -- )
  Print interrupt configuration in a human readable fashion.

## Interrupt Service Routines

isrsave, ( -- )
  Compile code that sets rSP to $60 and pushes r0 and r1 to it.

isrrestore, ( -- )
  Compile code that pops r1 and r0.

The ISRs below are convenience ISRs, directly pluggable into "intrtbl". They are
self-sufficient in term of register save/restore.

noopisr
  Do nothing and return from interrupt.

abortisr
  Rather than returning from interrupt normally, return to "abort". This allows
  an interrupt to "break" back into the prompt.

cntisr
  Increase the value "isrcounter" by 1, then return from interrupt.
