Skip to main content

cortex_m/
macros.rs

1/// Macro for sending a formatted string through an ITM channel
2#[macro_export]
3macro_rules! iprint {
4    ($channel:expr, $s:expr) => {
5        $crate::itm::write_str($channel, $s);
6    };
7    ($channel:expr, $($arg:tt)*) => {
8        $crate::itm::write_fmt($channel, format_args!($($arg)*));
9    };
10}
11
12/// Macro for sending a formatted string through an ITM channel, with a newline.
13#[macro_export]
14macro_rules! iprintln {
15    ($channel:expr) => {
16        $crate::itm::write_str($channel, "\n");
17    };
18    ($channel:expr, $fmt:expr) => {
19        $crate::itm::write_str($channel, concat!($fmt, "\n"));
20    };
21    ($channel:expr, $fmt:expr, $($arg:tt)*) => {
22        $crate::itm::write_fmt($channel, format_args!(concat!($fmt, "\n"), $($arg)*));
23    };
24}
25
26/// Macro to create a mutable reference to a statically allocated value
27///
28/// This macro returns a value with type `Option<&'static mut $ty>`. `Some($expr)` will be returned
29/// the first time the macro is executed; further calls will return `None`. To avoid `unwrap`ping a
30/// `None` variant the caller must ensure that the macro is called from a function that's executed
31/// at most once in the whole lifetime of the program.
32///
33/// # Notes
34///
35/// This macro requires a `critical-section` implementation to be set. For most single core systems,
36/// you can enable the `critical-section-single-core` feature for this crate. For other systems, you
37/// have to provide one from elsewhere, typically your chip's HAL crate.
38///
39/// For debuggability, you can set an explicit name for a singleton. This name only shows up the
40/// debugger and is not referenceable from other code. See example below.
41///
42/// # Example
43///
44/// ``` no_run
45/// use cortex_m::singleton;
46///
47/// fn main() {
48///     // OK if `main` is executed only once
49///     let x: &'static mut bool = singleton!(: bool = false).unwrap();
50///
51///     let y = alias();
52///     // BAD this second call to `alias` will definitively `panic!`
53///     let y_alias = alias();
54/// }
55///
56/// fn alias() -> &'static mut bool {
57///     singleton!(: bool = false).unwrap()
58/// }
59///
60/// fn singleton_with_name() {
61///     // A name only for debugging purposes
62///     singleton!(FOO_BUFFER: [u8; 1024] = [0u8; 1024]);
63/// }
64/// ```
65#[macro_export]
66macro_rules! singleton {
67    ($(#[$meta:meta])* $name:ident: $ty:ty = $expr:expr) => {
68        $crate::_export::critical_section::with(|_| {
69            // this is a tuple of a MaybeUninit and a bool because using an Option here is
70            // problematic:  Due to niche-optimization, an Option could end up producing a non-zero
71            // initializer value which would move the entire static from `.bss` into `.data`...
72            $(#[$meta])*
73            static mut $name: (::core::mem::MaybeUninit<$ty>, bool) =
74                (::core::mem::MaybeUninit::uninit(), false);
75
76            #[allow(unsafe_code)]
77            let used = unsafe { $name.1 };
78            if used {
79                None
80            } else {
81                let expr = $expr;
82
83                #[allow(unsafe_code)]
84                unsafe {
85                    $name.1 = true;
86                    Some($name.0.write(expr))
87                }
88            }
89        })
90    };
91    ($(#[$meta:meta])* : $ty:ty = $expr:expr) => {
92        $crate::singleton!($(#[$meta])* VAR: $ty = $expr)
93    };
94}
95
96/// ``` compile_fail
97/// use cortex_m::singleton;
98///
99/// fn foo() {
100///     // check that the call to `uninitialized` requires unsafe
101///     singleton!(: u8 = std::mem::uninitialized());
102/// }
103/// ```
104#[allow(dead_code)]
105const CFAIL: () = ();
106
107/// ```
108/// #![deny(unsafe_code)]
109/// use cortex_m::singleton;
110///
111/// fn foo() {
112///     // check that calls to `singleton!` don't trip the `unsafe_code` lint
113///     singleton!(: u8 = 0);
114/// }
115/// ```
116#[allow(dead_code)]
117const CPASS: () = ();
118
119/// ```
120/// use cortex_m::singleton;
121///
122/// fn foo() {
123///     // check that attributes are forwarded
124///     singleton!(#[unsafe(link_section = ".bss")] FOO: u8 = 0);
125///     singleton!(#[unsafe(link_section = ".bss")]: u8 = 1);
126/// }
127/// ```
128#[allow(dead_code)]
129const CPASS_ATTR: () = ();