1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
extern "Rust"
/// RAII guard that acquires the critical section on creation and releases it on drop.
///
/// Prefer [`critical_section`] for scoped use. Use this type directly only when
/// you need to hold the critical section across a scope boundary.
/// Executes `f` inside a critical section, returning its result.
///
/// The critical section is entered before calling `f` and exited when `f` returns,
/// even if `f` panics (via [`IrqGuard`]'s `Drop` impl).
/// Implement this macro once in your project to provide the critical section.
///
/// # Example (ARM Cortex-M)
///
/// ```ignore
/// mmio_rs::impl_critical_section!(
/// acquire: {
/// let primask: u32;
/// core::arch::asm!("MRS {}, PRIMASK", out(reg) primask);
/// core::arch::asm!("CPSID i", options(nomem, nostack));
/// primask
/// },
/// release: |state| {
/// core::arch::asm!("MSR PRIMASK, {}", in(reg) state, options(nomem, nostack));
/// }
/// );
/// ```
///
/// # Example (RISC-V)
///
/// ```ignore
/// mmio_rs::impl_critical_section!(
/// acquire: {
/// let mstatus: u32;
/// core::arch::asm!("csrrci {}, mstatus, 0x8", out(reg) mstatus);
/// mstatus & 0x8
/// },
/// release: |state| {
/// if state != 0 {
/// core::arch::asm!("csrsi mstatus, 0x8", options(nomem, nostack));
/// }
/// }
/// );
/// ```
///
/// # Example (host/test — no-op)
///
/// ```ignore
/// mmio_rs::impl_critical_section!(
/// acquire: { 0 },
/// release: |_state| {}
/// );
/// ```