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. `Mutex` and `cell::RefCell` must be imported.
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: Mutex<RefCell<Option<$type>>> = Mutex::new(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. `Mutex` and `cell::Cell` must be imported.
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: Mutex<Cell<$type>> = Mutex::new(Cell::new($val));
61        )+
62    };
63}
64
65/// Initialize one or more globals inside a critical section. `critical_section::with`
66/// must be imported.
67///
68/// Usage:
69/// ```rust
70/// init_globals!(
71///     (FLASH, flash),
72///     (SPI_IMU, spi1),
73///     (I2C_MAG, i2c1),
74///     // …
75/// );
76/// ```
77#[macro_export]
78macro_rules! init_globals {
79    ($(($NAME:ident, $val:expr)),* $(,)?) => {
80        with(|cs| {
81            $(
82                $NAME.borrow(cs).replace(Some($val));
83            )*
84        });
85    };
86}
87
88/// Automates Cortex-M NVIC setup. The second value is NVIC priority; lower
89/// is higher priority. Example use:
90/// setup_nvic!([
91///     (TIM2, 6),
92///     (TIM3, 7),
93///     (EXTI0, 4),
94/// ], cp);
95#[macro_export]
96macro_rules! setup_nvic {
97    (
98        [ $( ($int:ident, $prio:expr) ),* $(,)? ],
99        $cp:ident
100    ) => {
101        unsafe {
102            $(
103                NVIC::unmask(pac::Interrupt::$int);
104            )*
105            $(
106                $cp.NVIC.set_priority(pac::Interrupt::$int, $prio);
107            )*
108        }
109    };
110}
111
112/// Syntax helper for parsing multi-byte fields into primitives.
113///
114/// Example: `parse_le!(bytes, i32, 5..9);`
115#[macro_export]
116macro_rules! parse_le {
117    ($bytes:expr, $t:ty, $range:expr) => {{ <$t>::from_le_bytes($bytes[$range].try_into().unwrap()) }};
118}
119
120/// Syntax helper for parsing multi-byte fields into primitives.
121///
122/// Example: `parse_be!(bytes, i32, 5..9);`
123#[macro_export]
124macro_rules! parse_be {
125    ($bytes:expr, $t:ty, $range:expr) => {{ <$t>::from_be_bytes($bytes[$range].try_into().unwrap()) }};
126}
127
128/// Syntax helper for converting primitives to multi-byte fields.
129///
130/// Example: `copy_le!(bytes, self.position, 5..9);`
131#[macro_export]
132macro_rules! copy_le {
133    ($dest:expr, $src:expr, $range:expr) => {{ $dest[$range].copy_from_slice(&$src.to_le_bytes()) }};
134}
135
136/// Syntax helper for converting primitives to multi-byte fields.
137///
138/// Example: `copy_be!(bytes, self.position, 5..9);`
139#[macro_export]
140macro_rules! copy_be {
141    ($dest:expr, $src:expr, $range:expr) => {{ $dest[$range].copy_from_slice(&$src.to_be_bytes()) }};
142}