From 54197d1663b8579b9f569e60f1e4aa010bed2cfe Mon Sep 17 00:00:00 2001 From: Thales Fragoso Date: Mon, 28 Jun 2021 18:01:40 -0300 Subject: [PATCH 1/2] Add BlockingTimer and features to choose tick rate --- embassy/Cargo.toml | 5 ++++ embassy/src/time/mod.rs | 64 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index 6364f990..f3cb4655 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml @@ -5,7 +5,11 @@ authors = ["Dario Nieuwenhuis "] edition = "2018" [features] +default = ["tick-hz-32768"] std = ["futures/std", "embassy-traits/std"] +tick-hz-32768 = [] +tick-hz-1000 = [] +tick-mhz-1 = [] defmt-trace = [] defmt-debug = [] @@ -26,6 +30,7 @@ embassy-macros = { version = "0.1.0", path = "../embassy-macros"} embassy-traits = { version = "0.1.0", path = "../embassy-traits"} atomic-polyfill = { version = "0.1.1" } critical-section = "0.2.1" +embedded-hal = "0.2.5" # Workaround https://github.com/japaric/cast.rs/pull/27 cast = { version = "=0.2.3", default-features = false } diff --git a/embassy/src/time/mod.rs b/embassy/src/time/mod.rs index 21b93d38..2ebe19fb 100644 --- a/embassy/src/time/mod.rs +++ b/embassy/src/time/mod.rs @@ -10,8 +10,22 @@ pub use duration::Duration; pub use instant::Instant; pub use traits::*; -// TODO allow customizing, probably via Cargo features `tick-hz-32768` or something. -pub const TICKS_PER_SECOND: u64 = 32768; +#[cfg(any( + all(feature = "tick-hz-32768", feature = "tick-hz-1000"), + all(feature = "tick-hz-32768", feature = "tick-mhz-1"), +))] +compile_error!( + "Disable default-features to be able to use a tick rate other than the default (32768 Hz)" +); + +#[cfg(feature = "tick-hz-1000")] +pub const TICKS_PER_SECOND: u64 = 1_000; + +#[cfg(feature = "tick-hz-32768")] +pub const TICKS_PER_SECOND: u64 = 32_768; + +#[cfg(feature = "tick-mhz-1")] +pub const TICKS_PER_SECOND: u64 = 1_000_000; static mut CLOCK: Option<&'static dyn Clock> = None; @@ -28,3 +42,49 @@ pub unsafe fn set_clock(clock: &'static dyn Clock) { pub(crate) fn now() -> u64 { unsafe { unwrap!(CLOCK, "No clock set").now() } } + +pub struct BlockingTimer; + +impl embedded_hal::blocking::delay::DelayMs for BlockingTimer { + fn delay_ms(&mut self, ms: u8) { + block_for(Duration::from_millis(u64::from(ms))) + } +} + +impl embedded_hal::blocking::delay::DelayMs for BlockingTimer { + fn delay_ms(&mut self, ms: u16) { + block_for(Duration::from_millis(u64::from(ms))) + } +} + +impl embedded_hal::blocking::delay::DelayMs for BlockingTimer { + fn delay_ms(&mut self, ms: u32) { + block_for(Duration::from_millis(u64::from(ms))) + } +} + +#[cfg(feature = "tick-mhz-1")] +impl embedded_hal::blocking::delay::DelayUs for BlockingTimer { + fn delay_us(&mut self, us: u8) { + block_for(Duration::from_micros(u64::from(us))) + } +} + +#[cfg(feature = "tick-mhz-1")] +impl embedded_hal::blocking::delay::DelayUs for BlockingTimer { + fn delay_us(&mut self, us: u16) { + block_for(Duration::from_micros(u64::from(us))) + } +} + +#[cfg(feature = "tick-mhz-1")] +impl embedded_hal::blocking::delay::DelayUs for BlockingTimer { + fn delay_us(&mut self, us: u32) { + block_for(Duration::from_micros(u64::from(us))) + } +} + +pub fn block_for(duration: Duration) { + let expires_at = Instant::now() + duration; + while Instant::now() < expires_at {} +} From 51583afc1e1e5d6eafefbb994c153d1d923a502f Mon Sep 17 00:00:00 2001 From: Thales Fragoso Date: Mon, 28 Jun 2021 18:30:04 -0300 Subject: [PATCH 2/2] Add docs for BlockingTimer and rename tick features --- embassy/Cargo.toml | 8 ++++---- embassy/src/time/mod.rs | 35 +++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index f3cb4655..87f54409 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml @@ -5,11 +5,11 @@ authors = ["Dario Nieuwenhuis "] edition = "2018" [features] -default = ["tick-hz-32768"] +default = ["tick-32768hz"] std = ["futures/std", "embassy-traits/std"] -tick-hz-32768 = [] -tick-hz-1000 = [] -tick-mhz-1 = [] +tick-32768hz = [] +tick-1000hz = [] +tick-1mhz = [] defmt-trace = [] defmt-debug = [] diff --git a/embassy/src/time/mod.rs b/embassy/src/time/mod.rs index 2ebe19fb..d50d9ef0 100644 --- a/embassy/src/time/mod.rs +++ b/embassy/src/time/mod.rs @@ -11,20 +11,20 @@ pub use instant::Instant; pub use traits::*; #[cfg(any( - all(feature = "tick-hz-32768", feature = "tick-hz-1000"), - all(feature = "tick-hz-32768", feature = "tick-mhz-1"), + 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-hz-1000")] +#[cfg(feature = "tick-1000hz")] pub const TICKS_PER_SECOND: u64 = 1_000; -#[cfg(feature = "tick-hz-32768")] +#[cfg(feature = "tick-32768hz")] pub const TICKS_PER_SECOND: u64 = 32_768; -#[cfg(feature = "tick-mhz-1")] +#[cfg(feature = "tick-1mhz")] pub const TICKS_PER_SECOND: u64 = 1_000_000; static mut CLOCK: Option<&'static dyn Clock> = None; @@ -43,47 +43,54 @@ pub(crate) fn now() -> u64 { unsafe { unwrap!(CLOCK, "No clock set").now() } } +/// Type used for blocking delays through embedded-hal traits. +/// +/// For this interface to work, the Executor's clock must be correctly initialized before using it. +/// The delays are implemented in a "best-effort" way, meaning that the cpu will block for at least +/// the amount provided, but accuracy can be affected by many factors, including interrupt usage. +/// Make sure to use a suitable tick rate for your use case. The tick rate can be chosen through +/// features flags of this crate. pub struct BlockingTimer; impl embedded_hal::blocking::delay::DelayMs for BlockingTimer { fn delay_ms(&mut self, ms: u8) { - block_for(Duration::from_millis(u64::from(ms))) + block_for(Duration::from_millis(ms as u64)) } } impl embedded_hal::blocking::delay::DelayMs for BlockingTimer { fn delay_ms(&mut self, ms: u16) { - block_for(Duration::from_millis(u64::from(ms))) + block_for(Duration::from_millis(ms as u64)) } } impl embedded_hal::blocking::delay::DelayMs for BlockingTimer { fn delay_ms(&mut self, ms: u32) { - block_for(Duration::from_millis(u64::from(ms))) + block_for(Duration::from_millis(ms as u64)) } } -#[cfg(feature = "tick-mhz-1")] impl embedded_hal::blocking::delay::DelayUs for BlockingTimer { fn delay_us(&mut self, us: u8) { - block_for(Duration::from_micros(u64::from(us))) + block_for(Duration::from_micros(us as u64)) } } -#[cfg(feature = "tick-mhz-1")] impl embedded_hal::blocking::delay::DelayUs for BlockingTimer { fn delay_us(&mut self, us: u16) { - block_for(Duration::from_micros(u64::from(us))) + block_for(Duration::from_micros(us as u64)) } } -#[cfg(feature = "tick-mhz-1")] impl embedded_hal::blocking::delay::DelayUs for BlockingTimer { fn delay_us(&mut self, us: u32) { - block_for(Duration::from_micros(u64::from(us))) + block_for(Duration::from_micros(us as u64)) } } +/// Blocks the cpu for at least `duration`. +/// +/// For this interface to work, the Executor's clock must be correctly initialized before using it. pub fn block_for(duration: Duration) { let expires_at = Instant::now() + duration; while Instant::now() < expires_at {}