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/// This macro is unsound on multi core systems.
35///
36/// For debuggability, you can set an explicit name for a singleton.  This name only shows up the
37/// the debugger and is not referencable from other code.  See example below.
38///
39/// # Example
40///
41/// ``` no_run
42/// use cortex_m::singleton;
43///
44/// fn main() {
45///     // OK if `main` is executed only once
46///     let x: &'static mut bool = singleton!(: bool = false).unwrap();
47///
48///     let y = alias();
49///     // BAD this second call to `alias` will definitively `panic!`
50///     let y_alias = alias();
51/// }
52///
53/// fn alias() -> &'static mut bool {
54///     singleton!(: bool = false).unwrap()
55/// }
56///
57/// fn singleton_with_name() {
58///     // A name only for debugging purposes
59///     singleton!(FOO_BUFFER: [u8; 1024] = [0u8; 1024]);
60/// }
61/// ```
62#[macro_export]
63macro_rules! singleton {
64    ($name:ident: $ty:ty = $expr:expr) => {
65        $crate::interrupt::free(|_| {
66            // this is a tuple of a MaybeUninit and a bool because using an Option here is
67            // problematic:  Due to niche-optimization, an Option could end up producing a non-zero
68            // initializer value which would move the entire static from `.bss` into `.data`...
69            static mut $name: (::core::mem::MaybeUninit<$ty>, bool) =
70                (::core::mem::MaybeUninit::uninit(), false);
71
72            #[allow(unsafe_code)]
73            let used = unsafe { $name.1 };
74            if used {
75                None
76            } else {
77                let expr = $expr;
78
79                #[allow(unsafe_code)]
80                unsafe {
81                    $name.1 = true;
82                    $name.0 = ::core::mem::MaybeUninit::new(expr);
83                    Some(&mut *$name.0.as_mut_ptr())
84                }
85            }
86        })
87    };
88    (: $ty:ty = $expr:expr) => {
89        $crate::singleton!(VAR: $ty = $expr)
90    };
91}
92
93/// ``` compile_fail
94/// use cortex_m::singleton;
95///
96/// fn foo() {
97///     // check that the call to `uninitialized` requires unsafe
98///     singleton!(: u8 = std::mem::uninitialized());
99/// }
100/// ```
101#[allow(dead_code)]
102const CFAIL: () = ();
103
104/// ```
105/// #![deny(unsafe_code)]
106/// use cortex_m::singleton;
107///
108/// fn foo() {
109///     // check that calls to `singleton!` don't trip the `unsafe_code` lint
110///     singleton!(: u8 = 0);
111/// }
112/// ```
113#[allow(dead_code)]
114const CPASS: () = ();