From ae531a4234b82baef2dfa3f4fbc5da4f72b22dee Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 12 Jan 2024 22:59:57 -0500 Subject: [PATCH] Add initial support for `embedded-hal` version 1.0 This adds a dependency and feature for embedded-hal v1.0 and a basic implementation for the `DelayNs` trait. --- hal/CHANGELOG.md | 1 + hal/Cargo.toml | 3 +++ hal/src/lib.rs | 2 ++ hal/src/prelude.rs | 11 +++++++++-- hal/src/sleeping_delay.rs | 35 ++++++++++++++++++++++++++++++++++- 5 files changed, 49 insertions(+), 3 deletions(-) diff --git a/hal/CHANGELOG.md b/hal/CHANGELOG.md index 6a5bc3b1f10a..b5f9ca2e8e92 100644 --- a/hal/CHANGELOG.md +++ b/hal/CHANGELOG.md @@ -7,6 +7,7 @@ - Update the PACs to svd2rust 0.30.2. - Fix warnings for thumbv7 targets - Update README.md - moves some content to wiki +- Add basic support for `embedded-hal` version 1.0 under the feature `embedded-hal-1`. # v0.16.0 diff --git a/hal/Cargo.toml b/hal/Cargo.toml index f251dce9eb6b..4642de3afa57 100644 --- a/hal/Cargo.toml +++ b/hal/Cargo.toml @@ -36,6 +36,7 @@ bitflags = "1.2.1" cipher = "0.3" cortex-m = "0.7" embedded-hal = "0.2" +embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-rc.1", optional = true } fugit = "0.3" modular-bitfield = "0.11" nb = "1.0" @@ -371,3 +372,5 @@ periph-e53n = ["periph-d51n", "has-ethernet"] periph-e54n = ["periph-d51n", "has-ethernet", "has-can0", "has-can1"] periph-e54p = ["periph-d51p", "has-ethernet", "has-can0", "has-can1"] + +embedded-hal-1 = ["dep:embedded-hal-1"] diff --git a/hal/src/lib.rs b/hal/src/lib.rs index 7a53ac6ef825..3a60b995ab51 100644 --- a/hal/src/lib.rs +++ b/hal/src/lib.rs @@ -1,6 +1,8 @@ #![no_std] pub use embedded_hal as ehal; +#[cfg(feature = "embedded-hal-1")] +pub use embedded_hal_1 as ehal1; pub use fugit; pub use paste; pub mod typelevel; diff --git a/hal/src/prelude.rs b/hal/src/prelude.rs index d4a5cb869188..0caf5fe5019e 100644 --- a/hal/src/prelude.rs +++ b/hal/src/prelude.rs @@ -6,12 +6,19 @@ pub use fugit::RateExtU32 as _; // embedded-hal doesn’t yet have v2 in its prelude, so we need to // export it ourselves -#[cfg(feature = "unproven")] +// +// We only have embedded-hal v0.2 items inour prelude if v1 is not enabled. +#[cfg(all(not(feature = "embedded-hal-1"), feature = "unproven"))] pub use crate::ehal::digital::v2::InputPin as _atsamd_hal_embedded_hal_digital_v2_InputPin; +#[cfg(not(feature = "embedded-hal-1"))] pub use crate::ehal::digital::v2::OutputPin as _atsamd_hal_embedded_hal_digital_v2_OutputPin; -#[cfg(feature = "unproven")] +#[cfg(all(not(feature = "embedded-hal-1"), feature = "unproven"))] pub use crate::ehal::digital::v2::ToggleableOutputPin as _atsamd_hal_embedded_hal_digital_v2_ToggleableOutputPin; +#[cfg(not(feature = "embedded-hal-1"))] pub use crate::ehal::prelude::*; +#[cfg(feature = "embedded-hal-1")] +pub use crate::ehal::digital::{Error as _, InputPin as _, OutputPin as _, StatefulOutputPin as _}; + pub use nb; diff --git a/hal/src/sleeping_delay.rs b/hal/src/sleeping_delay.rs index fb27b220fc53..069587393660 100644 --- a/hal/src/sleeping_delay.rs +++ b/hal/src/sleeping_delay.rs @@ -4,9 +4,13 @@ use cortex_m::asm; use fugit::ExtU32; use crate::ehal::blocking::delay::{DelayMs, DelayUs}; +#[cfg(feature = "embedded-hal-1")] +use crate::ehal1::delay::DelayNs; use crate::timer_traits::InterruptDrivenTimer; const NUM_US_IN_S: u32 = 1_000_000; +#[cfg(feature = "embedded-hal-1")] +const NUM_NS_IN_S: u32 = 1_000_000_000; /// Delay and sleep while we do (WFI) using a timer pub struct SleepingDelay { @@ -35,6 +39,34 @@ where } } +#[cfg(feature = "embedded-hal-1")] +impl DelayNs for SleepingDelay +where + TIM: InterruptDrivenTimer, +{ + fn delay_ns(&mut self, ns: u32) { + // Determine how many cycles we need to run for this delay, if any + // Avoid timers that run longer than a second because for 48 MHz-based timers, + // there is no valid divisor + cycle count greater than ~1.3s, so we'd panic. + let mut loop_count: u32 = 1 + (ns / NUM_NS_IN_S); + + // Start the timer and sleep! + self.timer.start((ns / loop_count).nanos()); + self.timer.enable_interrupt(); + loop { + asm::wfi(); + if self.timer.wait().is_ok() || self.interrupt_fired.load(atomic::Ordering::Relaxed) { + self.interrupt_fired.store(false, atomic::Ordering::Relaxed); + loop_count -= 1; + if loop_count == 0 { + break; + } + } + } + self.timer.disable_interrupt(); + } +} + impl DelayUs for SleepingDelay where TIM: InterruptDrivenTimer, @@ -49,6 +81,7 @@ where let mut count: u32 = 1 + (us / NUM_US_IN_S); // Start the timer and sleep! + // TODO: why does this use nanos? self.timer.start((us / count).nanos()); self.timer.enable_interrupt(); loop { @@ -71,6 +104,6 @@ where TYPE: Into, { fn delay_ms(&mut self, ms: TYPE) { - self.delay_us(ms.into() * 1_000_u32); + >::delay_us(self, ms.into() * 1_000_u32); } }