#![doc = ""]
#![doc = include_str!(concat!(env!("OUT_DIR"), "/esp_hal_embassy_config_table.md"))]
#![doc = ""]
#![doc = document_features::document_features!()]
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
#![deny(missing_docs, rust_2018_idioms, rustdoc::all)]
#![cfg_attr(xtensa, feature(asm_experimental_arch))]
#![no_std]
mod fmt;
use esp_hal::timer::{AnyTimer, timg::Timer as TimgTimer};
pub use macros::embassy_main as main;
#[cfg(feature = "executors")]
pub use self::executor::{Callbacks, Executor, InterruptExecutor};
use self::time_driver::{EmbassyTimer, Timer};
#[cfg(feature = "executors")]
pub(crate) mod executor;
mod time_driver;
mod timer_queue;
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
mod private {
pub trait Sealed {}
#[derive(Clone, Copy)]
pub struct Internal;
}
pub trait TimeBase: private::Sealed {
#[doc(hidden)]
fn timers(self, _: private::Internal) -> &'static mut [Timer];
}
macro_rules! impl_timebase {
($timebase:path) => {
impl private::Sealed for $timebase {}
impl TimeBase for $timebase {
fn timers(self, _: private::Internal) -> &'static mut [Timer] {
mk_static!([Timer; 1], [Timer::new(self)])
}
}
};
}
macro_rules! impl_timebase_array {
($timebase:path, $n:literal) => {
impl private::Sealed for [$timebase; $n] {}
impl TimeBase for [$timebase; $n] {
fn timers(self, _: private::Internal) -> &'static mut [Timer] {
mk_static!([Timer; $n], self.map(|t| Timer::new(t)))
}
}
};
}
macro_rules! impl_array {
($n:literal) => {
impl private::Sealed for [Timer; $n] {}
impl TimeBase for [Timer; $n] {
fn timers(self, _: private::Internal) -> &'static mut [Timer] {
mk_static!([Timer; $n], self)
}
}
impl_timebase_array!(AnyTimer<'static>, $n);
impl_timebase_array!(TimgTimer<'static>, $n);
#[cfg(systimer)]
impl_timebase_array!(esp_hal::timer::systimer::Alarm<'static>, $n);
};
}
impl private::Sealed for Timer {}
impl TimeBase for Timer {
fn timers(self, _: private::Internal) -> &'static mut [Timer] {
mk_static!([Timer; 1], [self])
}
}
impl_timebase!(AnyTimer<'static>);
impl_timebase!(TimgTimer<'static>);
#[cfg(systimer)]
impl_timebase!(esp_hal::timer::systimer::Alarm<'static>);
impl private::Sealed for &'static mut [Timer] {}
impl TimeBase for &'static mut [Timer] {
fn timers(self, _: private::Internal) -> &'static mut [Timer] {
self
}
}
impl<const N: usize> private::Sealed for &'static mut [Timer; N] {}
impl<const N: usize> TimeBase for &'static mut [Timer; N] {
fn timers(self, _: private::Internal) -> &'static mut [Timer] {
self.as_mut()
}
}
impl_array!(1);
impl_array!(2);
impl_array!(3);
impl_array!(4);
#[cfg_attr(systimer, doc = " - `esp_hal::timer::systimer::Alarm`")]
#[doc = esp_hal::before_snippet!()]
pub fn init(time_driver: impl TimeBase) {
#[cfg(all(feature = "executors", multi_core, low_power_wait))]
unsafe {
use esp_hal::interrupt::software::SoftwareInterrupt;
#[esp_hal::ram]
extern "C" fn software3_interrupt() {
unsafe { SoftwareInterrupt::<3>::steal().reset() };
}
esp_hal::interrupt::bind_interrupt(
esp_hal::peripherals::Interrupt::FROM_CPU_INTR3,
software3_interrupt,
);
}
EmbassyTimer::init(time_driver.timers(private::Internal))
}