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: () = ();