1#[doc(hidden)]
8#[macro_export]
10macro_rules! before_snippet {
11 () => {
12 r#"
13# #![no_std]
14# use esp_hal::{interrupt::{self, InterruptConfigurable}, time::{Duration, Instant, Rate}};
15# macro_rules! println {
16# ($($tt:tt)*) => { };
17# }
18# macro_rules! print {
19# ($($tt:tt)*) => { };
20# }
21# #[panic_handler]
22# fn panic(_ : &core::panic::PanicInfo) -> ! {
23# loop {}
24# }
25# fn main() {
26# let _ = example();
27# }
28# struct ExampleError {}
29# impl <T> From<T> for ExampleError where T: core::fmt::Debug {
30# fn from(_value: T) -> Self {
31# Self{}
32# }
33# }
34# async fn example() -> Result<(), ExampleError> {
35# let mut peripherals = esp_hal::init(esp_hal::Config::default());
36"#
37 };
38}
39
40#[doc(hidden)]
41#[macro_export]
42macro_rules! after_snippet {
43 () => {
44 r#"
45# Ok(())
46# }
47"#
48 };
49}
50
51#[doc(hidden)]
52#[macro_export]
53macro_rules! trm_markdown_link {
54 () => {
55 concat!("[Technical Reference Manual](", property!("trm"), ")")
56 };
57 ($anchor:literal) => {
58 concat!(
59 "[Technical Reference Manual](",
60 property!("trm"),
61 "#",
62 $anchor,
63 ")"
64 )
65 };
66}
67
68#[doc(hidden)]
69#[macro_export]
79macro_rules! any_peripheral {
80 ($(#[$meta:meta])* $vis:vis peripheral $name:ident<'d> {
81 $(
82 $(#[cfg($variant_meta:meta)])*
83 $variant:ident($inner:ty)
84 ),* $(,)?
85 }) => {
86 #[doc = concat!("Utilities related to [`", stringify!($name), "`]")]
87 #[doc(hidden)]
88 #[instability::unstable]
89 pub mod any {
90 #[allow(unused_imports)]
91 use super::*;
92
93 macro_rules! delegate {
94 ($any:ident, $inner_ident:ident => $code:tt) => {
95 match &$any.0 {
96 $(
97 $(#[cfg($variant_meta)])*
98 any::Inner::$variant($inner_ident) => $code,
99 )*
100 }
101 }
102 }
103
104 pub(crate) use delegate;
105
106 $(#[$meta])*
107 #[derive(Debug)]
108 pub(crate) enum Inner<'d> {
109 $(
110 $(#[cfg($variant_meta)])*
111 $variant($inner),
112 )*
113 }
114
115 #[cfg(feature = "defmt")]
116 impl defmt::Format for Inner<'_> {
117 fn format(&self, fmt: defmt::Formatter<'_>) {
118 match self {
119 $(
120 $(#[cfg($variant_meta)])*
121 Self::$variant(inner) => inner.format(fmt),
122 )*
123 }
124 }
125 }
126
127 #[allow(unused)]
133 pub trait Degrade: Sized + $crate::private::Sealed {
134 fn degrade<'a>(self) -> super::$name<'a>
135 where
136 Self: 'a;
137 }
138 }
139
140 $(#[$meta])*
141 #[doc = concat!("let any_peripheral = ", stringify!($name), "::from(peripheral);")]
148 #[derive(Debug)]
150 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
151 $vis struct $name<'d>(any::Inner<'d>);
152
153 impl $name<'_> {
154 #[inline]
160 #[allow(unused)]
161 pub unsafe fn clone_unchecked(&self) -> Self { unsafe {
162 any::delegate!(self, inner => { Self::from(inner.clone_unchecked()) })
163 }}
164
165 #[inline]
174 #[allow(unused)]
175 pub fn reborrow(&mut self) -> $name<'_> {
176 unsafe { self.clone_unchecked() }
177 }
178
179 #[procmacros::doc_replace]
180 #[cfg_attr(
182 uart_driver_supported,
186 doc = r#"
187## Example
188
189```rust,no_run
190# {before_snippet}
191#
192# use esp_hal::{
193# uart::AnyUart as AnyPeripheral,
194# peripherals::{UART0 as PERI0, UART1 as PERI1},
195# };
196#
197# let peri0 = peripherals.UART0;
198# let peri1 = peripherals.UART1;
199// let peri0 = peripherals.PERI0;
200// let peri1 = peripherals.PERI1;
201let any_peri0 = AnyPeripheral::from(peri0);
202let any_peri1 = AnyPeripheral::from(peri1);
203
204let uart0 = any_peri0
205 .downcast::<PERI0>()
206 .expect("This downcast succeeds because AnyPeripheral was created from Peri0");
207let uart0 = any_peri1
208 .downcast::<PERI0>()
209 .expect_err("This AnyPeripheral was created from Peri1, it cannot be downcast to Peri0");
210#
211# {after_snippet}
212```
213"#
214 )]
215 #[inline]
216 #[allow(unused)]
217 pub fn downcast<P>(self) -> Result<P, Self>
218 where
219 Self: TryInto<P, Error = Self>
220 {
221 self.try_into()
222 }
223 }
224
225 impl $crate::private::Sealed for $name<'_> {}
226
227 impl<'d> any::Degrade for $name<'d> {
229 #[inline]
230 fn degrade<'a>(self) -> $name<'a>
231 where
232 Self: 'a,
233 {
234 self
235 }
236 }
237
238 $(
239 $(#[cfg($variant_meta)])*
241 impl<'d> any::Degrade for $inner {
242 #[inline]
243 fn degrade<'a>(self) -> $name<'a>
244 where
245 Self: 'a,
246 {
247 $name::from(self)
248 }
249 }
250
251 $(#[cfg($variant_meta)])*
252 impl<'d> From<$inner> for $name<'d> {
253 #[inline]
254 fn from(inner: $inner) -> Self {
255 Self(any::Inner::$variant(inner))
256 }
257 }
258
259 $(#[cfg($variant_meta)])*
260 impl<'d> TryFrom<$name<'d>> for $inner {
261 type Error = $name<'d>;
262
263 #[inline]
264 fn try_from(any: $name<'d>) -> Result<Self, $name<'d>> {
265 #[allow(irrefutable_let_patterns)]
266 if let $name(any::Inner::$variant(inner)) = any {
267 Ok(inner)
268 } else {
269 Err(any)
270 }
271 }
272 }
273 )*
274 };
275}
276
277#[macro_export]
280#[doc(hidden)]
281macro_rules! if_set {
282 (, $not_set:expr) => {
283 $not_set
284 };
285 ($set:expr, $not_set:expr) => {
286 $set
287 };
288}
289
290#[cfg(feature = "unstable")]
291include!(concat!(env!("OUT_DIR"), "/version_macro.rs"));
292
293#[doc_replace]
294#[macro_export]
316#[cfg(feature = "unstable")]
317#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
318macro_rules! at_least_version {
319 ($($branch:tt)*) => {
320 $crate::__esp_hal_at_least_version! { $($branch)* }
321 };
322}
323
324#[macro_export]
329#[doc(hidden)]
330macro_rules! ignore {
331 ($($item:tt)*) => {};
332}
333
334#[macro_export]
342#[doc(hidden)]
343macro_rules! metadata {
344 ($category:literal, $key:ident, $value:expr) => {
345 #[cfg(feature = "rt")]
346 #[unsafe(link_section = concat!(".espressif.metadata"))]
347 #[used]
348 #[unsafe(export_name = concat!($category, ".", stringify!($key)))]
349 static $key: [u8; $value.len()] = const {
350 let val_bytes = $value.as_bytes();
351 let mut val_bytes_array = [0; $value.len()];
352 let mut i = 0;
353 while i < val_bytes.len() {
354 val_bytes_array[i] = val_bytes[i];
355 i += 1;
356 }
357 val_bytes_array
358 };
359 };
360}
361
362#[procmacros::doc_replace]
363#[cfg_attr(
365 all(soc_has_spi2, soc_has_i2c0, gpio_driver_supported),
369 doc = r#"
370## Example
371
372```rust,no_run
373# {before_snippet}
374#
375use esp_hal::assign_resources;
376
377assign_resources! {
378 Resources<'d> {
379 display: DisplayResources<'d> {
380 spi: SPI2,
381 sda: GPIO5,
382 sclk: GPIO4,
383 cs: GPIO3,
384 dc: GPIO2,
385 },
386 axl: AccelerometerResources<'d> {
387 i2c: I2C0,
388 sda: GPIO0,
389 scl: GPIO1,
390 },
391 }
392}
393
394# struct Display<'d>(core::marker::PhantomData<&'d ()>);
395fn init_display<'d>(r: DisplayResources<'d>) -> Display<'d> {
396 // use `r.spi`, `r.sda`, `r.sclk`, `r.cs`, `r.dc`
397 todo!()
398}
399
400# struct Accelerometer<'d>(core::marker::PhantomData<&'d ()>);
401fn init_accelerometer<'d>(r: AccelerometerResources<'d>) -> Accelerometer<'d> {
402 // use `r.i2c`, `r.sda`, `r.scl`
403 todo!()
404}
405
406// let peripherals = esp_hal::init(...);
407let resources = split_resources!(peripherals);
408
409let display = init_display(resources.display);
410let axl = init_accelerometer(resources.axl);
411
412// Other fields (`peripherals.UART0`, ...) of the `peripherals` struct can still be accessed.
413# {after_snippet}
414```
415"#
416)]
417#[macro_export]
419#[cfg(feature = "unstable")]
420#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
421macro_rules! assign_resources {
422 {
423 $(#[$struct_meta:meta])*
424 $vis:vis $struct_name:ident<$struct_lt:lifetime> {
425 $(
426 $(#[$group_meta:meta])*
427 $group_name:ident : $group_struct:ident<$group_lt:lifetime> {
428 $(
429 $(#[$resource_meta:meta])*
430 $resource_name:ident : $resource_field:ident
431 ),*
432 $(,)?
433 }
434 ),+
435 $(,)?
436 }
437 } => {
438 $(
440 $(#[$group_meta])*
441 #[allow(missing_docs)]
442 $vis struct $group_struct<$group_lt> {
443 $(
444 $(#[$resource_meta])*
445 pub $resource_name: $crate::peripherals::$resource_field<$group_lt>,
446 )+
447 }
448
449 impl<$group_lt> $group_struct<$group_lt> {
450 pub unsafe fn steal() -> Self {
456 unsafe {
457 Self {
458 $($resource_name: $crate::peripherals::$resource_field::steal()),*
459 }
460 }
461 }
462
463 pub fn reborrow(&mut self) -> $group_struct<'_> {
468 $group_struct {
469 $($resource_name: self.$resource_name.reborrow()),*
470 }
471 }
472 }
473 )+
474
475 $(#[$struct_meta])*
477 $vis struct $struct_name<$struct_lt> {
479 $( pub $group_name: $group_struct<$struct_lt>, )+
480 }
481
482 impl<$struct_lt> $struct_name<$struct_lt> {
483 pub unsafe fn steal() -> Self {
489 unsafe {
490 Self {
491 $($group_name: $group_struct::steal()),*
492 }
493 }
494 }
495
496 pub fn reborrow(&mut self) -> $struct_name<'_> {
501 $struct_name {
502 $($group_name: self.$group_name.reborrow()),*
503 }
504 }
505 }
506
507 #[macro_export]
509 macro_rules! split_resources {
510 ($peris:ident) => {
511 $struct_name {
512 $($group_name: $group_struct {
513 $($resource_name: $peris.$resource_field),*
514 }),*
515 }
516 }
517 }
518 };
519}
520
521#[doc(hidden)]
559#[rustfmt::skip]
560#[cfg(dma_driver_supported)]
561macro_rules! impl_dma_channel_trait {
562 (
564 $dma_engine:tt,
565 peri = $peri:tt,
566 $pattern:tt => $body:tt
567 ) => {
568 macro_rules! impl_dma_channel_trait_inner {
569 ($pattern) => $body;
570 }
571
572 for_each_dma_channel_peri_pair! {
573 ($dma_engine, any_channel = $any_ch:ident, $peri) => {
574 impl_dma_channel_trait_inner! { ( $peri <'d>, $crate::dma::$any_ch<'d>) }
575 };
576 ($dma_engine, $ch:ident, $peri) => {
577 impl_dma_channel_trait_inner! { ( $peri <'d>, $crate::peripherals::$ch<'d>) }
578 };
579 }
580 };
581
582 (
584 $dma_engine:tt,
585 any_peri = $any_peri:ty,
586 peris = $for_each_peri_macro:ident,
587 $pattern:tt => $body:tt
588 ) => {
589 macro_rules! impl_dma_channel_trait_inner {
590 ($pattern) => $body;
591 }
592
593 for_each_dma_channel! {
594 ($dma_engine, any_channel = $any_ch:ident) => {
595 impl_dma_channel_trait_inner! { ($any_peri, $crate::dma::$any_ch<'d>) }
596 };
597 ($dma_engine, $ch:ident) => {
598 impl_dma_channel_trait_inner! { ($any_peri, $crate::peripherals::$ch<'d>) }
599 };
600 }
601
602 $for_each_peri_macro! {
603 ($peri:ident) => {
604 for_each_dma_channel_peri_pair! {
605 ($dma_engine, any_channel = $any_ch:ident, $peri) => {
606 impl_dma_channel_trait_inner! { ($crate::peripherals::$peri<'d>, $crate::dma::$any_ch<'d>) }
607 };
608 ($dma_engine, $ch:ident, $peri) => {
609 impl_dma_channel_trait_inner! { ($crate::peripherals::$peri<'d>, $crate::peripherals::$ch<'d>) }
610 };
611 }
612 };
613 }
614 };
615}
616#[cfg(dma_driver_supported)]
617pub(crate) use impl_dma_channel_trait;
618#[cfg(feature = "unstable")]
619use procmacros::doc_replace;
620
621#[macro_export]
624#[doc(hidden)]
625#[cfg(feature = "unstable")]
626macro_rules! if_unstable_hal {
627 ($($tt:tt)*) => {
628 $($tt)*
629 };
630}
631
632#[macro_export]
635#[doc(hidden)]
636#[cfg(not(feature = "unstable"))]
637macro_rules! if_unstable_hal {
638 ($($tt:tt)*) => {};
639}