1-- Hazard3's external interrupt controller, Xh3irq, the RP2350's RISC-V
2-- cores' (D687). Its enable, pending and force bits are core CSRs, meiea,
3-- meipa and meifa, each written sixteen IRQs at a time: the low five bits
4-- of the value select the window, IRQ / 16, and bits 16 to 31 are its
5-- sixteen IRQs. The compiler's dispatch reads meinext and calls slot
6-- 16 + IRQ (D680); enabling an IRQ is the program's, here. Every routine
7-- takes an IRQ below 512, Xh3irq's limit, and on a core without Xh3irq the
8-- CSRs trap as illegal instructions.
9
10fixed if compiler.arch == rv32 then
11 --- The meiea, meipa or meifa value naming IRQ in its window.
12 window_bit: (irq: u32) -> (bits: u32) =
13 bits = (u32(1) << (u32(16) + (irq & u32(15)))) | ((irq >> u32(4)) & u32(31))
14 end window_bit
15
16 --- Enable external interrupt IRQ in meiea. The core takes it once it is
17 --- pending and mie.MEIE, which `platform/riscv`'s `enable_lines(0x800)`
18 --- sets, and mstatus.MIE are set.
19 public enable_irq: (irq: u32) -> none =
20 assembler.block("csrs 0xbe0, {bits}", in bits: u32 at general = window_bit(irq))
21 end enable_irq
22
23 --- Disable external interrupt IRQ in meiea.
24 public disable_irq: (irq: u32) -> none =
25 assembler.block("csrc 0xbe0, {bits}", in bits: u32 at general = window_bit(irq))
26 end disable_irq
27
28 --- Force IRQ pending through meifa, as if its source had asserted it,
29 --- until `clear_forced_irq`.
30 public force_irq: (irq: u32) -> none =
31 assembler.block("csrs 0xbe2, {bits}", in bits: u32 at general = window_bit(irq))
32 end force_irq
33
34 --- Stop forcing IRQ pending.
35 public clear_forced_irq: (irq: u32) -> none =
36 assembler.block("csrc 0xbe2, {bits}", in bits: u32 at general = window_bit(irq))
37 end clear_forced_irq
38end if