From 77507816502e03f37c78ba894a364c0b454b3423 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Sat, 26 Feb 2022 11:06:55 +0100 Subject: [PATCH] Implement embedded-hal 1.0.0-alpha.7 traits (#298) * embedded-hal v1.0.0-alpha.7 removed several traits * bump dependency to embedded-hal 1.0.0-alpha.7 * Mention embedded-hal alpha changes in changelog --- rp2040-hal/CHANGELOG.md | 2 +- rp2040-hal/Cargo.toml | 2 +- rp2040-hal/src/gpio/dynpin.rs | 16 ++--- rp2040-hal/src/gpio/pin.rs | 30 +++++++--- rp2040-hal/src/i2c/controller.rs | 99 ++++++++++++++++++++++++++----- rp2040-hal/src/pwm/mod.rs | 65 -------------------- rp2040-hal/src/spi.rs | 5 +- rp2040-hal/src/timer.rs | 42 ------------- rp2040-hal/src/uart/peripheral.rs | 11 ++-- rp2040-hal/src/uart/reader.rs | 7 ++- rp2040-hal/src/uart/writer.rs | 7 ++- rp2040-hal/src/watchdog.rs | 43 -------------- 12 files changed, 137 insertions(+), 192 deletions(-) diff --git a/rp2040-hal/CHANGELOG.md b/rp2040-hal/CHANGELOG.md index 7126b06..73a76c0 100644 --- a/rp2040-hal/CHANGELOG.md +++ b/rp2040-hal/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- None +- Updated embedded-hal alpha support to version 1.0.0-alpha.7 ## [0.3.0] - 2021-12-19 diff --git a/rp2040-hal/Cargo.toml b/rp2040-hal/Cargo.toml index ecf2ffc..8822de4 100644 --- a/rp2040-hal/Cargo.toml +++ b/rp2040-hal/Cargo.toml @@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m = "0.7.2" embedded-hal = { version = "0.2.5", features = ["unproven"] } -eh1_0_alpha = { version = "=1.0.0-alpha.6", package="embedded-hal", optional=true } +eh1_0_alpha = { version = "=1.0.0-alpha.7", package="embedded-hal", optional=true } embedded-time = "0.12.0" itertools = { version = "0.10.1", default-features = false } nb = "1.0" diff --git a/rp2040-hal/src/gpio/dynpin.rs b/rp2040-hal/src/gpio/dynpin.rs index 7a29a62..44b38a5 100644 --- a/rp2040-hal/src/gpio/dynpin.rs +++ b/rp2040-hal/src/gpio/dynpin.rs @@ -79,7 +79,7 @@ use super::reg::RegisterInterface; use core::convert::TryFrom; #[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::digital::blocking as eh1; +use eh1_0_alpha::digital as eh1; use hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin}; //============================================================================== @@ -545,8 +545,12 @@ impl StatefulOutputPin for DynPin { } #[cfg(feature = "eh1_0_alpha")] -impl eh1::OutputPin for DynPin { +impl eh1::ErrorType for DynPin { type Error = Error; +} + +#[cfg(feature = "eh1_0_alpha")] +impl eh1::blocking::OutputPin for DynPin { #[inline] fn set_high(&mut self) -> Result<(), Self::Error> { self._set_high() @@ -558,8 +562,7 @@ impl eh1::OutputPin for DynPin { } #[cfg(feature = "eh1_0_alpha")] -impl eh1::InputPin for DynPin { - type Error = Error; +impl eh1::blocking::InputPin for DynPin { #[inline] fn is_high(&self) -> Result { self._is_high() @@ -571,8 +574,7 @@ impl eh1::InputPin for DynPin { } #[cfg(feature = "eh1_0_alpha")] -impl eh1::ToggleableOutputPin for DynPin { - type Error = Error; +impl eh1::blocking::ToggleableOutputPin for DynPin { #[inline] fn toggle(&mut self) -> Result<(), Self::Error> { self._toggle() @@ -580,7 +582,7 @@ impl eh1::ToggleableOutputPin for DynPin { } #[cfg(feature = "eh1_0_alpha")] -impl eh1::StatefulOutputPin for DynPin { +impl eh1::blocking::StatefulOutputPin for DynPin { #[inline] fn is_set_high(&self) -> Result { self._is_set_high() diff --git a/rp2040-hal/src/gpio/pin.rs b/rp2040-hal/src/gpio/pin.rs index 15a8508..19df1d8 100644 --- a/rp2040-hal/src/gpio/pin.rs +++ b/rp2040-hal/src/gpio/pin.rs @@ -104,7 +104,7 @@ use core::marker::PhantomData; use crate::gpio::dynpin::DynFunction; #[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::digital::blocking as eh1; +use eh1_0_alpha::digital as eh1; use hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin}; use core::mem::transmute; @@ -845,12 +845,20 @@ where } #[cfg(feature = "eh1_0_alpha")] -impl eh1::OutputPin for Pin> +impl eh1::ErrorType for Pin> where I: PinId, C: OutputConfig, { type Error = Infallible; +} + +#[cfg(feature = "eh1_0_alpha")] +impl eh1::blocking::OutputPin for Pin> +where + I: PinId, + C: OutputConfig, +{ #[inline] fn set_high(&mut self) -> Result<(), Self::Error> { self._set_high(); @@ -864,11 +872,10 @@ where } #[cfg(feature = "eh1_0_alpha")] -impl eh1::InputPin for Pin +impl eh1::blocking::InputPin for Pin where I: PinId, { - type Error = Infallible; #[inline] fn is_high(&self) -> Result { Ok(self._is_high()) @@ -880,12 +887,20 @@ where } #[cfg(feature = "eh1_0_alpha")] -impl eh1::InputPin for Pin> +impl eh1::ErrorType for Pin> where I: PinId, C: InputConfig, { type Error = Infallible; +} + +#[cfg(feature = "eh1_0_alpha")] +impl eh1::blocking::InputPin for Pin> +where + I: PinId, + C: InputConfig, +{ #[inline] fn is_high(&self) -> Result { Ok(self._is_high()) @@ -897,12 +912,11 @@ where } #[cfg(feature = "eh1_0_alpha")] -impl eh1::ToggleableOutputPin for Pin> +impl eh1::blocking::ToggleableOutputPin for Pin> where I: PinId, C: OutputConfig, { - type Error = Infallible; #[inline] fn toggle(&mut self) -> Result<(), Self::Error> { self._toggle(); @@ -911,7 +925,7 @@ where } #[cfg(feature = "eh1_0_alpha")] -impl eh1::StatefulOutputPin for Pin> +impl eh1::blocking::StatefulOutputPin for Pin> where I: PinId, C: OutputConfig, diff --git a/rp2040-hal/src/i2c/controller.rs b/rp2040-hal/src/i2c/controller.rs index 212bf58..bd4ac7c 100644 --- a/rp2040-hal/src/i2c/controller.rs +++ b/rp2040-hal/src/i2c/controller.rs @@ -10,7 +10,7 @@ use hal::blocking::i2c::{Read, Write, WriteRead}; use pac::{i2c0::RegisterBlock as Block, RESETS}; #[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::i2c::blocking as eh1; +use eh1_0_alpha::i2c as eh1; use super::{i2c_reserved_addr, Controller, Error, SclPin, SdaPin, I2C}; @@ -160,7 +160,12 @@ impl, PINS> I2C { } } - fn read_internal(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + fn read_internal( + &mut self, + buffer: &mut [u8], + force_restart: bool, + do_stop: bool, + ) -> Result<(), Error> { let lastindex = buffer.len() - 1; for (i, byte) in buffer.iter_mut().enumerate() { let first = i == 0; @@ -170,13 +175,13 @@ impl, PINS> I2C { while self.tx_fifo_full() {} self.i2c.ic_data_cmd.write(|w| { - if first { + if force_restart && first { w.restart().enable(); } else { w.restart().disable(); } - if last { + if do_stop && last { w.stop().enable(); } else { w.stop().disable(); @@ -246,7 +251,7 @@ impl, PINS> Read for I2C { Self::validate(addr, None, Some(buffer.is_empty()))?; self.setup(addr); - self.read_internal(buffer) + self.read_internal(buffer, true, true) } } impl, PINS> WriteRead for I2C { @@ -259,7 +264,7 @@ impl, PINS> WriteRead for I2C { self.setup(addr); self.write_internal(tx, false)?; - self.read_internal(rx) + self.read_internal(rx, true, true) } } impl, PINS> Write for I2C { @@ -275,26 +280,90 @@ impl, PINS> Write for I2C { } #[cfg(feature = "eh1_0_alpha")] -impl, PINS> eh1::Write for I2C { +impl, PINS> eh1::ErrorType for I2C { type Error = Error; +} +#[cfg(feature = "eh1_0_alpha")] +impl, PINS> eh1::blocking::I2c for I2C { fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { Write::write(self, addr, bytes) } -} -#[cfg(feature = "eh1_0_alpha")] -impl, PINS> eh1::WriteRead for I2C { - type Error = Error; + + fn write_iter(&mut self, address: u8, bytes: B) -> Result<(), Self::Error> + where + B: IntoIterator, + { + let mut peekable = bytes.into_iter().peekable(); + let addr: u16 = address.into(); + Self::validate(addr, Some(peekable.peek().is_none()), None)?; + self.setup(addr); + + while let Some(tx) = peekable.next() { + self.write_internal(&[tx], peekable.peek().is_none())? + } + Ok(()) + } fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { WriteRead::write_read(self, addr, bytes, buffer) } -} -#[cfg(feature = "eh1_0_alpha")] -impl, PINS> eh1::Read for I2C { - type Error = Error; + + fn write_iter_read( + &mut self, + address: u8, + bytes: B, + buffer: &mut [u8], + ) -> Result<(), Self::Error> + where + B: IntoIterator, + { + let mut peekable = bytes.into_iter().peekable(); + let addr: u16 = address.into(); + Self::validate(addr, Some(peekable.peek().is_none()), None)?; + self.setup(addr); + + for tx in peekable { + self.write_internal(&[tx], false)? + } + self.read_internal(buffer, true, true) + } fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { Read::read(self, addr, buffer) } + + fn transaction<'a>( + &mut self, + address: u8, + operations: &mut [eh1::blocking::Operation<'a>], + ) -> Result<(), Self::Error> { + let addr: u16 = address.into(); + self.setup(addr); + for i in 0..operations.len() { + let last = i == operations.len() - 1; + match &mut operations[i] { + eh1::blocking::Operation::Read(buf) => self.read_internal(buf, false, last)?, + eh1::blocking::Operation::Write(buf) => self.write_internal(buf, last)?, + } + } + Ok(()) + } + + fn transaction_iter<'a, O>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> + where + O: IntoIterator>, + { + let addr: u16 = address.into(); + self.setup(addr); + let mut peekable = operations.into_iter().peekable(); + while let Some(operation) = peekable.next() { + let last = peekable.peek().is_none(); + match operation { + eh1::blocking::Operation::Read(buf) => self.read_internal(buf, false, last)?, + eh1::blocking::Operation::Write(buf) => self.write_internal(buf, last)?, + } + } + Ok(()) + } } diff --git a/rp2040-hal/src/pwm/mod.rs b/rp2040-hal/src/pwm/mod.rs index 4720f9d..a4eac77 100644 --- a/rp2040-hal/src/pwm/mod.rs +++ b/rp2040-hal/src/pwm/mod.rs @@ -87,8 +87,6 @@ use crate::{ resets::SubsystemReset, typelevel::Sealed, }; -#[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::pwm::blocking as eh1; use embedded_hal::PwmPin; use pac::PWM; @@ -616,38 +614,6 @@ impl PwmPin for Channel { } } -#[cfg(feature = "eh1_0_alpha")] -impl eh1::PwmPin for Channel { - type Duty = u16; - type Error = core::convert::Infallible; - - /// We cant disable the channel without disturbing the other channel. - /// So this just sets the duty cycle to zero - fn disable(&mut self) -> Result<(), Self::Error> { - self.duty_cycle = self.regs.read_cc_a(); - self.regs.write_cc_a(0); - Ok(()) - } - - fn enable(&mut self) -> Result<(), Self::Error> { - self.regs.write_cc_a(self.duty_cycle); - Ok(()) - } - - fn get_duty(&self) -> Result { - Ok(self.regs.read_cc_a()) - } - - fn get_max_duty(&self) -> Result { - Ok(self.regs.read_top()) - } - - fn set_duty(&mut self, duty: Self::Duty) -> Result<(), Self::Error> { - self.regs.write_cc_a(duty); - Ok(()) - } -} - impl PwmPin for Channel { type Duty = u16; @@ -674,37 +640,6 @@ impl PwmPin for Channel { self.regs.write_cc_b(duty) } } -#[cfg(feature = "eh1_0_alpha")] -impl eh1::PwmPin for Channel { - type Duty = u16; - type Error = core::convert::Infallible; - - /// We cant disable the channel without disturbing the other channel. - /// So this just sets the duty cycle to zero - fn disable(&mut self) -> Result<(), Self::Error> { - self.duty_cycle = self.regs.read_cc_b(); - self.regs.write_cc_b(0); - Ok(()) - } - - fn enable(&mut self) -> Result<(), Self::Error> { - self.regs.write_cc_b(self.duty_cycle); - Ok(()) - } - - fn get_duty(&self) -> Result { - Ok(self.regs.read_cc_b()) - } - - fn get_max_duty(&self) -> Result { - Ok(self.regs.read_top()) - } - - fn set_duty(&mut self, duty: Self::Duty) -> Result<(), Self::Error> { - self.regs.write_cc_b(duty); - Ok(()) - } -} impl> Channel { /// Capture a gpio pin and use it as pwm output for channel A diff --git a/rp2040-hal/src/spi.rs b/rp2040-hal/src/spi.rs index 7244dd0..9dd54b1 100644 --- a/rp2040-hal/src/spi.rs +++ b/rp2040-hal/src/spi.rs @@ -243,9 +243,12 @@ macro_rules! impl_write { impl spi::write_iter::Default<$type> for Spi {} #[cfg(feature = "eh1_0_alpha")] - impl eh1::nb::FullDuplex<$type> for Spi { + impl eh1::ErrorType for Spi { type Error = SpiInfallible; + } + #[cfg(feature = "eh1_0_alpha")] + impl eh1::nb::FullDuplex<$type> for Spi { fn read(&mut self) -> Result<$type, nb::Error> { if !self.is_readable() { return Err(nb::Error::WouldBlock); diff --git a/rp2040-hal/src/timer.rs b/rp2040-hal/src/timer.rs index 84478ea..ed912f7 100644 --- a/rp2040-hal/src/timer.rs +++ b/rp2040-hal/src/timer.rs @@ -133,38 +133,7 @@ impl embedded_hal::timer::CountDown for CountDown<'_> { } } -#[cfg(feature = "eh1_0_alpha")] -impl eh1_0_alpha::timer::nb::CountDown for CountDown<'_> { - type Time = embedded_time::duration::Microseconds; - type Error = &'static str; - - fn start(&mut self, count: T) -> Result<(), Self::Error> - where - T: Into, - { - self.period = count.into(); - self.next_end = Some(self.timer.get_counter().wrapping_add(self.period.0)); - Ok(()) - } - - fn wait(&mut self) -> nb::Result<(), Self::Error> { - if let Some(end) = self.next_end { - let ts = self.timer.get_counter(); - if ts >= end { - self.next_end = Some(end.wrapping_add(self.period.0)); - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } else { - panic!("CountDown is not running!"); - } - } -} - impl embedded_hal::timer::Periodic for CountDown<'_> {} -#[cfg(feature = "eh1_0_alpha")] -impl eh1_0_alpha::timer::Periodic for CountDown<'_> {} impl embedded_hal::timer::Cancel for CountDown<'_> { type Error = &'static str; @@ -178,17 +147,6 @@ impl embedded_hal::timer::Cancel for CountDown<'_> { } } } -#[cfg(feature = "eh1_0_alpha")] -impl eh1_0_alpha::timer::nb::Cancel for CountDown<'_> { - fn cancel(&mut self) -> Result<(), Self::Error> { - if self.next_end.is_none() { - Err("CountDown is not running.") - } else { - self.next_end = None; - Ok(()) - } - } -} macro_rules! impl_alarm { ($name:ident { rb: $timer_alarm:ident, int: $int_alarm:ident, int_name: $int_name:tt, armed_bit_mask: $armed_bit_mask: expr }) => { diff --git a/rp2040-hal/src/uart/peripheral.rs b/rp2040-hal/src/uart/peripheral.rs index 67e474a..796731f 100644 --- a/rp2040-hal/src/uart/peripheral.rs +++ b/rp2040-hal/src/uart/peripheral.rs @@ -15,7 +15,7 @@ use nb::Error::{Other, WouldBlock}; use rp2040_pac::{UART0, UART1}; #[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::serial::nb as eh1; +use eh1_0_alpha::serial as eh1; /// An UART Peripheral based on an underlying UART device. pub struct UartPeripheral> { @@ -345,9 +345,12 @@ impl> Read for UartPeripheral> eh1::Read for UartPeripheral { +impl> eh1::ErrorType for UartPeripheral { type Error = ReadErrorType; +} +#[cfg(feature = "eh1_0_alpha")] +impl> eh1::nb::Read for UartPeripheral { fn read(&mut self) -> nb::Result { let byte: &mut [u8] = &mut [0; 1]; @@ -377,9 +380,7 @@ impl> Write for UartPeripheral> eh1::Write for UartPeripheral { - type Error = SerialInfallible; - +impl> eh1::nb::Write for UartPeripheral { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { if self.write_raw(&[word]).is_err() { Err(WouldBlock) diff --git a/rp2040-hal/src/uart/reader.rs b/rp2040-hal/src/uart/reader.rs index c8f03f3..78b8702 100644 --- a/rp2040-hal/src/uart/reader.rs +++ b/rp2040-hal/src/uart/reader.rs @@ -10,7 +10,7 @@ use embedded_time::rate::Baud; use nb::Error::*; #[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::serial::nb as eh1; +use eh1_0_alpha::serial as eh1; /// When there's a read error. pub struct ReadError<'err> { @@ -217,9 +217,12 @@ impl> Read for Reader { } #[cfg(feature = "eh1_0_alpha")] -impl> eh1::Read for Reader { +impl> eh1::ErrorType for Reader { type Error = ReadErrorType; +} +#[cfg(feature = "eh1_0_alpha")] +impl> eh1::nb::Read for Reader { fn read(&mut self) -> nb::Result { let byte: &mut [u8] = &mut [0; 1]; diff --git a/rp2040-hal/src/uart/writer.rs b/rp2040-hal/src/uart/writer.rs index d5f86ba..bf5a550 100644 --- a/rp2040-hal/src/uart/writer.rs +++ b/rp2040-hal/src/uart/writer.rs @@ -10,7 +10,7 @@ use nb::Error::*; use rp2040_pac::uart0::RegisterBlock; #[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::serial::nb as eh1; +use eh1_0_alpha::serial as eh1; /// Returns `Err(WouldBlock)` if the UART TX FIFO still has data in it or /// `Ok(())` if the FIFO is empty. @@ -169,9 +169,12 @@ impl> Write for Writer { } #[cfg(feature = "eh1_0_alpha")] -impl> eh1::Write for Writer { +impl> eh1::ErrorType for Writer { type Error = super::utils::SerialInfallible; +} +#[cfg(feature = "eh1_0_alpha")] +impl> eh1::nb::Write for Writer { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { if self.write_raw(&[word]).is_err() { Err(WouldBlock) diff --git a/rp2040-hal/src/watchdog.rs b/rp2040-hal/src/watchdog.rs index 21d3725..286275d 100644 --- a/rp2040-hal/src/watchdog.rs +++ b/rp2040-hal/src/watchdog.rs @@ -35,8 +35,6 @@ //! See [examples/watchdog.rs](https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal/examples/watchdog.rs) for a more complete example use crate::pac::WATCHDOG; -#[cfg(feature = "eh1_0_alpha")] -use eh1_0_alpha::watchdog::blocking as eh1; use embedded_hal::watchdog; use embedded_time::{duration, fixed_point::FixedPoint}; @@ -114,15 +112,6 @@ impl watchdog::Watchdog for Watchdog { self.load_counter(self.delay_ms) } } -#[cfg(feature = "eh1_0_alpha")] -impl eh1::Watchdog for Watchdog { - type Error = core::convert::Infallible; - - fn feed(&mut self) -> Result<(), Self::Error> { - self.load_counter(self.delay_ms); - Ok(()) - } -} impl watchdog::WatchdogEnable for Watchdog { type Time = duration::Microseconds; @@ -146,41 +135,9 @@ impl watchdog::WatchdogEnable for Watchdog { self.enable(true); } } -#[cfg(feature = "eh1_0_alpha")] -impl eh1::Enable for Watchdog { - type Error = core::convert::Infallible; - type Target = Self; - type Time = duration::Microseconds; - - fn start>(mut self, period: T) -> Result { - const MAX_PERIOD: u32 = 0xFFFFFF; - - // Due to a logic error, the watchdog decrements by 2 and - // the load value must be compensated; see RP2040-E1 - self.delay_ms = period.into().integer() * 2; - - if self.delay_ms > MAX_PERIOD { - panic!("Period cannot exceed maximum load value of {}", MAX_PERIOD); - } - - self.enable(false); - self.load_counter(self.delay_ms); - self.enable(true); - Ok(self) - } -} impl watchdog::WatchdogDisable for Watchdog { fn disable(&mut self) { self.enable(false) } } -#[cfg(feature = "eh1_0_alpha")] -impl eh1::Disable for Watchdog { - type Error = core::convert::Infallible; - type Target = Self; - fn disable(self) -> Result { - self.enable(false); - Ok(self) - } -}