embassy/time: make optional via Cargo feature
This commit is contained in:
parent
94bd4eb7d5
commit
35a76c364a
@ -21,7 +21,7 @@ nrf52840 = ["nrf52840-pac"]
|
|||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy" }
|
embassy = { version = "0.1.0", path = "../embassy", features = ["time-tick-32768hz"] }
|
||||||
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]}
|
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]}
|
||||||
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ defmt-warn = [ ]
|
|||||||
defmt-error = [ ]
|
defmt-error = [ ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy" }
|
embassy = { version = "0.1.0", path = "../embassy", features = [ "time-tick-1mhz" ] }
|
||||||
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
||||||
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["rp"]}
|
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["rp"]}
|
||||||
|
|
||||||
|
@ -5,6 +5,6 @@ authors = ["Dario Nieuwenhuis <dirbaio@dirbaio.net>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy", features = ["std"] }
|
embassy = { version = "0.1.0", path = "../embassy", features = ["std", "time-tick-32768hz"] }
|
||||||
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["std"]}
|
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["std"]}
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy" }
|
embassy = { version = "0.1.0", path = "../embassy", features = ["time-tick-32768hz"] }
|
||||||
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["stm32"] }
|
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["stm32"] }
|
||||||
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
||||||
embassy-traits = {version = "0.1.0", path = "../embassy-traits" }
|
embassy-traits = {version = "0.1.0", path = "../embassy-traits" }
|
||||||
|
@ -5,11 +5,13 @@ authors = ["Dario Nieuwenhuis <dirbaio@dirbaio.net>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["tick-32768hz"]
|
default = []
|
||||||
std = ["futures/std", "embassy-traits/std"]
|
std = ["futures/std", "embassy-traits/std"]
|
||||||
tick-32768hz = []
|
|
||||||
tick-1000hz = []
|
time = []
|
||||||
tick-1mhz = []
|
time-tick-32768hz = ["time"]
|
||||||
|
time-tick-1000hz = ["time"]
|
||||||
|
time-tick-1mhz = ["time"]
|
||||||
|
|
||||||
defmt-trace = []
|
defmt-trace = []
|
||||||
defmt-debug = []
|
defmt-debug = []
|
||||||
|
@ -4,12 +4,12 @@ use core::{mem, ptr};
|
|||||||
|
|
||||||
pub mod raw;
|
pub mod raw;
|
||||||
mod run_queue;
|
mod run_queue;
|
||||||
|
#[cfg(feature = "time")]
|
||||||
mod timer_queue;
|
mod timer_queue;
|
||||||
mod util;
|
mod util;
|
||||||
mod waker;
|
mod waker;
|
||||||
|
|
||||||
use crate::interrupt::{Interrupt, InterruptExt};
|
use crate::interrupt::{Interrupt, InterruptExt};
|
||||||
use crate::time::Alarm;
|
|
||||||
|
|
||||||
#[must_use = "Calling a task function does nothing on its own. You must pass the returned SpawnToken to Executor::spawn()"]
|
#[must_use = "Calling a task function does nothing on its own. You must pass the returned SpawnToken to Executor::spawn()"]
|
||||||
pub struct SpawnToken<F> {
|
pub struct SpawnToken<F> {
|
||||||
@ -116,7 +116,8 @@ impl Executor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_alarm(&mut self, alarm: &'static dyn Alarm) {
|
#[cfg(feature = "time")]
|
||||||
|
pub fn set_alarm(&mut self, alarm: &'static dyn crate::time::Alarm) {
|
||||||
self.inner.set_alarm(alarm);
|
self.inner.set_alarm(alarm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +161,8 @@ impl<I: Interrupt> InterruptExecutor<I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_alarm(&mut self, alarm: &'static dyn Alarm) {
|
#[cfg(feature = "time")]
|
||||||
|
pub fn set_alarm(&mut self, alarm: &'static dyn crate::time::Alarm) {
|
||||||
self.inner.set_alarm(alarm);
|
self.inner.set_alarm(alarm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
use atomic_polyfill::{AtomicU32, Ordering};
|
use atomic_polyfill::{AtomicU32, Ordering};
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::cmp::min;
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
use core::task::{Context, Poll, Waker};
|
use core::task::{Context, Poll};
|
||||||
use core::{mem, ptr};
|
use core::{mem, ptr};
|
||||||
|
|
||||||
use super::run_queue::{RunQueue, RunQueueItem};
|
use super::run_queue::{RunQueue, RunQueueItem};
|
||||||
use super::timer_queue::{TimerQueue, TimerQueueItem};
|
|
||||||
use super::util::UninitCell;
|
use super::util::UninitCell;
|
||||||
use super::waker;
|
use super::waker;
|
||||||
use super::SpawnToken;
|
use super::SpawnToken;
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
use super::timer_queue::{TimerQueue, TimerQueueItem};
|
||||||
|
#[cfg(feature = "time")]
|
||||||
use crate::time::{Alarm, Instant};
|
use crate::time::{Alarm, Instant};
|
||||||
|
|
||||||
/// Task is spawned (has a future)
|
/// Task is spawned (has a future)
|
||||||
@ -20,26 +22,33 @@ pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
|
|||||||
/// Task is in the executor run queue
|
/// Task is in the executor run queue
|
||||||
pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
|
pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
|
||||||
/// Task is in the executor timer queue
|
/// Task is in the executor timer queue
|
||||||
|
#[cfg(feature = "time")]
|
||||||
pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
|
pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
|
||||||
|
|
||||||
pub struct TaskHeader {
|
pub struct TaskHeader {
|
||||||
pub(crate) state: AtomicU32,
|
pub(crate) state: AtomicU32,
|
||||||
pub(crate) run_queue_item: RunQueueItem,
|
pub(crate) run_queue_item: RunQueueItem,
|
||||||
pub(crate) expires_at: Cell<Instant>,
|
|
||||||
pub(crate) timer_queue_item: TimerQueueItem,
|
|
||||||
pub(crate) executor: Cell<*const Executor>, // Valid if state != 0
|
pub(crate) executor: Cell<*const Executor>, // Valid if state != 0
|
||||||
pub(crate) poll_fn: UninitCell<unsafe fn(NonNull<TaskHeader>)>, // Valid if STATE_SPAWNED
|
pub(crate) poll_fn: UninitCell<unsafe fn(NonNull<TaskHeader>)>, // Valid if STATE_SPAWNED
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
pub(crate) expires_at: Cell<Instant>,
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
pub(crate) timer_queue_item: TimerQueueItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskHeader {
|
impl TaskHeader {
|
||||||
pub(crate) const fn new() -> Self {
|
pub(crate) const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: AtomicU32::new(0),
|
state: AtomicU32::new(0),
|
||||||
expires_at: Cell::new(Instant::from_ticks(0)),
|
|
||||||
run_queue_item: RunQueueItem::new(),
|
run_queue_item: RunQueueItem::new(),
|
||||||
timer_queue_item: TimerQueueItem::new(),
|
|
||||||
executor: Cell::new(ptr::null()),
|
executor: Cell::new(ptr::null()),
|
||||||
poll_fn: UninitCell::uninit(),
|
poll_fn: UninitCell::uninit(),
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
expires_at: Cell::new(Instant::from_ticks(0)),
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
timer_queue_item: TimerQueueItem::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,9 +163,12 @@ unsafe impl<F: Future + 'static> Sync for Task<F> {}
|
|||||||
|
|
||||||
pub struct Executor {
|
pub struct Executor {
|
||||||
run_queue: RunQueue,
|
run_queue: RunQueue,
|
||||||
timer_queue: TimerQueue,
|
|
||||||
signal_fn: fn(*mut ()),
|
signal_fn: fn(*mut ()),
|
||||||
signal_ctx: *mut (),
|
signal_ctx: *mut (),
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
timer_queue: TimerQueue,
|
||||||
|
#[cfg(feature = "time")]
|
||||||
alarm: Option<&'static dyn Alarm>,
|
alarm: Option<&'static dyn Alarm>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,13 +176,17 @@ impl Executor {
|
|||||||
pub const fn new(signal_fn: fn(*mut ()), signal_ctx: *mut ()) -> Self {
|
pub const fn new(signal_fn: fn(*mut ()), signal_ctx: *mut ()) -> Self {
|
||||||
Self {
|
Self {
|
||||||
run_queue: RunQueue::new(),
|
run_queue: RunQueue::new(),
|
||||||
timer_queue: TimerQueue::new(),
|
|
||||||
signal_fn,
|
signal_fn,
|
||||||
signal_ctx,
|
signal_ctx,
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
timer_queue: TimerQueue::new(),
|
||||||
|
#[cfg(feature = "time")]
|
||||||
alarm: None,
|
alarm: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
pub fn set_alarm(&mut self, alarm: &'static dyn Alarm) {
|
pub fn set_alarm(&mut self, alarm: &'static dyn Alarm) {
|
||||||
self.alarm = Some(alarm);
|
self.alarm = Some(alarm);
|
||||||
}
|
}
|
||||||
@ -192,6 +208,7 @@ impl Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn run_queued(&'static self) {
|
pub unsafe fn run_queued(&'static self) {
|
||||||
|
#[cfg(feature = "time")]
|
||||||
if self.alarm.is_some() {
|
if self.alarm.is_some() {
|
||||||
self.timer_queue.dequeue_expired(Instant::now(), |p| {
|
self.timer_queue.dequeue_expired(Instant::now(), |p| {
|
||||||
p.as_ref().enqueue();
|
p.as_ref().enqueue();
|
||||||
@ -200,6 +217,8 @@ impl Executor {
|
|||||||
|
|
||||||
self.run_queue.dequeue_all(|p| {
|
self.run_queue.dequeue_all(|p| {
|
||||||
let task = p.as_ref();
|
let task = p.as_ref();
|
||||||
|
|
||||||
|
#[cfg(feature = "time")]
|
||||||
task.expires_at.set(Instant::MAX);
|
task.expires_at.set(Instant::MAX);
|
||||||
|
|
||||||
let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel);
|
let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel);
|
||||||
@ -216,11 +235,13 @@ impl Executor {
|
|||||||
task.poll_fn.read()(p as _);
|
task.poll_fn.read()(p as _);
|
||||||
|
|
||||||
// Enqueue or update into timer_queue
|
// Enqueue or update into timer_queue
|
||||||
|
#[cfg(feature = "time")]
|
||||||
self.timer_queue.update(p);
|
self.timer_queue.update(p);
|
||||||
});
|
});
|
||||||
|
|
||||||
// If this is in the past, set_alarm will immediately trigger the alarm,
|
// If this is in the past, set_alarm will immediately trigger the alarm,
|
||||||
// which will make the wfe immediately return so we do another loop iteration.
|
// which will make the wfe immediately return so we do another loop iteration.
|
||||||
|
#[cfg(feature = "time")]
|
||||||
if let Some(alarm) = self.alarm {
|
if let Some(alarm) = self.alarm {
|
||||||
let next_expiration = self.timer_queue.next_expiration();
|
let next_expiration = self.timer_queue.next_expiration();
|
||||||
alarm.set_callback(self.signal_fn, self.signal_ctx);
|
alarm.set_callback(self.signal_fn, self.signal_ctx);
|
||||||
@ -242,9 +263,10 @@ pub unsafe fn wake_task(task: NonNull<TaskHeader>) {
|
|||||||
task.as_ref().enqueue();
|
task.as_ref().enqueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn register_timer(at: Instant, waker: &Waker) {
|
#[cfg(feature = "time")]
|
||||||
|
pub(crate) unsafe fn register_timer(at: Instant, waker: &core::task::Waker) {
|
||||||
let task = waker::task_from_waker(waker);
|
let task = waker::task_from_waker(waker);
|
||||||
let task = task.as_ref();
|
let task = task.as_ref();
|
||||||
let expires_at = task.expires_at.get();
|
let expires_at = task.expires_at.get();
|
||||||
task.expires_at.set(min(expires_at, at));
|
task.expires_at.set(expires_at.min(at));
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ pub(crate) mod fmt;
|
|||||||
pub mod executor;
|
pub mod executor;
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
|
#[cfg(feature = "time")]
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
@ -13,21 +13,13 @@ pub use instant::Instant;
|
|||||||
pub use timer::{with_timeout, Ticker, TimeoutError, Timer};
|
pub use timer::{with_timeout, Ticker, TimeoutError, Timer};
|
||||||
pub use traits::*;
|
pub use traits::*;
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(feature = "time-tick-1000hz")]
|
||||||
all(feature = "tick-32768hz", feature = "tick-1000hz"),
|
|
||||||
all(feature = "tick-32768hz", feature = "tick-1mhz"),
|
|
||||||
))]
|
|
||||||
compile_error!(
|
|
||||||
"Disable default-features to be able to use a tick rate other than the default (32768 Hz)"
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "tick-1000hz")]
|
|
||||||
pub const TICKS_PER_SECOND: u64 = 1_000;
|
pub const TICKS_PER_SECOND: u64 = 1_000;
|
||||||
|
|
||||||
#[cfg(feature = "tick-32768hz")]
|
#[cfg(feature = "time-tick-32768hz")]
|
||||||
pub const TICKS_PER_SECOND: u64 = 32_768;
|
pub const TICKS_PER_SECOND: u64 = 32_768;
|
||||||
|
|
||||||
#[cfg(feature = "tick-1mhz")]
|
#[cfg(feature = "time-tick-1mhz")]
|
||||||
pub const TICKS_PER_SECOND: u64 = 1_000_000;
|
pub const TICKS_PER_SECOND: u64 = 1_000_000;
|
||||||
|
|
||||||
static mut CLOCK: Option<&'static dyn Clock> = None;
|
static mut CLOCK: Option<&'static dyn Clock> = None;
|
||||||
|
Loading…
Reference in New Issue
Block a user