1#[doc(hidden)]
14#[macro_export]
15macro_rules! peripherals {
16 (
17 peripherals: [
18 $(
19 $name:ident <= $from_pac:tt $(($($interrupt:ident),*))?
20 ),* $(,)?
21 ],
22 unstable_peripherals: [
23 $(
24 $unstable_name:ident <= $unstable_from_pac:tt $(($($unstable_interrupt:ident),*))?
25 ),* $(,)?
26 ],
27 pins: [
28 $( ( $pin:literal, $($pin_tokens:tt)* ) )*
29 ]
30 ) => {
31 paste::paste! {
32 $(
33 $crate::create_peripheral!($name <= $from_pac);
34 )*
35 $(
36 $crate::create_peripheral!(#[instability::unstable] $unstable_name <= $unstable_from_pac);
37 )*
38 $(
39 $crate::create_peripheral!([< GPIO $pin >] <= virtual);
40 )*
41
42 #[allow(non_snake_case)]
44 pub struct Peripherals {
45 $(
46 #[doc = concat!("The ", stringify!($name), " peripheral.")]
47 pub $name: $name<'static>,
48 )*
49 $(
50 #[doc = concat!("The ", stringify!($unstable_name), " peripheral.")]
51 #[doc = "**This API is marked as unstable** and is only available when the `unstable`
52 crate feature is enabled. This comes with no stability guarantees, and could be changed
53 or removed at any time."]
54 #[cfg(feature = "unstable")]
55 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
56 pub $unstable_name: $unstable_name<'static>,
57
58 #[doc = concat!("The ", stringify!($unstable_name), " peripheral.")]
59 #[doc = "**This API is marked as unstable** and is only available when the `unstable`
60 crate feature is enabled. This comes with no stability guarantees, and could be changed
61 or removed at any time."]
62 #[cfg(not(feature = "unstable"))]
63 #[allow(unused)]
64 pub(crate) $unstable_name: $unstable_name<'static>,
65 )*
66
67 $(
68 #[doc = concat!("GPIO", stringify!($pin))]
69 pub [<GPIO $pin>]: [<GPIO $pin>]<'static>,
70 )*
71 }
72
73 impl Peripherals {
74 #[inline]
76 pub(crate) fn take() -> Self {
77 #[unsafe(no_mangle)]
78 static mut _ESP_HAL_DEVICE_PERIPHERALS: bool = false;
79
80 critical_section::with(|_| unsafe {
81 if _ESP_HAL_DEVICE_PERIPHERALS {
82 panic!("init called more than once!")
83 }
84 _ESP_HAL_DEVICE_PERIPHERALS = true;
85 Self::steal()
86 })
87 }
88
89 #[inline]
95 pub unsafe fn steal() -> Self {
96 unsafe {
97 Self {
98 $(
99 $name: $name::steal(),
100 )*
101 $(
102 $unstable_name: $unstable_name::steal(),
103 )*
104
105 $(
106 [<GPIO $pin>]: [<GPIO $pin>]::steal(),
107 )*
108 }
109 }
110 }
111 }
112
113 $crate::gpio! {
114 $( ($pin, $($pin_tokens)* ) )*
115 }
116 }
117
118 $(
119 $(
120 impl $name<'_> {
121 $(
122 paste::paste!{
123 #[instability::unstable]
125 pub fn [<bind_ $interrupt:lower _interrupt >](&mut self, handler: unsafe extern "C" fn() -> ()) {
126 unsafe { $crate::interrupt::bind_interrupt($crate::peripherals::Interrupt::$interrupt, handler); }
127 }
128 }
129 )*
130 }
131 )*
132 )*
133
134 $(
135 $(
136 impl $unstable_name<'_> {
137 $(
138 paste::paste!{
139 #[instability::unstable]
141 pub fn [<bind_ $unstable_interrupt:lower _interrupt >](&mut self, handler: unsafe extern "C" fn() -> ()) {
142 unsafe { $crate::interrupt::bind_interrupt($crate::peripherals::Interrupt::$unstable_interrupt, handler); }
143 }
144 }
145 )*
146 }
147 )*
148 )*
149 };
150}
151
152#[doc(hidden)]
153#[macro_export]
154macro_rules! create_peripheral {
156 ($(#[$attr:meta])? $name:ident <= virtual) => {
157 $(#[$attr])?
158 #[derive(Debug)]
159 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
160 #[non_exhaustive]
161 #[allow(non_camel_case_types, clippy::upper_case_acronyms)]
162 #[doc = concat!(stringify!($name), " peripheral singleton")]
163 pub struct $name<'a> {
164 _marker: core::marker::PhantomData<&'a mut ()>,
165 }
166
167 impl $name<'_> {
168 #[inline]
174 pub unsafe fn steal() -> Self {
175 Self {
176 _marker: core::marker::PhantomData,
177 }
178 }
179
180 #[inline]
186 #[allow(dead_code)]
187 pub unsafe fn clone_unchecked(&self) -> Self {
188 unsafe { Self::steal() }
189 }
190
191 #[inline]
196 #[allow(dead_code)]
197 pub fn reborrow(&mut self) -> $name<'_> {
198 unsafe { self.clone_unchecked() }
199 }
200 }
201
202 impl $crate::private::Sealed for $name<'_> {}
203 };
204
205 ($(#[$attr:meta])? $name:ident <= $base:ident) => {
206 $crate::create_peripheral!($(#[$attr])? $name <= virtual);
207
208 impl $name<'_> {
209 #[doc = r"Pointer to the register block"]
210 #[instability::unstable]
211 pub const PTR: *const <pac::$base as core::ops::Deref>::Target = pac::$base::PTR;
212
213 #[doc = r"Return the pointer to the register block"]
214 #[inline(always)]
215 #[instability::unstable]
216 pub const fn ptr() -> *const <pac::$base as core::ops::Deref>::Target {
217 pac::$base::PTR
218 }
219
220 #[doc = r"Return a reference to the register block"]
221 #[inline(always)]
222 #[instability::unstable]
223 pub const fn regs<'a>() -> &'a <pac::$base as core::ops::Deref>::Target {
224 unsafe { &*Self::PTR }
225 }
226
227 #[doc = r"Return a reference to the register block"]
228 #[inline(always)]
229 #[instability::unstable]
230 pub fn register_block(&self) -> &<pac::$base as core::ops::Deref>::Target {
231 unsafe { &*Self::PTR }
232 }
233 }
234 };
235}