stm32_hal2/
macros.rs

1//! This module contains utility macros that are not STM32-specific, or specific
2//! to this library.
3
4/// Syntax helper for getting global variables of the form `Mutex<RefCell<Option>>>` from an interrupt-free
5/// context - eg in interrupt handlers.
6///
7/// Example: `access_global!(DELAY, delay, cs)`
8#[macro_export]
9macro_rules! access_global {
10    ($NAME_GLOBAL:ident, $name_local:ident, $cs:expr) => {
11        let mut part1 = $NAME_GLOBAL.borrow($cs).borrow_mut();
12        let $name_local = part1.as_mut().unwrap();
13    };
14}
15
16/// Similar to `access_global`, but combining multiple calls.
17///
18/// Example: `access_globals!([
19///     (USB_DEV, usb_dev),
20///     (USB_SERIAL, usb_serial),
21/// ], cs);`
22#[macro_export]
23macro_rules! access_globals {
24    ([$(($NAME_GLOBAL:ident, $name_local:ident)),* $(,)?], $cs:expr) => {
25        $(
26            let mut part = $NAME_GLOBAL.borrow($cs).borrow_mut();
27            let $name_local = part.as_mut().unwrap();
28        )*
29    };
30}
31
32/// Syntax helper for setting global variables of the form `Mutex<RefCell<Option>>>`.
33/// eg in interrupt handlers. Ideal for non-copy-type variables that can't be initialized
34/// immediatiately.
35///
36/// Example: `make_globals!(
37///     (USB_SERIAL, SerialPort<UsbBusType>),
38///     (DELAY, Delay),
39/// )`
40#[macro_export]
41macro_rules! make_globals {
42    ($(($NAME:ident, $type:ty)),+ $(,)?) => {
43        $(
44            static $NAME: ::critical_section::Mutex<core::cell::RefCell<Option<$type>>> = ::critical_section::Mutex::new(core::cell::RefCell::new(None));
45        )+
46    };
47}
48
49/// Syntax helper for setting global variables of the form `Mutex<Cell<>>>`.
50/// eg in interrupt handlers. Ideal for copy-type variables.
51///
52/// Example: `make_simple_globals!(
53///     (VALUE, f32, 2.),
54///     (SETTING, Setting, Setting::A),
55/// )`
56#[macro_export]
57macro_rules! make_simple_globals {
58    ($(($NAME:ident, $type:ty, $val:expr)),+ $(,)?) => {
59        $(
60            static $NAME: ::critical_section::Mutex<core::cell::Cell<$type>> = ::critical_section::Mutex::new(core::cell::Cell::new($val));
61        )+
62    };
63}
64
65/// Initialize one or more globals inside a critical section.
66///
67/// Usage:
68/// ```rust
69/// init_globals!(
70///     (FLASH, flash),
71///     (SPI_IMU, spi1),
72///     (I2C_MAG, i2c1),
73///     // …
74/// );
75/// ```
76#[macro_export]
77macro_rules! init_globals {
78    ($(($NAME:ident, $val:expr)),* $(,)?) => {
79        ::critical_section::with(|cs| {
80            $(
81                $NAME.borrow(cs).replace(Some($val));
82            )*
83        });
84    };
85}
86
87/// Automates Cortex-M NVIC setup. The second value is NVIC priority; lower
88/// is higher priority. Example use:
89/// setup_nvic!([
90///     (TIM2, 6),
91///     (TIM3, 7),
92///     (EXTI0, 4),
93/// ], cp);
94#[macro_export]
95macro_rules! setup_nvic {
96    (
97        [ $( ($int:ident, $prio:expr) ),* $(,)? ],
98        $cp:ident
99    ) => {
100        unsafe {
101            $(
102                cortex_m::peripheral::NVIC::unmask(pac::Interrupt::$int);
103            )*
104            $(
105                $cp.NVIC.set_priority(pac::Interrupt::$int, $prio);
106            )*
107        }
108    };
109}
110
111/// Syntax helper for parsing multi-byte fields into primitives.
112///
113/// Example: `parse_le!(bytes, i32, 5..9);`
114#[macro_export]
115macro_rules! parse_le {
116    ($bytes:expr, $t:ty, $range:expr) => {{ <$t>::from_le_bytes($bytes[$range].try_into().unwrap()) }};
117}
118
119/// Syntax helper for parsing multi-byte fields into primitives.
120///
121/// Example: `parse_be!(bytes, i32, 5..9);`
122#[macro_export]
123macro_rules! parse_be {
124    ($bytes:expr, $t:ty, $range:expr) => {{ <$t>::from_be_bytes($bytes[$range].try_into().unwrap()) }};
125}
126
127/// Syntax helper for converting primitives to multi-byte fields.
128///
129/// Example: `copy_le!(bytes, self.position, 5..9);`
130#[macro_export]
131macro_rules! copy_le {
132    ($dest:expr, $src:expr, $range:expr) => {{ $dest[$range].copy_from_slice(&$src.to_le_bytes()) }};
133}
134
135/// Syntax helper for converting primitives to multi-byte fields.
136///
137/// Example: `copy_be!(bytes, self.position, 5..9);`
138#[macro_export]
139macro_rules! copy_be {
140    ($dest:expr, $src:expr, $range:expr) => {{ $dest[$range].copy_from_slice(&$src.to_be_bytes()) }};
141}