assign_resources/
lib.rs

1#![no_std]
2
3/// Extract the specified fields from the `Peripherals` struct into several named
4/// structs which can be passed to other tasks to provide them with all their
5/// resources, including pins, peripherals, DMA channels, etc.
6///
7/// The `peripherals` module must be in scope when `resource_assigs!{}` is called,
8/// and it defines a new macro `split_resources!()` which uses the `Peripherals` struct
9/// and returns a new struct with a field for each of the structs named in `resource_assigs!{}`.
10///
11/// Defines new structs containing the specified structs from the `peripherals` module,
12/// a top-level struct called `AssignedResources` that contains an instance of each of these new structs,
13/// and a macro that creates the top-level struct and populates it with fields from
14/// a `Peripherals` instance.
15///
16/// # Example
17///
18/// ```
19/// use assign_resources::assign_resources;
20/// use embassy_stm32::{Peri, peripherals};
21///
22/// assign_resources! {
23///     usb: UsbResources {
24///         dp: PA12,
25///         dm: PA11,
26///         usb: USB,
27///     }
28///     leds: LedResources {
29///         r: PA2,
30///         g: PA3,
31///         b: PA4,
32///         tim2: TIM2,
33///     }
34/// }
35///
36/// #[embassy_executor::task]
37/// async fn usb_task(r: UsbResources) {
38///     // use r.dp, r.dm, r.usb
39/// }
40///
41/// #[embassy_executor::task]
42/// async fn led_task(r: LedResources) {
43///     // use r.r, r.g, r.b, r.tim2
44/// }
45///
46/// #[embassy_executor::main]
47/// async fn main(spawner: embassy_executor::Spawner) {
48///     let p = embassy_stm32::init(Default::default());
49///     let r = split_resources!(p);
50///     spawner.spawn(usb_task(r.usb)).unwrap();
51///     spawner.spawn(led_task(r.leds)).unwrap();
52///
53///     // can still use p.PA0, p.PA1, etc
54/// }
55/// ```
56#[macro_export]
57macro_rules! assign_resources {
58    {
59        $(
60            $(#[$outer:meta])*
61            $group_name:ident : $group_struct:ident {
62                $(
63                    $(#[$inner:meta])*
64                    $resource_name:ident : $resource_field:ident $(=$resource_alias:ident)?),*
65                $(,)?
66            }
67            $(,)?
68        )+
69    } => {
70        #[allow(dead_code,non_snake_case,missing_docs)]
71        pub struct AssignedResources {
72            $(pub $group_name : $group_struct),*
73        }
74        $(
75            #[allow(dead_code,non_snake_case)]
76            $(#[$outer])*
77            pub struct $group_struct {
78                $(
79                    $(#[$inner])*
80                    pub $resource_name: Peri<'static, peripherals::$resource_field>
81                ),*
82            }
83        )+
84
85
86        $($($(
87            #[allow(missing_docs)]
88            pub type $resource_alias = Peri<'static, peripherals::$resource_field>;
89        )?)*)*
90
91        #[macro_export]
92        /// `split_resources!` macro
93        macro_rules! split_resources (
94            ($p:ident) => {
95                AssignedResources {
96                    $($group_name: $group_struct {
97                        $($resource_name: $p.$resource_field),*
98                    }),*
99                }
100            }
101        );
102    }
103}