mik32_runtime/
interrupt.rs1use core::arch::asm;
8
9const MSTATUS_MIE: usize = 1 << 3;
10const MIE_MEIE: usize = 1 << 11;
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17#[repr(transparent)]
18pub struct RestoreState {
19 bits: usize,
20}
21
22impl RestoreState {
23 #[inline]
25 pub const fn machine_interrupts_enabled(self) -> bool {
26 self.bits & MSTATUS_MIE != 0
27 }
28
29 #[inline]
31 pub const fn machine_external_interrupt_enabled(self) -> bool {
32 self.bits & MIE_MEIE != 0
33 }
34
35 #[inline]
36 const fn from_raw_parts(mstatus: usize, mie: usize) -> Self {
37 Self {
38 bits: (mstatus & MSTATUS_MIE) | (mie & MIE_MEIE),
39 }
40 }
41
42 #[inline]
43 #[cfg(feature = "critical-section")]
44 const fn bits(self) -> usize {
45 self.bits
46 }
47
48 #[inline]
49 #[cfg(feature = "critical-section")]
50 const unsafe fn from_bits(bits: usize) -> Self {
51 Self {
52 bits: bits & (MSTATUS_MIE | MIE_MEIE),
53 }
54 }
55}
56
57#[inline]
61pub fn disable() -> RestoreState {
62 let mstatus: usize;
63 let mie: usize;
64
65 unsafe {
68 asm!(
69 "csrrc {mstatus}, mstatus, {mstatus_mie}",
70 "csrrc {mie}, mie, {mie_meie}",
71 mstatus = out(reg) mstatus,
72 mie = out(reg) mie,
73 mstatus_mie = in(reg) MSTATUS_MIE,
74 mie_meie = in(reg) MIE_MEIE,
75 options(nostack),
76 );
77 }
78
79 RestoreState::from_raw_parts(mstatus, mie)
80}
81
82#[inline]
90pub unsafe fn enable() {
91 unsafe {
94 asm!(
95 "csrrs zero, mie, {mie_meie}",
96 "csrrs zero, mstatus, {mstatus_mie}",
97 mstatus_mie = in(reg) MSTATUS_MIE,
98 mie_meie = in(reg) MIE_MEIE,
99 options(nostack),
100 );
101 }
102}
103
104#[inline]
112pub unsafe fn restore(state: RestoreState) {
113 if state.machine_external_interrupt_enabled() {
114 unsafe {
116 asm!(
117 "csrrs zero, mie, {mask}",
118 mask = in(reg) MIE_MEIE,
119 options(nostack),
120 );
121 }
122 } else {
123 unsafe {
125 asm!(
126 "csrrc zero, mie, {mask}",
127 mask = in(reg) MIE_MEIE,
128 options(nostack),
129 );
130 }
131 }
132
133 if state.machine_interrupts_enabled() {
134 unsafe {
136 asm!(
137 "csrrs zero, mstatus, {mask}",
138 mask = in(reg) MSTATUS_MIE,
139 options(nostack),
140 );
141 }
142 } else {
143 unsafe {
145 asm!(
146 "csrrc zero, mstatus, {mask}",
147 mask = in(reg) MSTATUS_MIE,
148 options(nostack),
149 );
150 }
151 }
152}
153
154#[inline]
157pub fn free<R>(f: impl FnOnce() -> R) -> R {
158 let state = disable();
159 let result = f();
160
161 unsafe {
163 restore(state);
164 }
165
166 result
167}
168
169#[cfg(feature = "critical-section")]
170mod critical_section_impl {
171 use super::{RestoreState, disable, restore};
172 use critical_section::{Impl, RawRestoreState, set_impl};
173
174 struct SingleHartCriticalSection;
175
176 set_impl!(SingleHartCriticalSection);
177
178 unsafe impl Impl for SingleHartCriticalSection {
179 unsafe fn acquire() -> RawRestoreState {
180 disable().bits()
181 }
182
183 unsafe fn release(state: RawRestoreState) {
184 unsafe {
186 restore(RestoreState::from_bits(state));
187 }
188 }
189 }
190}