1#![doc = ""]
43#![doc = include_str!(concat!(env!("OUT_DIR"), "/esp_hal_embassy_config_table.md"))]
44#![doc = ""]
45#![doc = document_features::document_features!()]
47#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
48#![deny(missing_docs, rust_2018_idioms, rustdoc::all)]
49#![cfg_attr(xtensa, feature(asm_experimental_arch))]
50#![no_std]
51
52mod fmt;
54
55use esp_hal::timer::{AnyTimer, timg::Timer as TimgTimer};
56pub use macros::embassy_main as main;
57
58#[cfg(feature = "executors")]
59pub use self::executor::{Callbacks, Executor, InterruptExecutor};
60use self::time_driver::{EmbassyTimer, Timer};
61
62#[cfg(feature = "executors")]
63pub(crate) mod executor;
64mod time_driver;
65mod timer_queue;
66
67macro_rules! mk_static {
68 ($t:ty,$val:expr) => {{
69 static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
70 #[deny(unused_attributes)]
71 let x = STATIC_CELL.uninit().write(($val));
72 x
73 }};
74}
75
76mod private {
77 pub trait Sealed {}
78
79 #[derive(Clone, Copy)]
80 pub struct Internal;
81}
82
83pub trait TimeBase: private::Sealed {
85 #[doc(hidden)]
86 fn timers(self, _: private::Internal) -> &'static mut [Timer];
87}
88
89macro_rules! impl_timebase {
90 ($timebase:path) => {
91 impl private::Sealed for $timebase {}
92
93 impl TimeBase for $timebase {
94 fn timers(self, _: private::Internal) -> &'static mut [Timer] {
95 mk_static!([Timer; 1], [Timer::new(self)])
96 }
97 }
98 };
99}
100
101macro_rules! impl_timebase_array {
102 ($timebase:path, $n:literal) => {
103 impl private::Sealed for [$timebase; $n] {}
104
105 impl TimeBase for [$timebase; $n] {
106 fn timers(self, _: private::Internal) -> &'static mut [Timer] {
107 mk_static!([Timer; $n], self.map(|t| Timer::new(t)))
108 }
109 }
110 };
111}
112
113macro_rules! impl_array {
114 ($n:literal) => {
115 impl private::Sealed for [Timer; $n] {}
116
117 impl TimeBase for [Timer; $n] {
118 fn timers(self, _: private::Internal) -> &'static mut [Timer] {
119 mk_static!([Timer; $n], self)
120 }
121 }
122
123 impl_timebase_array!(AnyTimer<'static>, $n);
124 impl_timebase_array!(TimgTimer<'static>, $n);
125 #[cfg(systimer)]
126 impl_timebase_array!(esp_hal::timer::systimer::Alarm<'static>, $n);
127 };
128}
129
130impl private::Sealed for Timer {}
131impl TimeBase for Timer {
132 fn timers(self, _: private::Internal) -> &'static mut [Timer] {
133 mk_static!([Timer; 1], [self])
134 }
135}
136
137impl_timebase!(AnyTimer<'static>);
138impl_timebase!(TimgTimer<'static>);
139#[cfg(systimer)]
140impl_timebase!(esp_hal::timer::systimer::Alarm<'static>);
141
142impl private::Sealed for &'static mut [Timer] {}
143impl TimeBase for &'static mut [Timer] {
144 fn timers(self, _: private::Internal) -> &'static mut [Timer] {
145 self
146 }
147}
148
149impl<const N: usize> private::Sealed for &'static mut [Timer; N] {}
150impl<const N: usize> TimeBase for &'static mut [Timer; N] {
151 fn timers(self, _: private::Internal) -> &'static mut [Timer] {
152 self.as_mut()
153 }
154}
155
156impl_array!(1);
157impl_array!(2);
158impl_array!(3);
159impl_array!(4);
160
161#[cfg_attr(systimer, doc = " - `esp_hal::timer::systimer::Alarm`")]
170#[doc = esp_hal::before_snippet!()]
183pub fn init(time_driver: impl TimeBase) {
192 #[cfg(all(feature = "executors", multi_core, low_power_wait))]
193 unsafe {
194 use esp_hal::interrupt::software::SoftwareInterrupt;
195
196 #[esp_hal::ram]
197 extern "C" fn software3_interrupt() {
198 unsafe { SoftwareInterrupt::<3>::steal().reset() };
203 }
204
205 esp_hal::interrupt::bind_interrupt(
206 esp_hal::peripherals::Interrupt::FROM_CPU_INTR3,
207 software3_interrupt,
208 );
209 }
210
211 EmbassyTimer::init(time_driver.timers(private::Internal))
212}