From 70012b405c05a9a8f8500bd025f2e2edb08cb64d Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Thu, 10 Feb 2022 18:40:08 +0100 Subject: [PATCH] Adapt to embedded-hal-1.0.0-alpha.7 --- Cargo.toml | 2 +- examples/transactional-i2c.rs | 6 +-- src/cdev_pin.rs | 6 +-- src/i2c.rs | 52 +++++++++++++------- src/lib.rs | 2 +- src/serial.rs | 6 +-- src/spi.rs | 11 ++--- src/sysfs_pin.rs | 6 +-- src/timer.rs | 89 ++++++++++++++++++++++++++++++++++- 9 files changed, 142 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52673de6f..7b49c9e8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ async-tokio = ["gpio-cdev/async-tokio"] default = [ "gpio_cdev", "gpio_sysfs" ] [dependencies] -embedded-hal = "=1.0.0-alpha.6" +embedded-hal = "=1.0.0-alpha.7" gpio-cdev = { version = "0.5.1", optional = true } sysfs_gpio = { version = "0.6.1", optional = true } i2cdev = "0.5.1" diff --git a/examples/transactional-i2c.rs b/examples/transactional-i2c.rs index a8697e127..bd9667308 100644 --- a/examples/transactional-i2c.rs +++ b/examples/transactional-i2c.rs @@ -1,4 +1,4 @@ -use embedded_hal::i2c::blocking::{Operation as I2cOperation, Transactional}; +use embedded_hal::i2c::blocking::{I2c, Operation as I2cOperation}; use linux_embedded_hal::I2cdev; const ADDR: u8 = 0x12; @@ -9,7 +9,7 @@ struct Driver { impl Driver where - I2C: Transactional, + I2C: I2c, { pub fn new(i2c: I2C) -> Self { Driver { i2c } @@ -21,7 +21,7 @@ where I2cOperation::Write(&[0xAB]), I2cOperation::Read(&mut read_buffer), ]; - self.i2c.exec(ADDR, &mut ops).and(Ok(read_buffer[0])) + self.i2c.transaction(ADDR, &mut ops).and(Ok(read_buffer[0])) } } diff --git a/src/cdev_pin.rs b/src/cdev_pin.rs index 9d91a95ce..73e3e5f98 100644 --- a/src/cdev_pin.rs +++ b/src/cdev_pin.rs @@ -53,9 +53,11 @@ fn state_to_value(state: embedded_hal::digital::PinState, is_active_low: bool) - } } -impl embedded_hal::digital::blocking::OutputPin for CdevPin { +impl embedded_hal::digital::ErrorType for CdevPin { type Error = gpio_cdev::errors::Error; +} +impl embedded_hal::digital::blocking::OutputPin for CdevPin { fn set_low(&mut self) -> Result<(), Self::Error> { self.0.set_value(state_to_value( embedded_hal::digital::PinState::Low, @@ -72,8 +74,6 @@ impl embedded_hal::digital::blocking::OutputPin for CdevPin { } impl embedded_hal::digital::blocking::InputPin for CdevPin { - type Error = gpio_cdev::errors::Error; - fn is_high(&self) -> Result { self.0.get_value().map(|val| { val == state_to_value( diff --git a/src/i2c.rs b/src/i2c.rs index 072010796..4cc1bead5 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -57,32 +57,32 @@ impl ops::DerefMut for I2cdev { mod embedded_hal_impl { use super::*; - use embedded_hal::i2c::blocking::{ - Operation as I2cOperation, Read, Transactional, Write, WriteRead, - }; + use embedded_hal::i2c::blocking::{I2c, Operation as I2cOperation}; + use embedded_hal::i2c::ErrorType; use i2cdev::core::{I2CDevice, I2CMessage, I2CTransfer}; use i2cdev::linux::LinuxI2CMessage; - - impl Read for I2cdev { + impl ErrorType for I2cdev { type Error = I2CError; + } + impl I2c for I2cdev { fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { self.set_address(address)?; self.inner.read(buffer).map_err(|err| I2CError { err }) } - } - - impl Write for I2cdev { - type Error = I2CError; fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { self.set_address(address)?; self.inner.write(bytes).map_err(|err| I2CError { err }) } - } - impl WriteRead for I2cdev { - type Error = I2CError; + fn write_iter(&mut self, address: u8, bytes: B) -> Result<(), Self::Error> + where + B: IntoIterator, + { + let bytes: Vec<_> = bytes.into_iter().collect(); + self.write(address, &bytes) + } fn write_read( &mut self, @@ -97,12 +97,24 @@ mod embedded_hal_impl { .map(drop) .map_err(|err| I2CError { err }) } - } - impl Transactional for I2cdev { - type Error = I2CError; + fn write_iter_read( + &mut self, + address: u8, + bytes: B, + buffer: &mut [u8], + ) -> Result<(), Self::Error> + where + B: IntoIterator, + { + let bytes: Vec<_> = bytes.into_iter().collect(); + self.transaction( + address, + &mut [I2cOperation::Write(&bytes), I2cOperation::Read(buffer)], + ) + } - fn exec( + fn transaction( &mut self, address: u8, operations: &mut [I2cOperation], @@ -123,6 +135,14 @@ mod embedded_hal_impl { .map(drop) .map_err(|err| I2CError { err }) } + + fn transaction_iter<'a, O>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> + where + O: IntoIterator>, + { + let mut ops: Vec<_> = operations.into_iter().collect(); + self.transaction(address, &mut ops) + } } } diff --git a/src/lib.rs b/src/lib.rs index d31535525..081e70807 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,4 +49,4 @@ pub use crate::delay::Delay; pub use crate::i2c::{I2CError, I2cdev}; pub use crate::serial::{Serial, SerialError}; pub use crate::spi::{SPIError, Spidev}; -pub use crate::timer::SysTimer; +pub use crate::timer::{CountDown, Periodic, SysTimer}; diff --git a/src/serial.rs b/src/serial.rs index 2d679f2d1..7b528cd11 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -29,9 +29,11 @@ fn translate_io_errors(err: std::io::Error) -> nb::Error { } } -impl embedded_hal::serial::nb::Read for Serial { +impl embedded_hal::serial::ErrorType for Serial { type Error = SerialError; +} +impl embedded_hal::serial::nb::Read for Serial { fn read(&mut self) -> nb::Result { let mut buffer = [0; 1]; let bytes_read = self.0.read(&mut buffer).map_err(translate_io_errors)?; @@ -44,8 +46,6 @@ impl embedded_hal::serial::nb::Read for Serial { } impl embedded_hal::serial::nb::Write for Serial { - type Error = SerialError; - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { self.0.write(&[word]).map_err(translate_io_errors)?; Ok(()) diff --git a/src/spi.rs b/src/spi.rs index 96950bd1c..7e55e521c 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -43,12 +43,15 @@ mod embedded_hal_impl { use embedded_hal::spi::blocking::{ Operation as SpiOperation, Transactional, Transfer, TransferInplace, Write, }; + use embedded_hal::spi::ErrorType; use spidev::SpidevTransfer; use std::io::Write as _; - impl Transfer for Spidev { + impl ErrorType for Spidev { type Error = SPIError; + } + impl Transfer for Spidev { fn transfer<'b>(&mut self, read: &'b mut [u8], write: &[u8]) -> Result<(), Self::Error> { self.0 .transfer(&mut SpidevTransfer::read_write(&write, read)) @@ -57,8 +60,6 @@ mod embedded_hal_impl { } impl TransferInplace for Spidev { - type Error = SPIError; - fn transfer_inplace<'b>(&mut self, buffer: &'b mut [u8]) -> Result<(), Self::Error> { let tx = buffer.to_owned(); self.0 @@ -68,8 +69,6 @@ mod embedded_hal_impl { } impl Write for Spidev { - type Error = SPIError; - fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { self.0.write_all(buffer).map_err(|err| SPIError { err }) } @@ -77,8 +76,6 @@ mod embedded_hal_impl { /// Transactional implementation batches SPI operations into a single transaction impl Transactional for Spidev { - type Error = SPIError; - fn exec<'a>(&mut self, operations: &mut [SpiOperation<'a, u8>]) -> Result<(), Self::Error> { // Map types from generic to linux objects let mut messages: Vec<_> = operations diff --git a/src/sysfs_pin.rs b/src/sysfs_pin.rs index f5691259e..73aff16f8 100644 --- a/src/sysfs_pin.rs +++ b/src/sysfs_pin.rs @@ -28,9 +28,11 @@ impl SysfsPin { } } -impl embedded_hal::digital::blocking::OutputPin for SysfsPin { +impl embedded_hal::digital::ErrorType for SysfsPin { type Error = sysfs_gpio::Error; +} +impl embedded_hal::digital::blocking::OutputPin for SysfsPin { fn set_low(&mut self) -> Result<(), Self::Error> { if self.0.get_active_low()? { self.0.set_value(1) @@ -49,8 +51,6 @@ impl embedded_hal::digital::blocking::OutputPin for SysfsPin { } impl embedded_hal::digital::blocking::InputPin for SysfsPin { - type Error = sysfs_gpio::Error; - fn is_high(&self) -> Result { if !self.0.get_active_low()? { self.0.get_value().map(|val| val != 0) diff --git a/src/timer.rs b/src/timer.rs index 2c759bbe4..91aad8a35 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -5,7 +5,94 @@ use core::convert::Infallible; use std::time::{Duration, Instant}; -use embedded_hal::timer::{nb::CountDown, Periodic}; +/// Marker trait that indicates that a timer is periodic +pub trait Periodic {} + +/// A count down timer +/// +/// Note that this is borrowed from `embedded-hal` 0.2.x and will be in use until the `1.x` version provides one. +/// +/// # 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 +/// +/// ``` +/// use std::time::Duration; +/// use nb::block; +/// use linux_embedded_hal::{CountDown, SysTimer}; +/// +/// fn main() { +/// let mut led: Led = { +/// // .. +/// # Led +/// }; +/// let mut timer = SysTimer::new(); +/// +/// Led.on(); +/// timer.start(Duration::from_millis(1000)).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) {} +/// # } +/// ``` +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