1use core::num::NonZeroU32;
13use core::time::Duration;
14use core::{ffi, ptr};
15
16extern crate alloc;
17use alloc::boxed::Box;
18use alloc::sync::Arc;
19
20use esp_idf_hal::task::asynch::Notification;
21
22use crate::sys::*;
23
24use ::log::debug;
25
26#[cfg(esp_idf_esp_timer_supports_isr_dispatch_method)]
27pub use isr::*;
28
29use crate::handle::RawHandle;
30
31struct UnsafeCallback<'a>(*mut Box<dyn FnMut() + Send + 'a>);
32
33impl<'a> UnsafeCallback<'a> {
34 fn from(boxed: &mut Box<dyn FnMut() + Send + 'a>) -> Self {
35 Self(boxed)
36 }
37
38 unsafe fn from_ptr(ptr: *mut ffi::c_void) -> Self {
39 Self(ptr as *mut _)
40 }
41
42 fn as_ptr(&self) -> *mut ffi::c_void {
43 self.0 as *mut _
44 }
45
46 unsafe fn call(&self) {
47 let reference = self.0.as_mut().unwrap();
48
49 (reference)();
50 }
51}
52
53pub struct EspTimer<'a> {
54 handle: esp_timer_handle_t,
55 _callback: Box<dyn FnMut() + Send + 'a>,
56}
57
58impl EspTimer<'_> {
59 pub fn is_scheduled(&self) -> Result<bool, EspError> {
60 Ok(unsafe { esp_timer_is_active(self.handle) })
61 }
62
63 pub fn cancel(&self) -> Result<bool, EspError> {
64 let res = unsafe { esp_timer_stop(self.handle) };
65
66 Ok(res != ESP_OK)
67 }
68
69 pub fn after(&self, duration: Duration) -> Result<(), EspError> {
70 self.cancel()?;
71
72 esp!(unsafe { esp_timer_start_once(self.handle, duration.as_micros() as _) })?;
73
74 Ok(())
75 }
76
77 pub fn every(&self, duration: Duration) -> Result<(), EspError> {
78 self.cancel()?;
79
80 esp!(unsafe { esp_timer_start_periodic(self.handle, duration.as_micros() as _) })?;
81
82 Ok(())
83 }
84
85 extern "C" fn handle(arg: *mut ffi::c_void) {
86 if crate::hal::interrupt::active() {
87 #[cfg(esp_idf_esp_timer_supports_isr_dispatch_method)]
88 {
89 let signaled = crate::hal::interrupt::with_isr_yield_signal(move || unsafe {
90 UnsafeCallback::from_ptr(arg).call();
91 });
92
93 if signaled {
94 unsafe {
95 crate::sys::esp_timer_isr_dispatch_need_yield();
96 }
97 }
98 }
99
100 #[cfg(not(esp_idf_esp_timer_supports_isr_dispatch_method))]
101 {
102 unreachable!();
103 }
104 } else {
105 unsafe {
106 UnsafeCallback::from_ptr(arg).call();
107 }
108 }
109 }
110}
111
112unsafe impl Send for EspTimer<'_> {}
113
114impl Drop for EspTimer<'_> {
115 fn drop(&mut self) {
116 self.cancel().unwrap();
117
118 while unsafe { esp_timer_delete(self.handle) } != ESP_OK {
119 }
121
122 debug!("Timer dropped");
123 }
124}
125
126impl RawHandle for EspTimer<'_> {
127 type Handle = esp_timer_handle_t;
128
129 fn handle(&self) -> Self::Handle {
130 self.handle
131 }
132}
133
134pub struct EspAsyncTimer {
135 timer: EspTimer<'static>,
136 notification: Arc<Notification>,
137}
138
139impl EspAsyncTimer {
140 pub async fn after(&mut self, duration: Duration) -> Result<(), EspError> {
141 self.timer.cancel()?;
142
143 self.notification.reset();
144 self.timer.after(duration)?;
145
146 self.notification.wait().await;
147
148 Ok(())
149 }
150
151 pub fn every(&mut self, duration: Duration) -> Result<&'_ mut Self, EspError> {
152 self.timer.cancel()?;
153
154 self.notification.reset();
155 self.timer.every(duration)?;
156
157 Ok(self)
158 }
159
160 pub async fn tick(&mut self) -> Result<(), EspError> {
161 self.notification.wait().await;
162
163 Ok(())
164 }
165}
166
167impl embedded_hal_async::delay::DelayNs for EspAsyncTimer {
168 async fn delay_ns(&mut self, ns: u32) {
169 EspAsyncTimer::after(self, Duration::from_micros(ns as _))
170 .await
171 .unwrap();
172 }
173
174 async fn delay_ms(&mut self, ms: u32) {
175 EspAsyncTimer::after(self, Duration::from_millis(ms as _))
176 .await
177 .unwrap();
178 }
179}
180
181pub trait EspTimerServiceType {
182 fn is_isr() -> bool;
183}
184
185#[derive(Clone, Debug)]
186pub struct Task;
187
188impl EspTimerServiceType for Task {
189 fn is_isr() -> bool {
190 false
191 }
192}
193
194pub struct EspTimerService<T>(T)
195where
196 T: EspTimerServiceType;
197
198impl<T> EspTimerService<T>
199where
200 T: EspTimerServiceType,
201{
202 pub fn now(&self) -> Duration {
203 Duration::from_micros(unsafe { esp_timer_get_time() as _ })
204 }
205
206 pub fn timer<F>(&self, callback: F) -> Result<EspTimer<'static>, EspError>
207 where
208 F: FnMut() + Send + 'static,
209 {
210 self.internal_timer(callback, false)
211 }
212
213 pub fn timer_nowake<F>(&self, callback: F) -> Result<EspTimer<'static>, EspError>
215 where
216 F: FnMut() + Send + 'static,
217 {
218 self.internal_timer(callback, true)
219 }
220
221 pub fn timer_async(&self) -> Result<EspAsyncTimer, EspError> {
222 self.internal_timer_async(false)
223 }
224
225 pub fn timer_async_nowake(&self) -> Result<EspAsyncTimer, EspError> {
227 self.internal_timer_async(true)
228 }
229
230 pub unsafe fn timer_nonstatic<'a, F>(&self, callback: F) -> Result<EspTimer<'a>, EspError>
254 where
255 F: FnMut() + Send + 'a,
256 {
257 self.internal_timer(callback, false)
258 }
259
260 pub unsafe fn timer_nonstatic_nowake<'a, F>(
264 &self,
265 callback: F,
266 ) -> Result<EspTimer<'a>, EspError>
267 where
268 F: FnMut() + Send + 'a,
269 {
270 self.internal_timer(callback, true)
271 }
272
273 fn internal_timer<'a, F>(
274 &self,
275 callback: F,
276 skip_unhandled_events: bool,
277 ) -> Result<EspTimer<'a>, EspError>
278 where
279 F: FnMut() + Send + 'a,
280 {
281 let mut handle: esp_timer_handle_t = ptr::null_mut();
282
283 let boxed_callback: Box<dyn FnMut() + Send + 'a> = Box::new(callback);
284
285 let mut callback = Box::new(boxed_callback);
286 let unsafe_callback = UnsafeCallback::from(&mut callback);
287
288 #[cfg(esp_idf_esp_timer_supports_isr_dispatch_method)]
289 let dispatch_method = if T::is_isr() {
290 esp_timer_dispatch_t_ESP_TIMER_ISR
291 } else {
292 esp_timer_dispatch_t_ESP_TIMER_TASK
293 };
294
295 #[cfg(not(esp_idf_esp_timer_supports_isr_dispatch_method))]
296 let dispatch_method = esp_timer_dispatch_t_ESP_TIMER_TASK;
297
298 esp!(unsafe {
299 esp_timer_create(
300 &esp_timer_create_args_t {
301 callback: Some(EspTimer::handle),
302 name: b"rust\0" as *const _ as *const _, arg: unsafe_callback.as_ptr(),
304 dispatch_method,
305 skip_unhandled_events,
306 },
307 &mut handle as *mut _,
308 )
309 })?;
310
311 Ok(EspTimer {
312 handle,
313 _callback: callback,
314 })
315 }
316
317 fn internal_timer_async(&self, skip_unhandled_events: bool) -> Result<EspAsyncTimer, EspError> {
318 let notification = Arc::new(Notification::new());
319
320 let timer = {
321 let notification = Arc::downgrade(¬ification);
322
323 self.internal_timer(
324 move || {
325 if let Some(notification) = notification.upgrade() {
326 notification.notify(NonZeroU32::new(1).unwrap());
327 }
328 },
329 skip_unhandled_events,
330 )?
331 };
332
333 Ok(EspAsyncTimer {
334 timer,
335 notification,
336 })
337 }
338}
339
340pub type EspTaskTimerService = EspTimerService<Task>;
341
342impl EspTimerService<Task> {
343 pub fn new() -> Result<Self, EspError> {
344 Ok(Self(Task))
345 }
346}
347
348impl<T> Clone for EspTimerService<T>
349where
350 T: EspTimerServiceType + Clone,
351{
352 fn clone(&self) -> Self {
353 Self(self.0.clone())
354 }
355}
356
357#[cfg(esp_idf_esp_timer_supports_isr_dispatch_method)]
358mod isr {
359 use crate::sys::EspError;
360
361 #[derive(Clone, Debug)]
362 pub struct ISR;
363
364 impl super::EspTimerServiceType for ISR {
365 fn is_isr() -> bool {
366 true
367 }
368 }
369
370 pub type EspISRTimerService = super::EspTimerService<ISR>;
371
372 impl EspISRTimerService {
373 pub unsafe fn new() -> Result<Self, EspError> {
376 Ok(Self(ISR))
377 }
378 }
379}
380
381#[cfg(feature = "embassy-time-driver")]
388pub mod embassy_time_driver {
389 use core::cell::RefCell;
390 use core::task::Waker;
391
392 use ::embassy_time_driver::Driver;
393 use embassy_time_queue_utils::Queue;
394
395 use crate::private::mutex::Mutex;
396 use crate::timer::*;
397
398 struct EspDriverInner {
399 queue: embassy_time_queue_utils::Queue,
400 timer: Option<EspTimer<'static>>,
401 }
402
403 impl EspDriverInner {
404 fn now() -> u64 {
405 unsafe { esp_timer_get_time() as _ }
406 }
407
408 fn schedule_next_expiration(&mut self) {
409 const MAX_SAFE_TIMEOUT_US: u64 = u64::MAX - 24 * 60 * 60 * 1000 * 1000;
411
412 let timer = self.timer.as_mut().unwrap();
413
414 loop {
415 let now = Self::now();
416 let next_at = self.queue.next_expiration(now);
417
418 if now < next_at {
419 let after = next_at - now;
420
421 if after <= MAX_SAFE_TIMEOUT_US {
422 timer.after(Duration::from_micros(after)).unwrap();
441 }
442
443 break;
444 }
445 }
446 }
447 }
448
449 struct EspDriver {
450 inner: Mutex<RefCell<EspDriverInner>>,
451 }
452
453 impl EspDriver {
454 const fn new() -> Self {
455 Self {
456 inner: Mutex::new(RefCell::new(EspDriverInner {
457 queue: Queue::new(),
458 timer: None,
459 })),
460 }
461 }
462 }
463
464 unsafe impl Send for EspDriver {}
465 unsafe impl Sync for EspDriver {}
466
467 impl Driver for EspDriver {
468 fn now(&self) -> u64 {
469 EspDriverInner::now()
470 }
471
472 fn schedule_wake(&self, at: u64, waker: &Waker) {
473 let service = EspTimerService::<Task>::new().unwrap();
474
475 let guard = self.inner.lock();
476 let mut inner = guard.borrow_mut();
477
478 if inner.timer.is_none() {
479 let static_self: &'static Self = unsafe { core::mem::transmute(self) };
481
482 inner.timer = Some(
483 service
484 .timer(move || {
485 static_self
486 .inner
487 .lock()
488 .borrow_mut()
489 .schedule_next_expiration()
490 })
491 .unwrap(),
492 );
493 }
494
495 if inner.queue.schedule_wake(at, waker) {
496 inner.schedule_next_expiration();
497 }
498 }
499 }
500
501 pub type LinkWorkaround = [*mut (); 2];
502
503 #[used]
504 static mut __INTERNAL_REFERENCE: LinkWorkaround = [
505 _embassy_time_now as *mut _,
506 _embassy_time_schedule_wake as *mut _,
507 ];
508
509 pub fn link() -> LinkWorkaround {
510 unsafe { __INTERNAL_REFERENCE }
511 }
512
513 ::embassy_time_driver::time_driver_impl!(static DRIVER: EspDriver = EspDriver::new());
514}