Skip to content

Commit

Permalink
New release
Browse files Browse the repository at this point in the history
  • Loading branch information
ivmarkov committed Nov 2, 2023
1 parent f966704 commit cdfc601
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 75 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "esp-idf-svc"
version = "0.47.1"
version = "0.47.2"
authors = ["Ivan Markov <[email protected]>"]
edition = "2018"
resolver = "2"
Expand Down
127 changes: 54 additions & 73 deletions src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -331,50 +327,9 @@ pub mod embassy_time {
use crate::timer::*;

struct Alarm {
timer: EspTimer<'static>,
callback: Arc<AtomicU64>,
}

impl Alarm {
fn new() -> Result<Self, EspError> {
let callback = Arc::new(AtomicU64::new(0));
let timer_callback = Arc::downgrade(&callback);

let service = EspTimerService::<Task>::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<EspTimer<'static>>,
#[allow(clippy::type_complexity)]
callback: Option<(fn(*mut ()), *mut ())>,
}

struct EspDriver<const MAX_ALARMS: usize = 16> {
Expand All @@ -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<const MAX_ALARMS: usize> Send for EspDriver<MAX_ALARMS> {}
Expand All @@ -400,51 +374,58 @@ pub mod embassy_time {
}

unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
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::<Task>::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
Expand Down Expand Up @@ -587,7 +568,7 @@ pub mod embassy_time {

impl PartialOrd for Timer {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.at.partial_cmp(&other.at)
Some(self.cmp(other))
}
}

Expand Down

0 comments on commit cdfc601

Please sign in to comment.