From 513807ea418fdb89519b059e175adb45ea07ab51 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 3 Nov 2021 16:40:36 +0100 Subject: [PATCH] Remove traits with unconstrained `Time` associated types. As discussed in https://github.com/rust-embedded/embedded-hal/issues/201 and https://github.com/rust-embedded/embedded-hal/issues/177#issuecomment-910396479 , the traits that have an unconstrained `type Time` associated type end up not being usable for HAL-independent drivers in practice, since there is too much variation across HALs of what the actual Time type is. These should be bound to something, probably a `Duration` trait, so that drivers can actually create and use them. Alternatively embedded-hal could have actual `struct Duration` and so. Either way, it's unclear what the final solution would look like. We shouldn't leave these traits in the 1.0 release, since fixing them later will be a breaking change. We should temporarily remove them, and add them back once we have figured this out which won't be a breaking change. --- src/capture.rs | 130 ------------------------------ src/lib.rs | 58 -------------- src/pwm.rs | 207 ------------------------------------------------ src/qei.rs | 18 +---- src/timer.rs | 121 ---------------------------- src/watchdog.rs | 72 ----------------- 6 files changed, 1 insertion(+), 605 deletions(-) delete mode 100644 src/capture.rs delete mode 100644 src/pwm.rs delete mode 100644 src/timer.rs delete mode 100644 src/watchdog.rs diff --git a/src/capture.rs b/src/capture.rs deleted file mode 100644 index 136e7c727..000000000 --- a/src/capture.rs +++ /dev/null @@ -1,130 +0,0 @@ -//! Input capture - -/// Non-blocking input capture traits -pub mod nb { - /// Input capture - /// - /// # Examples - /// - /// You can use this interface to measure the period of (quasi) periodic signals - /// / events - /// - /// ``` - /// extern crate embedded_hal as hal; - /// #[macro_use(block)] - /// extern crate nb; - /// - /// use hal::capture::nb::Capture; - /// - /// fn main() { - /// let mut capture: Capture1 = { - /// // .. - /// # Capture1 - /// }; - /// - /// capture.set_resolution(1.ms()).unwrap(); - /// - /// let before = block!(capture.capture(Channel::_1)).unwrap(); - /// let after = block!(capture.capture(Channel::_1)).unwrap(); - /// - /// let period = after.wrapping_sub(before); - /// - /// println!("Period: {} ms", period); - /// } - /// - /// # use core::convert::Infallible; - /// # struct MilliSeconds(u32); - /// # trait U32Ext { fn ms(self) -> MilliSeconds; } - /// # impl U32Ext for u32 { fn ms(self) -> MilliSeconds { MilliSeconds(self) } } - /// # struct Capture1; - /// # enum Channel { _1 } - /// # impl hal::capture::nb::Capture for Capture1 { - /// # type Error = Infallible; - /// # type Capture = u16; - /// # type Channel = Channel; - /// # type Time = MilliSeconds; - /// # fn capture(&mut self, _: Channel) -> ::nb::Result { Ok(0) } - /// # fn disable(&mut self, _: Channel) -> Result<(), Self::Error> { unimplemented!() } - /// # fn enable(&mut self, _: Channel) -> Result<(), Self::Error> { unimplemented!() } - /// # fn get_resolution(&self) -> Result { unimplemented!() } - /// # fn set_resolution(&mut self, _: T) -> Result<(), Self::Error> where T: Into { Ok(()) } - /// # } - /// ``` - // unproven reason: pre-singletons API. With singletons a `CapturePin` (cf. `PwmPin`) trait seems more - // appropriate - pub trait Capture { - /// Enumeration of `Capture` errors - /// - /// Possible errors: - /// - /// - *overcapture*, the previous capture value was overwritten because it - /// was not read in a timely manner - type Error: core::fmt::Debug; - - /// Enumeration of channels that can be used with this `Capture` interface - /// - /// If your `Capture` interface has no channels you can use the type `()` - /// here - type Channel; - - /// A time unit that can be converted into a human time unit (e.g. seconds) - type Time; - - /// The type of the value returned by `capture` - type Capture; - - /// "Waits" for a transition in the capture `channel` and returns the value - /// of counter at that instant - /// - /// NOTE that you must multiply the returned value by the *resolution* of - /// this `Capture` interface to get a human time unit (e.g. seconds) - fn capture(&mut self, channel: Self::Channel) -> nb::Result; - - /// Disables a capture `channel` - fn disable(&mut self, channel: Self::Channel) -> Result<(), Self::Error>; - - /// Enables a capture `channel` - fn enable(&mut self, channel: Self::Channel) -> Result<(), Self::Error>; - - /// Returns the current resolution - fn get_resolution(&self) -> Result; - - /// Sets the resolution of the capture timer - fn set_resolution(&mut self, resolution: R) -> Result<(), Self::Error> - where - R: Into; - } - - impl Capture for &mut T { - type Error = T::Error; - - type Channel = T::Channel; - - type Time = T::Time; - - type Capture = T::Capture; - - fn capture(&mut self, channel: Self::Channel) -> nb::Result { - T::capture(self, channel) - } - - fn disable(&mut self, channel: Self::Channel) -> Result<(), Self::Error> { - T::disable(self, channel) - } - - fn enable(&mut self, channel: Self::Channel) -> Result<(), Self::Error> { - T::enable(self, channel) - } - - fn get_resolution(&self) -> Result { - T::get_resolution(self) - } - - fn set_resolution(&mut self, resolution: R) -> Result<(), Self::Error> - where - R: Into, - { - T::set_resolution(self, resolution) - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 05b6ad5a7..69bbd48b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -258,60 +258,6 @@ //! # fn main() {} //! ``` //! -//! - Blocking serial read with timeout -//! -//! ``` -//! use embedded_hal as hal; -//! use hal::nb; -//! -//! use hal::serial::nb::Write; -//! use hal::timer::nb::CountDown; -//! -//! enum Error { -//! /// Serial interface error -//! Serial(SE), -//! /// Timeout error -//! TimedOut(TE), -//! } -//! -//! fn read_with_timeout( -//! serial: &mut S, -//! timer: &mut T, -//! timeout: T::Time, -//! ) -> Result> -//! where -//! T: hal::timer::nb::CountDown, -//! S: hal::serial::nb::Read, -//! { -//! timer.start(timeout).map_err(Error::TimedOut)?; -//! -//! loop { -//! match serial.read() { -//! // raise error -//! Err(nb::Error::Other(e)) => return Err(Error::Serial(e)), -//! Err(nb::Error::WouldBlock) => { -//! // no data available yet, check the timer below -//! }, -//! Ok(byte) => return Ok(byte), -//! } -//! -//! match timer.wait() { -//! Err(nb::Error::Other(e)) => { -//! // The error type specified by `timer.wait()` is `!`, which -//! // means no error can actually occur. The Rust compiler -//! // still forces us to provide this match arm, though. -//! unreachable!() -//! }, -//! // no timeout yet, try again -//! Err(nb::Error::WouldBlock) => continue, -//! Ok(()) => return Err(Error::TimedOut(())), -//! } -//! } -//! } -//! -//! # fn main() {} -//! ``` -//! //! - Buffered serial interface with periodic flushing in interrupt handler //! //! ``` @@ -410,16 +356,12 @@ pub mod fmt; pub use nb; pub mod adc; pub mod can; -pub mod capture; pub mod delay; pub mod digital; pub mod i2c; -pub mod pwm; pub mod qei; pub mod serial; pub mod spi; -pub mod timer; -pub mod watchdog; mod private { use crate::i2c::{SevenBitAddress, TenBitAddress}; diff --git a/src/pwm.rs b/src/pwm.rs deleted file mode 100644 index 1208fc0f3..000000000 --- a/src/pwm.rs +++ /dev/null @@ -1,207 +0,0 @@ -//! Pulse Width Modulation - -/// Blocking pulse width modulation traits -pub mod blocking { - /// Pulse Width Modulation - /// - /// # Examples - /// - /// Use this interface to control the power output of some actuator - /// - /// ``` - /// extern crate embedded_hal as hal; - /// - /// use hal::pwm::blocking::Pwm; - /// - /// fn main() { - /// let mut pwm: Pwm1 = { - /// // .. - /// # Pwm1 - /// }; - /// - /// pwm.set_period(1.khz()).unwrap(); - /// - /// let max_duty = pwm.get_max_duty().unwrap(); - /// - /// // brightest LED - /// pwm.set_duty(&Channel::_1, max_duty).unwrap(); - /// - /// // dimmer LED - /// pwm.set_duty(&Channel::_2, max_duty / 4).unwrap(); - /// } - /// - /// # use core::convert::Infallible; - /// # struct KiloHertz(u32); - /// # trait U32Ext { fn khz(self) -> KiloHertz; } - /// # impl U32Ext for u32 { fn khz(self) -> KiloHertz { KiloHertz(self) } } - /// # enum Channel { _1, _2 } - /// # struct Pwm1; - /// # impl hal::pwm::blocking::Pwm for Pwm1 { - /// # type Error = Infallible; - /// # type Channel = Channel; - /// # type Time = KiloHertz; - /// # type Duty = u16; - /// # fn disable(&mut self, _: &Channel) -> Result<(), Self::Error> { unimplemented!() } - /// # fn enable(&mut self, _: &Channel) -> Result<(), Self::Error> { unimplemented!() } - /// # fn get_duty(&self, _: &Channel) -> Result { unimplemented!() } - /// # fn get_max_duty(&self) -> Result { Ok(0) } - /// # fn set_duty(&mut self, _: &Channel, _: u16) -> Result<(), Self::Error> { Ok(()) } - /// # fn get_period(&self) -> Result { unimplemented!() } - /// # fn set_period(&mut self, _: T) -> Result<(), Self::Error> where T: Into { Ok(()) } - /// # } - /// ``` - // unproven reason: pre-singletons API. The `PwmPin` trait seems more useful because it models independent - // PWM channels. Here a certain number of channels are multiplexed in a single implementer. - pub trait Pwm { - /// Enumeration of `Pwm` errors - type Error: core::fmt::Debug; - - /// Enumeration of channels that can be used with this `Pwm` interface - /// - /// If your `Pwm` interface has no channels you can use the type `()` - /// here - type Channel; - - /// A time unit that can be converted into a human time unit (e.g. seconds) - type Time; - - /// Type for the `duty` methods - /// - /// The implementer is free to choose a float / percentage representation - /// (e.g. `0.0 .. 1.0`) or an integer representation (e.g. `0 .. 65535`) - type Duty; - - /// Disables a PWM `channel` - fn disable(&mut self, channel: &Self::Channel) -> Result<(), Self::Error>; - - /// Enables a PWM `channel` - fn enable(&mut self, channel: &Self::Channel) -> Result<(), Self::Error>; - - /// Returns the current PWM period - fn get_period(&self) -> Result; - - /// Returns the current duty cycle - /// - /// While the pin is transitioning to the new duty cycle after a `set_duty` call, this may - /// return the old or the new duty cycle depending on the implementation. - fn get_duty(&self, channel: &Self::Channel) -> Result; - - /// Returns the maximum duty cycle value - fn get_max_duty(&self) -> Result; - - /// Sets a new duty cycle - fn set_duty( - &mut self, - channel: &Self::Channel, - duty: Self::Duty, - ) -> Result<(), Self::Error>; - - /// Sets a new PWM period - fn set_period

(&mut self, period: P) -> Result<(), Self::Error> - where - P: Into; - } - - impl Pwm for &mut T { - type Error = T::Error; - - type Channel = T::Channel; - - type Time = T::Time; - - type Duty = T::Duty; - - fn disable(&mut self, channel: &Self::Channel) -> Result<(), Self::Error> { - T::disable(self, channel) - } - - fn enable(&mut self, channel: &Self::Channel) -> Result<(), Self::Error> { - T::enable(self, channel) - } - - fn get_period(&self) -> Result { - T::get_period(self) - } - - fn get_duty(&self, channel: &Self::Channel) -> Result { - T::get_duty(self, channel) - } - - fn get_max_duty(&self) -> Result { - T::get_max_duty(self) - } - - fn set_duty( - &mut self, - channel: &Self::Channel, - duty: Self::Duty, - ) -> Result<(), Self::Error> { - T::set_duty(self, channel, duty) - } - - fn set_period

(&mut self, period: P) -> Result<(), Self::Error> - where - P: Into, - { - T::set_period(self, period) - } - } - - /// A single PWM channel / pin - /// - /// See `Pwm` for details - pub trait PwmPin { - /// Enumeration of `PwmPin` errors - type Error: core::fmt::Debug; - - /// Type for the `duty` methods - /// - /// The implementer is free to choose a float / percentage representation - /// (e.g. `0.0 .. 1.0`) or an integer representation (e.g. `0 .. 65535`) - type Duty; - - /// Disables a PWM `channel` - fn disable(&mut self) -> Result<(), Self::Error>; - - /// Enables a PWM `channel` - fn enable(&mut self) -> Result<(), Self::Error>; - - /// Returns the current duty cycle - /// - /// While the pin is transitioning to the new duty cycle after a `set_duty` call, this may - /// return the old or the new duty cycle depending on the implementation. - fn get_duty(&self) -> Result; - - /// Returns the maximum duty cycle value - fn get_max_duty(&self) -> Result; - - /// Sets a new duty cycle - fn set_duty(&mut self, duty: Self::Duty) -> Result<(), Self::Error>; - } - - impl PwmPin for &mut T { - type Error = T::Error; - - type Duty = T::Duty; - - fn disable(&mut self) -> Result<(), Self::Error> { - T::disable(self) - } - - fn enable(&mut self) -> Result<(), Self::Error> { - T::enable(self) - } - - fn get_duty(&self) -> Result { - T::get_duty(self) - } - - fn get_max_duty(&self) -> Result { - T::get_max_duty(self) - } - - fn set_duty(&mut self, duty: Self::Duty) -> Result<(), Self::Error> { - T::set_duty(self, duty) - } - } -} diff --git a/src/qei.rs b/src/qei.rs index 688e86f99..83d5210ea 100644 --- a/src/qei.rs +++ b/src/qei.rs @@ -25,22 +25,16 @@ pub mod blocking { /// extern crate nb; /// /// use hal::qei::blocking::Qei; - /// use hal::timer::nb::CountDown; /// /// fn main() { /// let mut qei: Qei1 = { /// // .. /// # Qei1 /// }; - /// let mut timer: Timer6 = { - /// // .. - /// # Timer6 - /// }; /// /// /// let before = qei.count().unwrap(); - /// timer.start(1.s()).unwrap(); - /// block!(timer.wait()); + /// // wait some time /// let after = qei.count().unwrap(); /// /// let speed = after.wrapping_sub(before); @@ -48,9 +42,6 @@ pub mod blocking { /// } /// /// # use core::convert::Infallible; - /// # struct Seconds(u32); - /// # trait U32Ext { fn s(self) -> Seconds; } - /// # impl U32Ext for u32 { fn s(self) -> Seconds { Seconds(self) } } /// # struct Qei1; /// # impl hal::qei::blocking::Qei for Qei1 { /// # type Error = Infallible; @@ -58,13 +49,6 @@ pub mod blocking { /// # fn count(&self) -> Result { Ok(0) } /// # fn direction(&self) -> Result<::hal::qei::Direction, Self::Error> { unimplemented!() } /// # } - /// # struct Timer6; - /// # impl hal::timer::nb::CountDown for Timer6 { - /// # type Error = Infallible; - /// # type Time = Seconds; - /// # fn start(&mut self, _: T) -> Result<(), Infallible> where T: Into { Ok(()) } - /// # fn wait(&mut self) -> ::nb::Result<(), Infallible> { Ok(()) } - /// # } /// ``` // unproven reason: needs to be re-evaluated in the new singletons world. At the very least this needs a // reference implementation diff --git a/src/timer.rs b/src/timer.rs deleted file mode 100644 index 83ba65614..000000000 --- a/src/timer.rs +++ /dev/null @@ -1,121 +0,0 @@ -//! Timer traits - -/// Marker trait that indicates that a timer is periodic -pub trait Periodic {} - -/// Non-blocking timer traits -pub mod nb { - - /// A count down timer - /// - /// # Contract - /// - /// - `self.start(count); block!(self.wait());` MUST block for AT LEAST the time specified by - /// `count`. - /// - /// *Note* that the implementer doesn't necessarily have to be a *downcounting* timer; it could also - /// be an *upcounting* timer as long as the above contract is upheld. - /// - /// # Examples - /// - /// You can use this timer to create delays - /// - /// ``` - /// extern crate embedded_hal as hal; - /// #[macro_use(block)] - /// extern crate nb; - /// - /// use hal::timer::nb::CountDown; - /// - /// fn main() { - /// let mut led: Led = { - /// // .. - /// # Led - /// }; - /// let mut timer: Timer6 = { - /// // .. - /// # Timer6 - /// }; - /// - /// Led.on(); - /// timer.start(1.s()).unwrap(); - /// block!(timer.wait()); // blocks for 1 second - /// Led.off(); - /// } - /// - /// # use core::convert::Infallible; - /// # struct Seconds(u32); - /// # trait U32Ext { fn s(self) -> Seconds; } - /// # impl U32Ext for u32 { fn s(self) -> Seconds { Seconds(self) } } - /// # struct Led; - /// # impl Led { - /// # pub fn off(&mut self) {} - /// # pub fn on(&mut self) {} - /// # } - /// # struct Timer6; - /// # impl hal::timer::nb::CountDown for Timer6 { - /// # type Error = Infallible; - /// # type Time = Seconds; - /// # fn start(&mut self, _: T) -> Result<(), Self::Error> where T: Into { Ok(()) } - /// # fn wait(&mut self) -> ::nb::Result<(), Infallible> { Ok(()) } - /// # } - /// ``` - pub trait CountDown { - /// An enumeration of `CountDown` errors. - /// - /// For infallible implementations, will be `Infallible` - type Error: core::fmt::Debug; - - /// The unit of time used by this timer - type Time; - - /// Starts a new count down - fn start(&mut self, count: T) -> Result<(), Self::Error> - where - T: Into; - - /// Non-blockingly "waits" until the count down finishes - /// - /// # Contract - /// - /// - If `Self: Periodic`, the timer will start a new count down right after the last one - /// finishes. - /// - Otherwise the behavior of calling `wait` after the last call returned `Ok` is UNSPECIFIED. - /// Implementers are suggested to panic on this scenario to signal a programmer error. - fn wait(&mut self) -> nb::Result<(), Self::Error>; - } - - impl CountDown for &mut T { - type Error = T::Error; - - type Time = T::Time; - - fn start