litex_vexriscv/
interrupt_controller.rs
1use core::cell::Cell;
8
9pub struct VexRiscvInterruptController {
15 saved_interrupts: Cell<usize>,
16}
17
18impl VexRiscvInterruptController {
19 pub const fn new() -> Self {
21 VexRiscvInterruptController {
22 saved_interrupts: Cell::new(0),
23 }
24 }
25
26 pub unsafe fn save_pending(&self) -> bool {
32 let all_pending = vexriscv_irq_raw::irq_pending();
33 self.saved_interrupts.set(all_pending);
34
35 all_pending != 0
37 }
38
39 pub fn next_saved(&self) -> Option<usize> {
47 let saved_interrupts: usize = self.saved_interrupts.get();
48 let interrupt_bits = usize::BITS as usize;
49
50 let trailing_zeros = usize::trailing_zeros(saved_interrupts) as usize;
54 if trailing_zeros == interrupt_bits {
55 None
56 } else {
57 Some(trailing_zeros)
58 }
59 }
60
61 pub fn complete_saved(&self, idx: usize) {
67 self.saved_interrupts
68 .set(self.saved_interrupts.get() & !(1 << idx));
69 }
70
71 pub unsafe fn mask_interrupt(idx: usize) {
74 vexriscv_irq_raw::irq_setmask(vexriscv_irq_raw::irq_getmask() & !(1 << idx));
75 }
76
77 pub unsafe fn unmask_interrupt(idx: usize) {
80 vexriscv_irq_raw::irq_setmask(vexriscv_irq_raw::irq_getmask() | (1 << idx));
81 }
82
83 pub unsafe fn mask_all_interrupts() {
85 vexriscv_irq_raw::irq_setmask(0);
86 }
87
88 pub unsafe fn unmask_all_interrupts() {
90 vexriscv_irq_raw::irq_setmask(usize::MAX);
91 }
92}
93
94mod vexriscv_irq_raw {
95 #![allow(dead_code)]
99
100 const CSR_IRQ_MASK: usize = 0xBC0;
102 const CSR_IRQ_PENDING: usize = 0xFC0;
104
105 #[cfg(not(any(doc, all(target_arch = "riscv32", target_os = "none"))))]
106 pub unsafe fn irq_getmask() -> usize {
107 0
108 }
109
110 #[cfg(any(doc, all(target_arch = "riscv32", target_os = "none")))]
111 pub unsafe fn irq_getmask() -> usize {
112 let mask: usize;
113 use core::arch::asm;
114 asm!("csrr {mask}, {csr}", mask = out(reg) mask, csr = const CSR_IRQ_MASK);
115 mask
116 }
117
118 #[cfg(not(any(doc, all(target_arch = "riscv32", target_os = "none"))))]
119 pub unsafe fn irq_setmask(_mask: usize) {}
120
121 #[cfg(any(doc, all(target_arch = "riscv32", target_os = "none")))]
122 pub unsafe fn irq_setmask(mask: usize) {
123 use core::arch::asm;
124 asm!("csrw {csr}, {mask}", csr = const CSR_IRQ_MASK, mask = in(reg) mask);
125 }
126
127 #[cfg(not(any(doc, all(target_arch = "riscv32", target_os = "none"))))]
128 pub unsafe fn irq_pending() -> usize {
129 0
130 }
131
132 #[cfg(any(doc, all(target_arch = "riscv32", target_os = "none")))]
133 pub unsafe fn irq_pending() -> usize {
134 let pending: usize;
135 use core::arch::asm;
136 asm!("csrr {pending}, {csr}", pending = out(reg) pending, csr = const CSR_IRQ_PENDING);
137 pending
138 }
139}