From a582de00adfa4ea13267283813c938517f13e90b Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Wed, 10 Jul 2019 15:08:41 +0300 Subject: [PATCH 1/2] digital v2 --- CHANGELOG.md | 1 + Cargo.toml | 2 +- examples/blinky.rs | 5 +- examples/blinky_rtc.rs | 1 + examples/delay.rs | 5 +- examples/led.rs | 7 +-- examples/mfrc522.rs | 5 +- examples/serial_config.rs | 4 +- src/gpio.rs | 108 +++++++++++++++++++++++--------------- src/prelude.rs | 4 +- 10 files changed, 84 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3da6f7de..5e2bd5c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Breaking changes +- Replace gpio traits with digital::v2 - Bump `stm32f1` dependency (`0.8.0`) - ADC now requires the clock configuration for intialisation - `disable_jtag` now transforms PA15, PB3 and PB4 to forbid their use without desactivating JTAG diff --git a/Cargo.toml b/Cargo.toml index a9912c3c..7b166e39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,8 +33,8 @@ default-features = false version = "0.2.2" [dependencies.embedded-hal] +version = "0.2.3" features = ["unproven"] -version = "0.2.2" [dev-dependencies] panic-halt = "0.2.0" diff --git a/examples/blinky.rs b/examples/blinky.rs index 51cefcea..44c3c721 100644 --- a/examples/blinky.rs +++ b/examples/blinky.rs @@ -19,6 +19,7 @@ use stm32f1xx_hal::{ timer::Timer, }; use cortex_m_rt::entry; +use embedded_hal::digital::v2::OutputPin; #[entry] fn main() -> ! { @@ -48,8 +49,8 @@ fn main() -> ! { // Wait for the timer to trigger an update and change the state of the LED loop { block!(timer.wait()).unwrap(); - led.set_high(); + led.set_high().unwrap(); block!(timer.wait()).unwrap(); - led.set_low(); + led.set_low().unwrap(); } } diff --git a/examples/blinky_rtc.rs b/examples/blinky_rtc.rs index 1e1da102..7a910de4 100644 --- a/examples/blinky_rtc.rs +++ b/examples/blinky_rtc.rs @@ -20,6 +20,7 @@ use stm32f1xx_hal::{ use nb::block; use cortex_m_rt::entry; +use embedded_hal::digital::v2::OutputPin; #[entry] fn main() -> ! { diff --git a/examples/delay.rs b/examples/delay.rs index f2770d52..100600c6 100644 --- a/examples/delay.rs +++ b/examples/delay.rs @@ -12,6 +12,7 @@ use stm32f1xx_hal::{ delay::Delay, }; use cortex_m_rt::entry; +use embedded_hal::digital::v2::OutputPin; #[entry] fn main() -> ! { @@ -37,9 +38,9 @@ fn main() -> ! { let mut delay = Delay::new(cp.SYST, clocks); loop { - led.set_high(); + led.set_high().unwrap(); delay.delay_ms(1_000_u16); - led.set_low(); + led.set_low().unwrap(); delay.delay_ms(1_000_u16); } } diff --git a/examples/led.rs b/examples/led.rs index f07d7588..c1a96ada 100644 --- a/examples/led.rs +++ b/examples/led.rs @@ -20,6 +20,7 @@ use stm32f1xx_hal::{ pac, }; use cortex_m_rt::entry; +use embedded_hal::digital::v2::OutputPin; #[entry] fn main() -> ! { @@ -29,13 +30,13 @@ fn main() -> ! { let mut gpioc = p.GPIOC.split(&mut rcc.apb2); #[cfg(feature = "stm32f100")] - gpioc.pc9.into_push_pull_output(&mut gpioc.crh).set_high(); + gpioc.pc9.into_push_pull_output(&mut gpioc.crh).set_high().unwrap(); #[cfg(feature = "stm32f101")] - gpioc.pc9.into_push_pull_output(&mut gpioc.crh).set_high(); + gpioc.pc9.into_push_pull_output(&mut gpioc.crh).set_high().unwrap(); #[cfg(feature = "stm32f103")] - gpioc.pc13.into_push_pull_output(&mut gpioc.crh).set_low(); + gpioc.pc13.into_push_pull_output(&mut gpioc.crh).set_low().unwrap(); loop {} } diff --git a/examples/mfrc522.rs b/examples/mfrc522.rs index 00252c91..7ae2ed04 100644 --- a/examples/mfrc522.rs +++ b/examples/mfrc522.rs @@ -13,6 +13,7 @@ use stm32f1xx_hal::{ }; use mfrc522::Mfrc522; use cortex_m_rt::entry; +use embedded_hal::digital::{v1_compat::OldOutputPin, v2::OutputPin}; #[entry] fn main() -> ! { @@ -42,10 +43,10 @@ fn main() -> ! { ); let nss = gpioa.pa4.into_push_pull_output(&mut gpioa.crl); - let mut mfrc522 = Mfrc522::new(spi, nss).unwrap(); + let mut mfrc522 = Mfrc522::new(spi, OldOutputPin::from(nss)).unwrap(); let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); - led.set_high(); + led.set_high().unwrap(); loop { if let Ok(atqa) = mfrc522.reqa() { diff --git a/examples/serial_config.rs b/examples/serial_config.rs index b499946a..1d089568 100644 --- a/examples/serial_config.rs +++ b/examples/serial_config.rs @@ -8,8 +8,6 @@ use panic_halt as _; -use cortex_m::asm; - use nb::block; use stm32f1xx_hal::{ @@ -73,7 +71,7 @@ fn main() -> ! { ); // Split the serial struct into a receiving and a transmitting part - let (mut tx, mut rx) = serial.split(); + let (mut tx, _rx) = serial.split(); let sent = b'U'; block!(tx.write(sent)).ok(); diff --git a/src/gpio.rs b/src/gpio.rs index 551d0f35..92b0155a 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -1,4 +1,18 @@ //! # General Purpose I/Os +//! +//! # Interfacing with v1 traits +//! +//! `embedded-hal` has two versions of the digital traits, `v2` which is used +//! by this crate and `v1` which is deprecated but still used by a lot of drivers. +//! If you want to use such a driver with this crate, you need to convert the digital pins to the `v1` type. +//! +//! This is done using `embedded-hal::digital::v1_compat::OldOutputPin`. For example: +//! +//! ```rust +//! let nss = gpioa.pa4.into_push_pull_output(&mut gpioa.crl); +//! let mut mfrc522 = Mfrc522::new(spi, OldOutputPin::from(nss)).unwrap(); +//! ``` +//! use core::marker::PhantomData; @@ -63,9 +77,10 @@ macro_rules! gpio { ]) => { /// GPIO pub mod $gpiox { + use void::Void; use core::marker::PhantomData; - use crate::hal::digital::{InputPin, OutputPin, StatefulOutputPin, toggleable}; + use crate::hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::pac::{$gpioy, $GPIOX}; use crate::rcc::APB2; @@ -143,49 +158,52 @@ macro_rules! gpio { } impl OutputPin for $PXx> { - fn set_high(&mut self) { + type Error = Void; + fn set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) } + Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }) } - fn set_low(&mut self) { + fn set_low(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + self.i))) } + Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + self.i))) }) } } impl InputPin for $PXx> { - fn is_high(&self) -> bool { - !self.is_low() + type Error = Void; + fn is_high(&self) -> Result { + self.is_low().map(|b| !b) } - fn is_low(&self) -> bool { + fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 } + Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }) } } impl StatefulOutputPin for $PXx> { - fn is_set_high(&self) -> bool { - !self.is_set_low() + fn is_set_high(&self) -> Result { + self.is_set_low().map(|b| !b) } - fn is_set_low(&self) -> bool { + fn is_set_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 } + Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 }) } } impl toggleable::Default for $PXx> {} impl InputPin for $PXx> { - fn is_high(&self) -> bool { - !self.is_low() + type Error = Void; + fn is_high(&self) -> Result { + self.is_low().map(|b| !b) } - fn is_low(&self) -> bool { + fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 } + Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }) } } @@ -354,7 +372,7 @@ macro_rules! gpio { match initial_state { State::High => res.set_high(), State::Low => res.set_low(), - } + }.unwrap(); cr .cr() @@ -392,7 +410,7 @@ macro_rules! gpio { match initial_state { State::High => res.set_high(), State::Low => res.set_low(), - } + }.unwrap(); cr .cr() @@ -437,72 +455,76 @@ macro_rules! gpio { } impl OutputPin for $PXi> { - fn set_high(&mut self) { + type Error = Void; + fn set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) } + Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }) } - fn set_low(&mut self) { + fn set_low(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) } + Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) }) } } impl StatefulOutputPin for $PXi> { - fn is_set_high(&self) -> bool { - !self.is_set_low() + fn is_set_high(&self) -> Result { + self.is_set_low().map(|b| !b) } - fn is_set_low(&self) -> bool { + fn is_set_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 } + Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }) } } impl toggleable::Default for $PXi> {} impl OutputPin for $PXi> { - fn set_high(&mut self) { + type Error = Void; + fn set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) } + Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }) } - fn set_low(&mut self) { + fn set_low(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register - unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) } + Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) }) } } impl StatefulOutputPin for $PXi> { - fn is_set_high(&self) -> bool { - !self.is_set_low() + fn is_set_high(&self) -> Result { + self.is_set_low().map(|b| !b) } - fn is_set_low(&self) -> bool { + fn is_set_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 } + Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }) } } impl InputPin for $PXi> { - fn is_high(&self) -> bool { - !self.is_low() + type Error = Void; + fn is_high(&self) -> Result { + self.is_low().map(|b| !b) } - fn is_low(&self) -> bool { + fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 } + Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }) } } impl InputPin for $PXi> { - fn is_high(&self) -> bool { - !self.is_low() + type Error = Void; + fn is_high(&self) -> Result { + self.is_low().map(|b| !b) } - fn is_low(&self) -> bool { + fn is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects - unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 } + Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }) } } )+ diff --git a/src/prelude.rs b/src/prelude.rs index f38a6b02..89fe334c 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,8 +3,8 @@ pub use crate::dma::DmaExt as _stm32_hal_dma_DmaExt; pub use crate::flash::FlashExt as _stm32_hal_flash_FlashExt; pub use crate::gpio::GpioExt as _stm32_hal_gpio_GpioExt; pub use crate::hal::adc::OneShot as _embedded_hal_adc_OneShot; -pub use crate::hal::digital::StatefulOutputPin as _embedded_hal_digital_StatefulOutputPin; -pub use crate::hal::digital::ToggleableOutputPin as _embedded_hal_digital_ToggleableOutputPin; +pub use crate::hal::digital::v2::StatefulOutputPin as _embedded_hal_digital_StatefulOutputPin; +pub use crate::hal::digital::v2::ToggleableOutputPin as _embedded_hal_digital_ToggleableOutputPin; pub use crate::hal::prelude::*; pub use crate::pwm::PwmExt as _stm32_hal_pwm_PwmExt; pub use crate::rcc::RccExt as _stm32_hal_rcc_RccExt; From b833111a7ff097f3d154a78c1f63b9cbd3f749c7 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sun, 4 Aug 2019 20:06:06 +0300 Subject: [PATCH 2/2] fix blinky_rtc --- examples/blinky_rtc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/blinky_rtc.rs b/examples/blinky_rtc.rs index 7a910de4..08ad7ecc 100644 --- a/examples/blinky_rtc.rs +++ b/examples/blinky_rtc.rs @@ -47,11 +47,11 @@ fn main() -> ! { rtc.set_alarm(5); block!(rtc.wait_alarm()).unwrap(); if led_on { - led.set_low(); + led.set_low().unwrap(); led_on = false; } else { - led.set_high(); + led.set_high().unwrap(); led_on = true; } }