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 104 105 106
/// Macro for sending a formatted string through an ITM channel #[macro_export] macro_rules! iprint { ($channel:expr, $s:expr) => { $crate::itm::write_str($channel, $s); }; ($channel:expr, $($arg:tt)*) => { $crate::itm::write_fmt($channel, format_args!($($arg)*)); }; } /// Macro for sending a formatted string through an ITM channel, with a newline. #[macro_export] macro_rules! iprintln { ($channel:expr) => { $crate::itm::write_str($channel, "\n"); }; ($channel:expr, $fmt:expr) => { $crate::itm::write_str($channel, concat!($fmt, "\n")); }; ($channel:expr, $fmt:expr, $($arg:tt)*) => { $crate::itm::write_fmt($channel, format_args!(concat!($fmt, "\n"), $($arg)*)); }; } /// Macro to create a mutable reference to a statically allocated value /// /// This macro returns a value with type `Option<&'static mut $ty>`. `Some($expr)` will be returned /// the first time the macro is executed; further calls will return `None`. To avoid `unwrap`ping a /// `None` variant the caller must ensure that the macro is called from a function that's executed /// at most once in the whole lifetime of the program. /// /// # Example /// /// ``` no_run /// #[macro_use(singleton)] /// extern crate cortex_m; /// /// fn main() { /// // OK if `main` is executed only once /// let x: &'static mut bool = singleton!(: bool = false).unwrap(); /// /// let y = alias(); /// // BAD this second call to `alias` will definitively `panic!` /// let y_alias = alias(); /// } /// /// fn alias() -> &'static mut bool { /// singleton!(: bool = false).unwrap() /// } /// ``` #[macro_export] macro_rules! singleton { (: $ty:ty = $expr:expr) => { $crate::interrupt::free(|_| { static mut VAR: Option<$ty> = None; #[allow(unsafe_code)] let used = unsafe { VAR.is_some() }; if used { None } else { let expr = $expr; #[allow(unsafe_code)] unsafe { VAR = Some(expr) } #[allow(unsafe_code)] unsafe { VAR.as_mut() } } }) }; } /// ``` compile_fail /// #[macro_use(singleton)] /// extern crate cortex_m; /// /// fn main() {} /// /// fn foo() { /// // check that the call to `uninitialized` requires unsafe /// singleton!(: u8 = std::mem::uninitialized()); /// } /// ``` #[allow(dead_code)] const CFAIL: () = (); /// ``` /// #![deny(unsafe_code)] /// #[macro_use(singleton)] /// extern crate cortex_m; /// /// fn main() {} /// /// fn foo() { /// // check that calls to `singleton!` don't trip the `unsafe_code` lint /// singleton!(: u8 = 0); /// } /// ``` #[allow(dead_code)] const CPASS: () = ();