Landin library reference discuss source

platform/riscv/hazard3/hazard3.ldn

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