diff --git a/CHANGELOG.md b/CHANGELOG.md index 43dc768e241..b144a4b65f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.47.2] - 2023-10-31 +## [0.47.2] - 2023-11-02 +* Remove dependency on `AtomicU64` which is no longer supported by the upstream `*-espidf` targets * HTTP client: support for chunked encoding of POST requests ## [0.47.1] - 2023-10-18 diff --git a/Cargo.toml b/Cargo.toml index 8cf6e08c32e..b3bd6437cbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "esp-idf-svc" -version = "0.47.1" +version = "0.47.2" authors = ["Ivan Markov "] edition = "2018" resolver = "2" diff --git a/src/timer.rs b/src/timer.rs index e6c9e3315b4..691268977b5 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -315,10 +315,6 @@ pub mod embassy_time { #[cfg(any(feature = "embassy-time-driver", feature = "embassy-time-isr-queue"))] pub mod driver { use core::cell::UnsafeCell; - use core::sync::atomic::{AtomicU64, Ordering}; - - extern crate alloc; - use alloc::sync::{Arc, Weak}; use heapless::Vec; @@ -331,50 +327,9 @@ pub mod embassy_time { use crate::timer::*; struct Alarm { - timer: EspTimer<'static>, - callback: Arc, - } - - impl Alarm { - fn new() -> Result { - let callback = Arc::new(AtomicU64::new(0)); - let timer_callback = Arc::downgrade(&callback); - - let service = EspTimerService::::new()?; - - let timer = service.timer(move || { - if let Some(callback) = Weak::upgrade(&timer_callback) { - Self::call(&callback); - } - })?; - - Ok(Self { timer, callback }) - } - - fn set_alarm(&self, duration: u64) -> Result<(), EspError> { - self.timer.after(Duration::from_micros(duration))?; - - Ok(()) - } - - fn set_callback(&self, callback: fn(*mut ()), ctx: *mut ()) { - let ptr: u64 = ((callback as usize as u64) << 32) | (ctx as usize as u64); - - self.callback.store(ptr, Ordering::SeqCst); - } - - fn call(callback: &AtomicU64) { - let ptr: u64 = callback.load(Ordering::SeqCst); - - if ptr != 0 { - unsafe { - let func: fn(*mut ()) = core::mem::transmute((ptr >> 32) as usize); - let arg: *mut () = (ptr & 0xffffffff) as usize as *mut (); - - func(arg); - } - } - } + timer: Option>, + #[allow(clippy::type_complexity)] + callback: Option<(fn(*mut ()), *mut ())>, } struct EspDriver { @@ -389,6 +344,25 @@ pub mod embassy_time { cs: CriticalSection::new(), } } + + fn call(&self, id: u8) { + let callback = { + let _guard = self.cs.enter(); + + let alarm = self.alarm(id); + + alarm.callback + }; + + if let Some((func, arg)) = callback { + func(arg) + } + } + + #[allow(clippy::mut_from_ref)] + fn alarm(&self, id: u8) -> &mut Alarm { + &mut unsafe { self.alarms.get().as_mut() }.unwrap()[id as usize] + } } unsafe impl Send for EspDriver {} @@ -400,51 +374,58 @@ pub mod embassy_time { } unsafe fn allocate_alarm(&self) -> Option { - let mut id = { + let id = { let _guard = self.cs.enter(); - self.alarms.get().as_mut().unwrap().len() as u8 - }; - - if (id as usize) < MAX_ALARMS { - let alarm = Alarm::new().unwrap(); - - { - let _guard = self.cs.enter(); - - id = self.alarms.get().as_mut().unwrap().len() as u8; - - if (id as usize) == MAX_ALARMS { - return None; - } + let id = self.alarms.get().as_mut().unwrap().len(); + if id < MAX_ALARMS { self.alarms .get() .as_mut() .unwrap() - .push(alarm) + .push(Alarm { + timer: None, + callback: None, + }) .unwrap_or_else(|_| unreachable!()); + + id as u8 + } else { + return None; } + }; - Some(AlarmHandle::new(id)) - } else { - None - } + let service = EspTimerService::::new().unwrap(); + + // Driver is always statically allocated, so this is safe + let static_self: &'static Self = core::mem::transmute(self); + + self.alarm(id).timer = Some(service.timer(move || static_self.call(id)).unwrap()); + + Some(AlarmHandle::new(id)) } fn set_alarm_callback(&self, handle: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { - let alarm = unsafe { &self.alarms.get().as_mut().unwrap()[handle.id() as usize] }; + let _guard = self.cs.enter(); + + let alarm = self.alarm(handle.id()); - alarm.set_callback(callback, ctx); + alarm.callback = Some((callback, ctx)); } fn set_alarm(&self, handle: AlarmHandle, timestamp: u64) -> bool { - let alarm = unsafe { &self.alarms.get().as_mut().unwrap()[handle.id() as usize] }; + let alarm = self.alarm(handle.id()); let now = self.now(); if now < timestamp { - alarm.set_alarm(timestamp - now).unwrap(); + alarm + .timer + .as_mut() + .unwrap() + .after(Duration::from_micros(timestamp)) + .unwrap(); true } else { false @@ -587,7 +568,7 @@ pub mod embassy_time { impl PartialOrd for Timer { fn partial_cmp(&self, other: &Self) -> Option { - self.at.partial_cmp(&other.at) + Some(self.cmp(other)) } }