#[doc(hidden)]
#[macro_export]
macro_rules! before_snippet {
() => {
r#"
# #![no_std]
# use esp_hal::{interrupt::{self, InterruptConfigurable}, time::{Duration, Instant, Rate}};
# macro_rules! println {
# ($($tt:tt)*) => { };
# }
# macro_rules! print {
# ($($tt:tt)*) => { };
# }
# #[panic_handler]
# fn panic(_ : &core::panic::PanicInfo) -> ! {
# loop {}
# }
# fn main() {
# let _ = example();
# }
# struct ExampleError {}
# impl <T> From<T> for ExampleError where T: core::fmt::Debug {
# fn from(_value: T) -> Self {
# Self{}
# }
# }
# async fn example() -> Result<(), ExampleError> {
# let mut peripherals = esp_hal::init(esp_hal::Config::default());
"#
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! after_snippet {
() => {
r#"
# Ok(())
# }
"#
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! trm_markdown_link {
() => {
concat!("[Technical Reference Manual](", property!("trm"), ")")
};
($anchor:literal) => {
concat!(
"[Technical Reference Manual](",
property!("trm"),
"#",
$anchor,
")"
)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! any_peripheral {
($(#[$meta:meta])* $vis:vis peripheral $name:ident<'d> {
$(
$(#[cfg($variant_meta:meta)])*
$variant:ident($inner:ty)
),* $(,)?
}) => {
#[doc = concat!("Utilities related to [`", stringify!($name), "`]")]
#[doc(hidden)]
#[instability::unstable]
pub mod any {
#[allow(unused_imports)]
use super::*;
macro_rules! delegate {
($any:ident, $inner_ident:ident => $code:tt) => {
match &$any.0 {
$(
$(#[cfg($variant_meta)])*
any::Inner::$variant($inner_ident) => $code,
)*
}
}
}
pub(crate) use delegate;
$(#[$meta])*
#[derive(Debug)]
pub(crate) enum Inner<'d> {
$(
$(#[cfg($variant_meta)])*
$variant($inner),
)*
}
#[cfg(feature = "defmt")]
impl defmt::Format for Inner<'_> {
fn format(&self, fmt: defmt::Formatter<'_>) {
match self {
$(
$(#[cfg($variant_meta)])*
Self::$variant(inner) => inner.format(fmt),
)*
}
}
}
#[allow(unused)]
pub trait Degrade: Sized + $crate::private::Sealed {
fn degrade<'a>(self) -> super::$name<'a>
where
Self: 'a;
}
}
$(#[$meta])*
#[doc = concat!("let any_peripheral = ", stringify!($name), "::from(peripheral);")]
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
$vis struct $name<'d>(any::Inner<'d>);
impl $name<'_> {
#[inline]
#[allow(unused)]
pub unsafe fn clone_unchecked(&self) -> Self { unsafe {
any::delegate!(self, inner => { Self::from(inner.clone_unchecked()) })
}}
#[inline]
#[allow(unused)]
pub fn reborrow(&mut self) -> $name<'_> {
unsafe { self.clone_unchecked() }
}
#[procmacros::doc_replace]
#[cfg_attr(
// Feature-gated so that this doesn't prevent gradual device bringup. Any
// stable driver would serve the purpose here, so this block will be part
// of the released documentation.
uart_driver_supported,
doc = r#"
## Example
```rust,no_run
# {before_snippet}
#
# use esp_hal::{
# uart::AnyUart as AnyPeripheral,
# peripherals::{UART0 as PERI0, UART1 as PERI1},
# };
#
# let peri0 = peripherals.UART0;
# let peri1 = peripherals.UART1;
// let peri0 = peripherals.PERI0;
// let peri1 = peripherals.PERI1;
let any_peri0 = AnyPeripheral::from(peri0);
let any_peri1 = AnyPeripheral::from(peri1);
let uart0 = any_peri0
.downcast::<PERI0>()
.expect("This downcast succeeds because AnyPeripheral was created from Peri0");
let uart0 = any_peri1
.downcast::<PERI0>()
.expect_err("This AnyPeripheral was created from Peri1, it cannot be downcast to Peri0");
#
# {after_snippet}
```
"#
)]
#[inline]
#[allow(unused)]
pub fn downcast<P>(self) -> Result<P, Self>
where
Self: TryInto<P, Error = Self>
{
self.try_into()
}
}
impl $crate::private::Sealed for $name<'_> {}
impl<'d> any::Degrade for $name<'d> {
#[inline]
fn degrade<'a>(self) -> $name<'a>
where
Self: 'a,
{
self
}
}
$(
$(#[cfg($variant_meta)])*
impl<'d> any::Degrade for $inner {
#[inline]
fn degrade<'a>(self) -> $name<'a>
where
Self: 'a,
{
$name::from(self)
}
}
$(#[cfg($variant_meta)])*
impl<'d> From<$inner> for $name<'d> {
#[inline]
fn from(inner: $inner) -> Self {
Self(any::Inner::$variant(inner))
}
}
$(#[cfg($variant_meta)])*
impl<'d> TryFrom<$name<'d>> for $inner {
type Error = $name<'d>;
#[inline]
fn try_from(any: $name<'d>) -> Result<Self, $name<'d>> {
#[allow(irrefutable_let_patterns)]
if let $name(any::Inner::$variant(inner)) = any {
Ok(inner)
} else {
Err(any)
}
}
}
)*
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! if_set {
(, $not_set:expr) => {
$not_set
};
($set:expr, $not_set:expr) => {
$set
};
}
#[cfg(feature = "unstable")]
include!(concat!(env!("OUT_DIR"), "/version_macro.rs"));
#[doc_replace]
#[macro_export]
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
macro_rules! at_least_version {
($($branch:tt)*) => {
$crate::__esp_hal_at_least_version! { $($branch)* }
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! ignore {
($($item:tt)*) => {};
}
#[macro_export]
#[doc(hidden)]
macro_rules! metadata {
($category:literal, $key:ident, $value:expr) => {
#[cfg(feature = "rt")]
#[unsafe(link_section = concat!(".espressif.metadata"))]
#[used]
#[unsafe(export_name = concat!($category, ".", stringify!($key)))]
static $key: [u8; $value.len()] = const {
let val_bytes = $value.as_bytes();
let mut val_bytes_array = [0; $value.len()];
let mut i = 0;
while i < val_bytes.len() {
val_bytes_array[i] = val_bytes[i];
i += 1;
}
val_bytes_array
};
};
}
#[procmacros::doc_replace]
#[cfg_attr(
// Feature-gated so that this doesn't prevent gradual device bringup. Any
// stable driver would serve the purpose here, so this block will be part
// of the released documentation.
all(soc_has_spi2, soc_has_i2c0, gpio_driver_supported),
doc = r#"
## Example
```rust,no_run
# {before_snippet}
#
use esp_hal::assign_resources;
assign_resources! {
Resources<'d> {
display: DisplayResources<'d> {
spi: SPI2,
sda: GPIO5,
sclk: GPIO4,
cs: GPIO3,
dc: GPIO2,
},
axl: AccelerometerResources<'d> {
i2c: I2C0,
sda: GPIO0,
scl: GPIO1,
},
}
}
# struct Display<'d>(core::marker::PhantomData<&'d ()>);
fn init_display<'d>(r: DisplayResources<'d>) -> Display<'d> {
// use `r.spi`, `r.sda`, `r.sclk`, `r.cs`, `r.dc`
todo!()
}
# struct Accelerometer<'d>(core::marker::PhantomData<&'d ()>);
fn init_accelerometer<'d>(r: AccelerometerResources<'d>) -> Accelerometer<'d> {
// use `r.i2c`, `r.sda`, `r.scl`
todo!()
}
// let peripherals = esp_hal::init(...);
let resources = split_resources!(peripherals);
let display = init_display(resources.display);
let axl = init_accelerometer(resources.axl);
// Other fields (`peripherals.UART0`, ...) of the `peripherals` struct can still be accessed.
# {after_snippet}
```
"#
)]
#[macro_export]
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
macro_rules! assign_resources {
{
$(#[$struct_meta:meta])*
$vis:vis $struct_name:ident<$struct_lt:lifetime> {
$(
$(#[$group_meta:meta])*
$group_name:ident : $group_struct:ident<$group_lt:lifetime> {
$(
$(#[$resource_meta:meta])*
$resource_name:ident : $resource_field:ident
),*
$(,)?
}
),+
$(,)?
}
} => {
$(
$(#[$group_meta])*
#[allow(missing_docs)]
$vis struct $group_struct<$group_lt> {
$(
$(#[$resource_meta])*
pub $resource_name: $crate::peripherals::$resource_field<$group_lt>,
)+
}
impl<$group_lt> $group_struct<$group_lt> {
pub unsafe fn steal() -> Self {
unsafe {
Self {
$($resource_name: $crate::peripherals::$resource_field::steal()),*
}
}
}
pub fn reborrow(&mut self) -> $group_struct<'_> {
$group_struct {
$($resource_name: self.$resource_name.reborrow()),*
}
}
}
)+
$(#[$struct_meta])*
$vis struct $struct_name<$struct_lt> {
$( pub $group_name: $group_struct<$struct_lt>, )+
}
impl<$struct_lt> $struct_name<$struct_lt> {
pub unsafe fn steal() -> Self {
unsafe {
Self {
$($group_name: $group_struct::steal()),*
}
}
}
pub fn reborrow(&mut self) -> $struct_name<'_> {
$struct_name {
$($group_name: self.$group_name.reborrow()),*
}
}
}
#[macro_export]
macro_rules! split_resources {
($peris:ident) => {
$struct_name {
$($group_name: $group_struct {
$($resource_name: $peris.$resource_field),*
}),*
}
}
}
};
}
#[doc(hidden)]
#[rustfmt::skip]
#[cfg(dma_driver_supported)]
macro_rules! impl_dma_channel_trait {
(
$dma_engine:tt,
peri = $peri:tt,
$pattern:tt => $body:tt
) => {
macro_rules! impl_dma_channel_trait_inner {
($pattern) => $body;
}
for_each_dma_channel_peri_pair! {
($dma_engine, any_channel = $any_ch:ident, $peri) => {
impl_dma_channel_trait_inner! { ( $peri <'d>, $crate::dma::$any_ch<'d>) }
};
($dma_engine, $ch:ident, $peri) => {
impl_dma_channel_trait_inner! { ( $peri <'d>, $crate::peripherals::$ch<'d>) }
};
}
};
(
$dma_engine:tt,
any_peri = $any_peri:ty,
peris = $for_each_peri_macro:ident,
$pattern:tt => $body:tt
) => {
macro_rules! impl_dma_channel_trait_inner {
($pattern) => $body;
}
for_each_dma_channel! {
($dma_engine, any_channel = $any_ch:ident) => {
impl_dma_channel_trait_inner! { ($any_peri, $crate::dma::$any_ch<'d>) }
};
($dma_engine, $ch:ident) => {
impl_dma_channel_trait_inner! { ($any_peri, $crate::peripherals::$ch<'d>) }
};
}
$for_each_peri_macro! {
($peri:ident) => {
for_each_dma_channel_peri_pair! {
($dma_engine, any_channel = $any_ch:ident, $peri) => {
impl_dma_channel_trait_inner! { ($crate::peripherals::$peri<'d>, $crate::dma::$any_ch<'d>) }
};
($dma_engine, $ch:ident, $peri) => {
impl_dma_channel_trait_inner! { ($crate::peripherals::$peri<'d>, $crate::peripherals::$ch<'d>) }
};
}
};
}
};
}
#[cfg(dma_driver_supported)]
pub(crate) use impl_dma_channel_trait;
#[cfg(feature = "unstable")]
use procmacros::doc_replace;
#[macro_export]
#[doc(hidden)]
#[cfg(feature = "unstable")]
macro_rules! if_unstable_hal {
($($tt:tt)*) => {
$($tt)*
};
}
#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "unstable"))]
macro_rules! if_unstable_hal {
($($tt:tt)*) => {};
}