diff --git a/.cargo/config b/.cargo/config.toml similarity index 100% rename from .cargo/config rename to .cargo/config.toml diff --git a/CHANGELOG.md b/CHANGELOG.md index edf2c3fb..5a46ac28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Replace UB code by a legitimate pointer access - Reexport `Direction` from `qei` - Add dac +- support `embedded-hal-1.0` ## [v0.10.0] - 2022-12-12 diff --git a/Cargo.toml b/Cargo.toml index b66f6b95..a2690631 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,16 +20,30 @@ default-target = "x86_64-unknown-linux-gnu" [dependencies] cortex-m = "0.7.6" cortex-m-rt = "0.7.1" -nb = "1" +nb = "1.1" stm32f1 = "0.15.1" embedded-dma = "0.2.0" bxcan = "0.7" void = { default-features = false, version = "1.0.2" } -embedded-hal = { features = ["unproven"], version = "0.2.7" } -fugit = "0.3.6" +fugit = "0.3.7" fugit-timer = "0.1.3" rtic-monotonic = { version = "1.0", optional = true } bitflags = "1.3.2" +vcell = "0.1.3" + +[dependencies.embedded-hal-02] +package = "embedded-hal" +version = "0.2.7" +features = ["unproven"] + +[dependencies.embedded-hal] +version = "1.0" + +[dependencies.embedded-hal-nb] +version = "1.0" + +[dependencies.embedded-io] +version = "0.6.1" [dependencies.stm32-usbd] version = "0.6.0" @@ -45,7 +59,6 @@ heapless = "0.7.16" mfrc522 = "0.3.0" usb-device = "0.2.8" usbd-serial = "0.1.1" -unwrap-infallible = "0.1.5" [features] device-selected = [] diff --git a/examples/delay-timer-blinky.rs b/examples/delay-timer-blinky.rs index 16e6a990..7cda54b3 100644 --- a/examples/delay-timer-blinky.rs +++ b/examples/delay-timer-blinky.rs @@ -41,7 +41,7 @@ fn main() -> ! { loop { // On for 1s, off for 3s. led.set_high(); - // Use `embedded_hal::DelayMs` trait + // Use `embedded_hal_02::DelayMs` trait delay.delay_ms(1000_u32); led.set_low(); // or use `fugit` duration units diff --git a/examples/delay.rs b/examples/delay.rs index cf076431..ce83c661 100644 --- a/examples/delay.rs +++ b/examples/delay.rs @@ -36,7 +36,7 @@ fn main() -> ! { loop { led.set_high(); - // Use `embedded_hal::DelayMs` trait + // Use `embedded_hal_02::DelayMs` trait delay.delay_ms(1_000_u16); led.set_low(); // or use `fugit` duration units diff --git a/examples/dynamic_gpio.rs b/examples/dynamic_gpio.rs index b96a84ca..6aa93fc5 100644 --- a/examples/dynamic_gpio.rs +++ b/examples/dynamic_gpio.rs @@ -8,7 +8,7 @@ use nb::block; use cortex_m_rt::entry; use cortex_m_semihosting::hprintln; -use embedded_hal::digital::v2::{InputPin, OutputPin}; +use embedded_hal_02::digital::v2::{InputPin, OutputPin}; use stm32f1xx_hal::{pac, prelude::*}; #[entry] diff --git a/examples/mfrc522.rs b/examples/mfrc522.rs index 000fdc72..cdf8f75d 100644 --- a/examples/mfrc522.rs +++ b/examples/mfrc522.rs @@ -7,8 +7,8 @@ use panic_itm as _; use cortex_m::iprintln; use cortex_m_rt::entry; -use embedded_hal::digital::v1_compat::OldOutputPin; -use embedded_hal::spi::{Mode, Phase, Polarity}; +use embedded_hal_02::digital::v1_compat::OldOutputPin; +use embedded_hal_02::spi::{Mode, Phase, Polarity}; use mfrc522::Mfrc522; use stm32f1xx_hal::{pac, prelude::*, spi::Spi}; pub const MODE: Mode = Mode { diff --git a/examples/serial-interrupt-idle.rs b/examples/serial-interrupt-idle.rs index 41af5eef..c8e91811 100644 --- a/examples/serial-interrupt-idle.rs +++ b/examples/serial-interrupt-idle.rs @@ -45,7 +45,7 @@ fn main() -> ! { // Set up the usart device. Takes ownership over the USART register and tx/rx pins. The rest of // the registers are used to enable and configure the device. let (mut tx, mut rx) = - Serial::new(p.USART1, (tx, rx), &mut afio.mapr, 115200.bps(), &clocks).split(); + Serial::new(p.USART1, (tx, rx), &mut afio.mapr, 115_200.bps(), &clocks).split(); tx.listen(); rx.listen(); rx.listen_idle(); @@ -69,7 +69,7 @@ static mut WIDX: usize = 0; unsafe fn write(buf: &[u8]) { if let Some(tx) = TX.as_mut() { buf.iter() - .for_each(|w| if let Err(_err) = nb::block!(tx.write(*w)) {}) + .for_each(|w| if let Err(_err) = nb::block!(tx.write_u8(*w)) {}) } } #[interrupt] diff --git a/examples/serial.rs b/examples/serial.rs index 2cb32ecf..b94bc41f 100644 --- a/examples/serial.rs +++ b/examples/serial.rs @@ -19,7 +19,6 @@ use stm32f1xx_hal::{ prelude::*, serial::{Config, Serial}, }; -use unwrap_infallible::UnwrapInfallible; #[entry] fn main() -> ! { @@ -71,7 +70,7 @@ fn main() -> ! { // Loopback test. Write `X` and wait until the write is successful. let sent = b'X'; - block!(serial.tx.write(sent)).unwrap_infallible(); + block!(serial.tx.write_u8(sent)).unwrap(); // Read the byte that was just sent. Blocks until the read is complete let received = block!(serial.rx.read()).unwrap(); @@ -85,7 +84,7 @@ fn main() -> ! { // You can also split the serial struct into a receiving and a transmitting part let (mut tx, mut rx) = serial.split(); let sent = b'Y'; - block!(tx.write(sent)).unwrap_infallible(); + block!(tx.write_u8(sent)).unwrap(); let received = block!(rx.read()).unwrap(); assert_eq!(received, sent); asm::bkpt(); diff --git a/examples/serial_9bits.rs b/examples/serial_9bits.rs index 52161d39..2eebee2d 100644 --- a/examples/serial_9bits.rs +++ b/examples/serial_9bits.rs @@ -9,16 +9,14 @@ #![no_main] #![no_std] -use core::convert::Infallible; use cortex_m_rt::entry; use nb::block; use panic_halt as _; use stm32f1xx_hal::{ pac, prelude::*, - serial::{self, Config, Serial}, + serial::{self, Config, Error, Serial}, }; -use unwrap_infallible::UnwrapInfallible; // The address of the slave device. const SLAVE_ADDR: u8 = 123; @@ -29,7 +27,7 @@ const MSG_MAX_LEN: usize = u8::MAX as usize; // Receives a message addressed to the slave device. Returns the size of the received message. fn receive_msg(serial_rx: &mut RX, buf: &mut [u8; MSG_MAX_LEN]) -> usize where - RX: embedded_hal::serial::Read, + RX: embedded_hal_02::serial::Read, { enum RxPhase { Start, @@ -79,19 +77,19 @@ where // Send message. fn send_msg(serial_tx: &mut TX, msg: &[u8]) where - TX: embedded_hal::serial::Write - + embedded_hal::serial::Write, + TX: embedded_hal_02::serial::Write + + embedded_hal_02::serial::Write, { // Send address. - block!(serial_tx.write(SLAVE_ADDR as u16 | 0x100)).unwrap_infallible(); + block!(serial_tx.write(SLAVE_ADDR as u16 | 0x100)).unwrap(); // Send message len. assert!(msg.len() <= MSG_MAX_LEN); - block!(serial_tx.write(msg.len() as u8)).unwrap_infallible(); + block!(serial_tx.write(msg.len() as u8)).unwrap(); // Send message. for &b in msg { - block!(serial_tx.write(b)).unwrap_infallible(); + block!(serial_tx.write(b)).unwrap(); } } diff --git a/examples/serial_config.rs b/examples/serial_config.rs index 28326e2c..6c2f646f 100644 --- a/examples/serial_config.rs +++ b/examples/serial_config.rs @@ -17,7 +17,6 @@ use stm32f1xx_hal::{ prelude::*, serial::{self, Serial}, }; -use unwrap_infallible::UnwrapInfallible; #[entry] fn main() -> ! { @@ -75,8 +74,8 @@ fn main() -> ! { let (mut tx, _rx) = serial.split(); let sent = b'U'; - block!(tx.write(sent)).unwrap_infallible(); - block!(tx.write(sent)).unwrap_infallible(); + block!(tx.write_u8(sent)).unwrap(); + block!(tx.write_u8(sent)).unwrap(); loop {} } diff --git a/examples/serial_reconfigure.rs b/examples/serial_reconfigure.rs index 6405e432..c34ee900 100644 --- a/examples/serial_reconfigure.rs +++ b/examples/serial_reconfigure.rs @@ -19,7 +19,6 @@ use stm32f1xx_hal::{ prelude::*, serial::{self, Config, Serial}, }; -use unwrap_infallible::UnwrapInfallible; #[entry] fn main() -> ! { @@ -71,7 +70,7 @@ fn main() -> ! { // Loopback test. Write `X` and wait until the write is successful. let sent = b'X'; - block!(serial.tx.write(sent)).unwrap_infallible(); + block!(serial.tx.write_u8(sent)).unwrap(); // Read the byte that was just sent. Blocks until the read is complete let received = block!(serial.rx.read()).unwrap(); @@ -88,7 +87,7 @@ fn main() -> ! { // Let's see if it works.' let sent = b'Y'; - block!(serial.tx.write(sent)).unwrap_infallible(); + block!(serial.tx.write_u8(sent)).unwrap(); let received = block!(serial.rx.read()).unwrap(); assert_eq!(received, sent); asm::bkpt(); diff --git a/examples/spi-slave.rs b/examples/spi-slave.rs index 8e8743c9..ea68890f 100644 --- a/examples/spi-slave.rs +++ b/examples/spi-slave.rs @@ -13,7 +13,7 @@ use cortex_m_rt::entry; use panic_halt as _; use cortex_m::{asm, singleton}; -use embedded_hal::spi::{Mode, Phase, Polarity}; +use stm32f1xx_hal::spi::{Mode, Phase, Polarity}; pub const MODE: Mode = Mode { phase: Phase::CaptureOnSecondTransition, polarity: Polarity::IdleHigh, diff --git a/examples/spi.rs b/examples/spi.rs index e5335181..0bf0d524 100644 --- a/examples/spi.rs +++ b/examples/spi.rs @@ -6,7 +6,7 @@ use cortex_m_rt::entry; use panic_halt as _; -use embedded_hal::spi::{Mode, Phase, Polarity}; +use embedded_hal_02::spi::{Mode, Phase, Polarity}; pub const MODE: Mode = Mode { phase: Phase::CaptureOnSecondTransition, polarity: Polarity::IdleHigh, diff --git a/src/adc.rs b/src/adc.rs index 8facceb1..d86292ad 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,7 +1,7 @@ //! # API for the Analog to Digital converter use core::marker::PhantomData; -use embedded_hal::adc::{Channel, OneShot}; +use embedded_hal_02::adc::{Channel, OneShot}; #[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl",),))] use crate::dma::dma2; @@ -101,7 +101,7 @@ impl From for bool { } macro_rules! adc_pins { - ($ADC:ty, $($pin:ty => $chan:expr),+ $(,)*) => { + ($ADC:ty, $($pin:ty => $chan:literal),+ $(,)*) => { $( impl Channel<$ADC> for $pin { type ID = u8; @@ -113,59 +113,59 @@ macro_rules! adc_pins { } adc_pins!(pac::ADC1, - gpio::PA0 => 0_u8, - gpio::PA1 => 1_u8, - gpio::PA2 => 2_u8, - gpio::PA3 => 3_u8, - gpio::PA4 => 4_u8, - gpio::PA5 => 5_u8, - gpio::PA6 => 6_u8, - gpio::PA7 => 7_u8, - gpio::PB0 => 8_u8, - gpio::PB1 => 9_u8, - gpio::PC0 => 10_u8, - gpio::PC1 => 11_u8, - gpio::PC2 => 12_u8, - gpio::PC3 => 13_u8, - gpio::PC4 => 14_u8, - gpio::PC5 => 15_u8, + gpio::PA0 => 0, + gpio::PA1 => 1, + gpio::PA2 => 2, + gpio::PA3 => 3, + gpio::PA4 => 4, + gpio::PA5 => 5, + gpio::PA6 => 6, + gpio::PA7 => 7, + gpio::PB0 => 8, + gpio::PB1 => 9, + gpio::PC0 => 10, + gpio::PC1 => 11, + gpio::PC2 => 12, + gpio::PC3 => 13, + gpio::PC4 => 14, + gpio::PC5 => 15, ); #[cfg(any(feature = "stm32f103", feature = "connectivity"))] adc_pins!(pac::ADC2, - gpio::PA0 => 0_u8, - gpio::PA1 => 1_u8, - gpio::PA2 => 2_u8, - gpio::PA3 => 3_u8, - gpio::PA4 => 4_u8, - gpio::PA5 => 5_u8, - gpio::PA6 => 6_u8, - gpio::PA7 => 7_u8, - gpio::PB0 => 8_u8, - gpio::PB1 => 9_u8, - gpio::PC0 => 10_u8, - gpio::PC1 => 11_u8, - gpio::PC2 => 12_u8, - gpio::PC3 => 13_u8, - gpio::PC4 => 14_u8, - gpio::PC5 => 15_u8, + gpio::PA0 => 0, + gpio::PA1 => 1, + gpio::PA2 => 2, + gpio::PA3 => 3, + gpio::PA4 => 4, + gpio::PA5 => 5, + gpio::PA6 => 6, + gpio::PA7 => 7, + gpio::PB0 => 8, + gpio::PB1 => 9, + gpio::PC0 => 10, + gpio::PC1 => 11, + gpio::PC2 => 12, + gpio::PC3 => 13, + gpio::PC4 => 14, + gpio::PC5 => 15, ); #[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl",),))] adc_pins!(pac::ADC3, - gpio::PA0 => 0_u8, - gpio::PA1 => 1_u8, - gpio::PA2 => 2_u8, - gpio::PA3 => 3_u8, - gpio::PF6 => 4_u8, - gpio::PF7 => 5_u8, - gpio::PF8 => 6_u8, - gpio::PF9 => 7_u8, - gpio::PF10 => 8_u8, - gpio::PC0 => 10_u8, - gpio::PC1 => 11_u8, - gpio::PC2 => 12_u8, - gpio::PC3 => 13_u8, + gpio::PA0 => 0, + gpio::PA1 => 1, + gpio::PA2 => 2, + gpio::PA3 => 3, + gpio::PF6 => 4, + gpio::PF7 => 5, + gpio::PF8 => 6, + gpio::PF9 => 7, + gpio::PF10 => 8, + gpio::PC0 => 10, + gpio::PC1 => 11, + gpio::PC2 => 12, + gpio::PC3 => 13, ); /// Stored ADC config can be restored using the `Adc::restore_cfg` method diff --git a/src/gpio.rs b/src/gpio.rs index 60535459..4a4a5d5c 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -77,7 +77,6 @@ use core::convert::Infallible; use core::marker::PhantomData; use crate::afio; -use crate::hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin}; use crate::pac::EXTI; mod partially_erased; @@ -85,6 +84,9 @@ pub use partially_erased::{PEPin, PartiallyErasedPin}; mod erased; pub use erased::{EPin, ErasedPin}; +mod hal_02; +mod hal_1; + /// Slew rates available for Output and relevant AlternateMode Pins /// /// See Table 21 "Output MODE bits" in the reference @@ -189,11 +191,7 @@ pub struct Alternate { impl Active for Alternate {} /// Digital output pin state -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum PinState { - High, - Low, -} +pub use embedded_hal_02::digital::v2::PinState; // Using SCREAMING_SNAKE_CASE to be consistent with other HALs // see 59b2740 and #125 for motivation @@ -392,8 +390,8 @@ macro_rules! gpio { $GPIOX::reset(rcc); Parts { - crl: Cr::<$port_id, false>(()), - crh: Cr::<$port_id, true>(()), + crl: Cr::<$port_id, false>, + crh: Cr::<$port_id, true>, $( $pxi: $PXi::new(), )+ @@ -405,8 +403,8 @@ macro_rules! gpio { $GPIOX::enable(rcc); Parts { - crl: Cr::<$port_id, false>(()), - crh: Cr::<$port_id, true>(()), + crl: Cr::<$port_id, false>, + crh: Cr::<$port_id, true>, $( $pxi: $PXi::new(), )+ @@ -502,44 +500,6 @@ impl Pin { } } -impl OutputPin for Pin { - type Error = PinModeError; - - fn set_high(&mut self) -> Result<(), Self::Error> { - if self.mode.is_output() { - self._set_high(); - Ok(()) - } else { - Err(PinModeError::IncorrectMode) - } - } - - fn set_low(&mut self) -> Result<(), Self::Error> { - if self.mode.is_output() { - self._set_low(); - Ok(()) - } else { - Err(PinModeError::IncorrectMode) - } - } -} - -impl InputPin for Pin { - type Error = PinModeError; - - fn is_high(&self) -> Result { - self.is_low().map(|b| !b) - } - - fn is_low(&self) -> Result { - if self.mode.is_input() { - Ok(self._is_low()) - } else { - Err(PinModeError::IncorrectMode) - } - } -} - // Internal helper functions // NOTE: The functions in this impl block are "safe", but they @@ -642,44 +602,6 @@ impl Pin> { } } -impl OutputPin for Pin> { - type Error = Infallible; - - #[inline] - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_high(); - Ok(()) - } - - #[inline] - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_low(); - Ok(()) - } -} - -impl StatefulOutputPin for Pin> { - #[inline] - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - - #[inline] - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - -impl ToggleableOutputPin for Pin> { - type Error = Infallible; - - #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - impl Pin> { #[inline] pub fn is_high(&self) -> bool { @@ -692,20 +614,6 @@ impl Pin> { } } -impl InputPin for Pin> { - type Error = Infallible; - - #[inline] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - impl Pin> { #[inline] pub fn is_high(&self) -> bool { @@ -718,22 +626,9 @@ impl Pin> { } } -impl InputPin for Pin> { - type Error = Infallible; - - #[inline] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - /// Opaque CR register -pub struct Cr(()); +#[non_exhaustive] +pub struct Cr; impl Pin where diff --git a/src/gpio/erased.rs b/src/gpio/erased.rs index 4cd0583f..7b38079c 100644 --- a/src/gpio/erased.rs +++ b/src/gpio/erased.rs @@ -115,54 +115,6 @@ impl ErasedPin> { } } -impl OutputPin for ErasedPin> { - type Error = Infallible; - - fn set_high(&mut self) -> Result<(), Infallible> { - self.set_high(); - Ok(()) - } - - fn set_low(&mut self) -> Result<(), Infallible> { - self.set_low(); - Ok(()) - } -} - -impl StatefulOutputPin for ErasedPin> { - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - -impl InputPin for ErasedPin> { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - -impl InputPin for ErasedPin> { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - #[cfg(not(any(feature = "xl", feature = "high")))] impl_pxx! { ('A'::PAx), diff --git a/src/gpio/hal_02.rs b/src/gpio/hal_02.rs new file mode 100644 index 00000000..54baa8ab --- /dev/null +++ b/src/gpio/hal_02.rs @@ -0,0 +1,214 @@ +use super::*; +use embedded_hal_02::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin}; + +// Pin + +impl OutputPin for Pin { + type Error = PinModeError; + fn set_high(&mut self) -> Result<(), Self::Error> { + if self.mode.is_output() { + self._set_state(PinState::High); + Ok(()) + } else { + Err(PinModeError::IncorrectMode) + } + } + fn set_low(&mut self) -> Result<(), Self::Error> { + if self.mode.is_output() { + self._set_state(PinState::Low); + Ok(()) + } else { + Err(PinModeError::IncorrectMode) + } + } +} + +impl InputPin for Pin { + type Error = PinModeError; + fn is_high(&self) -> Result { + self.is_low().map(|b| !b) + } + fn is_low(&self) -> Result { + if self.mode.is_input() { + Ok(self._is_low()) + } else { + Err(PinModeError::IncorrectMode) + } + } +} + +impl OutputPin for Pin> { + type Error = Infallible; + #[inline] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + #[inline] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for Pin> { + #[inline] + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + #[inline] + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } +} + +impl ToggleableOutputPin for Pin> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for Pin> { + type Error = Infallible; + #[inline] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +impl InputPin for Pin> { + type Error = Infallible; + #[inline] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +// PartiallyErasedPin + +impl OutputPin for PartiallyErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + + #[inline(always)] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for PartiallyErasedPin> { + #[inline(always)] + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + #[inline(always)] + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } +} + +impl ToggleableOutputPin for PartiallyErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for PartiallyErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline(always)] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +impl InputPin for PartiallyErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline(always)] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +// ErasedPin + +impl OutputPin for ErasedPin> { + type Error = Infallible; + fn set_high(&mut self) -> Result<(), Infallible> { + self.set_high(); + Ok(()) + } + + fn set_low(&mut self) -> Result<(), Infallible> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for ErasedPin> { + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } +} + +impl InputPin for ErasedPin> { + type Error = Infallible; + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +impl InputPin for ErasedPin> { + type Error = Infallible; + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} diff --git a/src/gpio/hal_1.rs b/src/gpio/hal_1.rs new file mode 100644 index 00000000..a3d4bc40 --- /dev/null +++ b/src/gpio/hal_1.rs @@ -0,0 +1,217 @@ +use core::convert::Infallible; + +use super::{Dynamic, ErasedPin, Input, OpenDrain, Output, PartiallyErasedPin, Pin, PinModeError}; + +pub use embedded_hal::digital::PinState; +use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin}; + +fn into_state(state: PinState) -> super::PinState { + match state { + PinState::Low => super::PinState::Low, + PinState::High => super::PinState::High, + } +} + +// Implementations for `Pin` +impl ErrorType for Pin> { + type Error = Infallible; +} +impl ErrorType for Pin> { + type Error = Infallible; +} + +impl embedded_hal::digital::Error for PinModeError { + fn kind(&self) -> embedded_hal::digital::ErrorKind { + match self { + PinModeError::IncorrectMode => embedded_hal::digital::ErrorKind::Other, + } + } +} + +impl ErrorType for Pin { + type Error = PinModeError; +} + +impl OutputPin for Pin { + fn set_high(&mut self) -> Result<(), Self::Error> { + if self.mode.is_output() { + self._set_state(into_state(PinState::High)); + Ok(()) + } else { + Err(PinModeError::IncorrectMode) + } + } + fn set_low(&mut self) -> Result<(), Self::Error> { + if self.mode.is_output() { + self._set_state(into_state(PinState::Low)); + Ok(()) + } else { + Err(PinModeError::IncorrectMode) + } + } +} + +impl InputPin for Pin { + fn is_high(&mut self) -> Result { + self.is_low().map(|b| !b) + } + fn is_low(&mut self) -> Result { + if self.mode.is_input() { + Ok(self._is_low()) + } else { + Err(PinModeError::IncorrectMode) + } + } +} + +impl OutputPin for Pin> { + #[inline] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + #[inline] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for Pin> { + #[inline] + fn is_set_high(&mut self) -> Result { + Ok((*self).is_set_high()) + } + #[inline] + fn is_set_low(&mut self) -> Result { + Ok((*self).is_set_low()) + } +} + +impl InputPin for Pin> { + #[inline] + fn is_high(&mut self) -> Result { + Ok((*self).is_high()) + } + + #[inline] + fn is_low(&mut self) -> Result { + Ok((*self).is_low()) + } +} + +impl InputPin for Pin> { + #[inline] + fn is_high(&mut self) -> Result { + Ok((*self).is_high()) + } + + #[inline] + fn is_low(&mut self) -> Result { + Ok((*self).is_low()) + } +} + +// PartiallyErasedPin + +impl ErrorType for PartiallyErasedPin { + type Error = Infallible; +} + +impl OutputPin for PartiallyErasedPin> { + #[inline(always)] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_high(); + Ok(()) + } + + #[inline(always)] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for PartiallyErasedPin> { + #[inline(always)] + fn is_set_high(&mut self) -> Result { + Ok((*self).is_set_high()) + } + + #[inline(always)] + fn is_set_low(&mut self) -> Result { + Ok((*self).is_set_low()) + } +} + +impl InputPin for PartiallyErasedPin> { + #[inline(always)] + fn is_high(&mut self) -> Result { + Ok((*self).is_high()) + } + + #[inline(always)] + fn is_low(&mut self) -> Result { + Ok((*self).is_low()) + } +} + +impl InputPin for PartiallyErasedPin> { + #[inline(always)] + fn is_high(&mut self) -> Result { + Ok((*self).is_high()) + } + + #[inline(always)] + fn is_low(&mut self) -> Result { + Ok((*self).is_low()) + } +} + +// ErasedPin + +impl ErrorType for ErasedPin { + type Error = core::convert::Infallible; +} + +impl OutputPin for ErasedPin> { + fn set_high(&mut self) -> Result<(), Infallible> { + self.set_high(); + Ok(()) + } + + fn set_low(&mut self) -> Result<(), Infallible> { + self.set_low(); + Ok(()) + } +} + +impl StatefulOutputPin for ErasedPin> { + fn is_set_high(&mut self) -> Result { + Ok((*self).is_set_high()) + } + + fn is_set_low(&mut self) -> Result { + Ok((*self).is_set_low()) + } +} + +impl InputPin for ErasedPin> { + fn is_high(&mut self) -> Result { + Ok((*self).is_high()) + } + + fn is_low(&mut self) -> Result { + Ok((*self).is_low()) + } +} + +impl InputPin for ErasedPin> { + fn is_high(&mut self) -> Result { + Ok((*self).is_high()) + } + + fn is_low(&mut self) -> Result { + Ok((*self).is_low()) + } +} diff --git a/src/gpio/partially_erased.rs b/src/gpio/partially_erased.rs index d113539e..094413db 100644 --- a/src/gpio/partially_erased.rs +++ b/src/gpio/partially_erased.rs @@ -93,44 +93,6 @@ impl PartiallyErasedPin> { } } -impl OutputPin for PartiallyErasedPin> { - type Error = Infallible; - - #[inline(always)] - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_high(); - Ok(()) - } - - #[inline(always)] - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_low(); - Ok(()) - } -} - -impl StatefulOutputPin for PartiallyErasedPin> { - #[inline(always)] - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - - #[inline(always)] - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - -impl ToggleableOutputPin for PartiallyErasedPin> { - type Error = Infallible; - - #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - impl PartiallyErasedPin> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -144,20 +106,6 @@ impl PartiallyErasedPin> { } } -impl InputPin for PartiallyErasedPin> { - type Error = Infallible; - - #[inline(always)] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline(always)] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - impl PartiallyErasedPin> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -170,17 +118,3 @@ impl PartiallyErasedPin> { unsafe { (*Gpio::

::ptr()).idr.read().bits() & (1 << self.pin_number) == 0 } } } - -impl InputPin for PartiallyErasedPin> { - type Error = Infallible; - - #[inline(always)] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline(always)] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} diff --git a/src/i2c.rs b/src/i2c.rs index cea6f079..54c5f8a2 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -6,7 +6,6 @@ use crate::afio::MAPR; use crate::gpio::{self, Alternate, OpenDrain}; -use crate::hal::blocking::i2c::{Read, Write, WriteRead}; use crate::pac::{DWT, I2C1, I2C2, RCC}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::{kHz, Hertz}; @@ -15,6 +14,11 @@ use core::ops::Deref; pub mod blocking; pub use blocking::BlockingI2c; +mod hal_02; +mod hal_1; + +pub use embedded_hal::i2c::NoAcknowledgeSource; + /// I2C error #[derive(Debug, Eq, PartialEq)] #[non_exhaustive] @@ -22,9 +26,9 @@ pub enum Error { /// Bus error Bus, /// Arbitration loss - Arbitration, + ArbitrationLoss, /// No ack received - Acknowledge, + NoAcknowledge(NoAcknowledgeSource), /// Overrun/underrun Overrun, // Pec, // SMBUS mode only @@ -255,9 +259,4 @@ where pub fn release(self) -> (I2C, PINS) { (self.i2c, self.pins) } - - #[deprecated(since = "0.7.1", note = "Please use release instead")] - pub fn free(self) -> (I2C, PINS) { - self.release() - } } diff --git a/src/i2c/blocking.rs b/src/i2c/blocking.rs index bd366b09..0dac4245 100644 --- a/src/i2c/blocking.rs +++ b/src/i2c/blocking.rs @@ -113,7 +113,7 @@ impl I2c { } macro_rules! wait_for_flag { - ($i2c:expr, $flag:ident) => {{ + ($i2c:expr, $flag:ident, $nack:ident) => {{ let sr1 = $i2c.sr1.read(); if sr1.berr().bit_is_set() { @@ -121,10 +121,10 @@ macro_rules! wait_for_flag { Err(Error::Bus.into()) } else if sr1.arlo().bit_is_set() { $i2c.sr1.write(|w| w.arlo().clear_bit()); - Err(Error::Arbitration.into()) + Err(Error::ArbitrationLoss.into()) } else if sr1.af().bit_is_set() { $i2c.sr1.write(|w| w.af().clear_bit()); - Err(Error::Acknowledge.into()) + Err(Error::NoAcknowledge(NoAcknowledgeSource::$nack).into()) } else if sr1.ovr().bit_is_set() { $i2c.sr1.write(|w| w.ovr().clear_bit()); Err(Error::Overrun.into()) @@ -163,10 +163,7 @@ macro_rules! busy_wait_cycles { }}; } -impl BlockingI2c -where - I2C: Instance, -{ +impl BlockingI2c { #[allow(clippy::too_many_arguments)] fn configure>( i2c: I2C, @@ -188,15 +185,12 @@ where } } -impl BlockingI2c -where - I2C: Instance, -{ +impl BlockingI2c { /// Check if START condition is generated. If the condition is not generated, this /// method returns `WouldBlock` so the program can act accordingly /// (busy wait, async, ...) fn wait_after_sent_start(&mut self) -> nb::Result<(), Error> { - wait_for_flag!(self.nb.i2c, sb) + wait_for_flag!(self.nb.i2c, sb, Unknown) } /// Check if STOP condition is generated. If the condition is not generated, this @@ -231,8 +225,11 @@ where fn send_addr_and_wait(&mut self, addr: u8, read: bool) -> Result<(), Error> { self.nb.i2c.sr1.read(); self.nb.send_addr(addr, read); - let ret = busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.timeouts.addr); - if ret == Err(Error::Acknowledge) { + let ret = busy_wait_cycles!( + wait_for_flag!(self.nb.i2c, addr, Address), + self.timeouts.addr + ); + if let Err(Error::NoAcknowledge(_)) = ret { self.nb.send_stop(); } ret @@ -245,10 +242,10 @@ where self.nb.i2c.dr.write(|w| w.dr().bits(bytes[0])); for byte in &bytes[1..] { - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, tx_e), self.timeouts.data)?; + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, tx_e, Data), self.timeouts.data)?; self.nb.i2c.dr.write(|w| w.dr().bits(*byte)); } - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.timeouts.data)?; + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf, Data), self.timeouts.data)?; Ok(()) } @@ -258,35 +255,21 @@ where self.send_addr_and_wait(addr, false)?; let ret = self.write_bytes_and_wait(bytes); - if ret == Err(Error::Acknowledge) { + if let Err(Error::NoAcknowledge(_)) = ret { self.nb.send_stop(); } ret } -} - -impl Write for BlockingI2c -where - I2C: Instance, -{ - type Error = Error; - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { self.write_without_stop(addr, bytes)?; self.nb.send_stop(); busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?; Ok(()) } -} -impl Read for BlockingI2c -where - I2C: Instance, -{ - type Error = Error; - - fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + pub fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { self.send_start_and_wait()?; self.send_addr_and_wait(addr, true)?; @@ -297,7 +280,7 @@ where self.nb.i2c.sr2.read(); self.nb.send_stop(); - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.timeouts.data)?; + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne, Data), self.timeouts.data)?; buffer[0] = self.nb.i2c.dr.read().dr().bits(); busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?; @@ -312,7 +295,7 @@ where self.nb.i2c.sr2.read(); self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.timeouts.data)?; + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf, Data), self.timeouts.data)?; self.nb.send_stop(); buffer[0] = self.nb.i2c.dr.read().dr().bits(); buffer[1] = self.nb.i2c.dr.read().dr().bits(); @@ -331,16 +314,19 @@ where let (first_bytes, last_two_bytes) = buffer.split_at_mut(buffer_len - 3); for byte in first_bytes { - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.timeouts.data)?; + busy_wait_cycles!( + wait_for_flag!(self.nb.i2c, rx_ne, Data), + self.timeouts.data + )?; *byte = self.nb.i2c.dr.read().dr().bits(); } - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.timeouts.data)?; + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf, Data), self.timeouts.data)?; self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); last_two_bytes[0] = self.nb.i2c.dr.read().dr().bits(); self.nb.send_stop(); last_two_bytes[1] = self.nb.i2c.dr.read().dr().bits(); - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.timeouts.data)?; + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne, Data), self.timeouts.data)?; last_two_bytes[2] = self.nb.i2c.dr.read().dr().bits(); busy_wait_cycles!(self.wait_for_stop(), self.timeouts.data)?; @@ -350,15 +336,8 @@ where Ok(()) } -} -impl WriteRead for BlockingI2c -where - I2C: Instance, -{ - type Error = Error; - - fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { + pub fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { if !bytes.is_empty() { self.write_without_stop(addr, bytes)?; } @@ -372,4 +351,20 @@ where Ok(()) } + + pub fn transaction_slice( + &mut self, + _addr: u8, + _ops_slice: &mut [embedded_hal::i2c::Operation<'_>], + ) -> Result<(), Error> { + todo!(); + } + + pub(crate) fn transaction_slice_hal_02( + &mut self, + _addr: u8, + _ops_slice: &mut [embedded_hal_02::blocking::i2c::Operation<'_>], + ) -> Result<(), Error> { + todo!(); + } } diff --git a/src/i2c/hal_02.rs b/src/i2c/hal_02.rs new file mode 100644 index 00000000..ca4b67df --- /dev/null +++ b/src/i2c/hal_02.rs @@ -0,0 +1,37 @@ +use super::*; +use embedded_hal_02::blocking::i2c::{Operation, Read, Transactional, Write, WriteRead}; + +impl Write for BlockingI2c { + type Error = Error; + + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(addr, bytes) + } +} + +impl Read for BlockingI2c { + type Error = Error; + + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.read(addr, buffer) + } +} + +impl WriteRead for BlockingI2c { + type Error = Error; + + fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { + self.write_read(addr, bytes, buffer) + } +} + +impl Transactional for BlockingI2c +where + I2C: Instance, +{ + type Error = Error; + + fn exec(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> { + self.transaction_slice_hal_02(address, operations) + } +} diff --git a/src/i2c/hal_1.rs b/src/i2c/hal_1.rs new file mode 100644 index 00000000..9cfa2ade --- /dev/null +++ b/src/i2c/hal_1.rs @@ -0,0 +1,49 @@ +use embedded_hal::i2c::{Error, ErrorKind, ErrorType}; + +impl Error for super::Error { + fn kind(&self) -> ErrorKind { + match *self { + Self::Overrun => ErrorKind::Overrun, + Self::Bus => ErrorKind::Bus, + Self::ArbitrationLoss => ErrorKind::ArbitrationLoss, + Self::NoAcknowledge(nack) => ErrorKind::NoAcknowledge(nack), + Self::Timeout => ErrorKind::Other, + } + } +} + +impl ErrorType for super::BlockingI2c { + type Error = super::Error; +} + +mod blocking { + use super::super::{BlockingI2c, Instance}; + use embedded_hal::i2c::Operation; + + impl embedded_hal::i2c::I2c for BlockingI2c { + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.read(addr, buffer) + } + + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(addr, bytes) + } + + fn write_read( + &mut self, + addr: u8, + bytes: &[u8], + buffer: &mut [u8], + ) -> Result<(), Self::Error> { + self.write_read(addr, bytes, buffer) + } + + fn transaction( + &mut self, + addr: u8, + operations: &mut [Operation<'_>], + ) -> Result<(), Self::Error> { + self.transaction_slice(addr, operations) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 2997c027..9b88c853 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,7 +114,9 @@ compile_error!( ); #[cfg(feature = "device-selected")] -use embedded_hal as hal; +pub use embedded_hal as hal; +#[cfg(feature = "device-selected")] +pub use embedded_hal_02 as hal_02; #[cfg(feature = "stm32f100")] pub use stm32f1::stm32f100 as pac; @@ -128,16 +130,6 @@ pub use stm32f1::stm32f103 as pac; #[cfg(any(feature = "stm32f105", feature = "stm32f107"))] pub use stm32f1::stm32f107 as pac; -#[cfg(feature = "device-selected")] -#[deprecated(since = "0.6.0", note = "please use `pac` instead")] -#[doc(hidden)] -pub use crate::pac as device; - -#[cfg(feature = "device-selected")] -#[deprecated(since = "0.6.0", note = "please use `pac` instead")] -#[doc(hidden)] -pub use crate::pac as stm32; - #[cfg(feature = "device-selected")] pub mod adc; #[cfg(feature = "device-selected")] diff --git a/src/prelude.rs b/src/prelude.rs index 0bde3d4a..c5a3a523 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -8,10 +8,8 @@ pub use crate::dma::ReadWriteDma as _stm32_hal_dma_ReadWriteDma; pub use crate::dma::WriteDma as _stm32_hal_dma_WriteDma; 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::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::hal_02::adc::OneShot as _embedded_hal_adc_OneShot; +pub use crate::hal_02::prelude::*; pub use crate::rcc::RccExt as _stm32_hal_rcc_RccExt; pub use crate::time::U32Ext as _stm32_hal_time_U32Ext; #[cfg(feature = "rtic")] diff --git a/src/qei.rs b/src/qei.rs index b7fc2c57..85ca7a5d 100644 --- a/src/qei.rs +++ b/src/qei.rs @@ -8,13 +8,13 @@ use core::u16; use core::marker::PhantomData; -use crate::hal; -pub use crate::hal::Direction; #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity",))] use crate::pac::TIM1; #[cfg(feature = "medium")] use crate::pac::TIM4; use crate::pac::{TIM2, TIM3}; +use embedded_hal_02 as hal; +pub use hal::Direction; use crate::afio::MAPR; diff --git a/src/serial.rs b/src/serial.rs index 0758ba07..9647fb0b 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -49,10 +49,10 @@ //! //! // Write data (9 bits) to the USART. //! // Depending on the configuration, only the lower 7, 8, or 9 bits are used. -//! block!(tx.write_u16(0x1FF)).unwrap_infallible(); +//! block!(tx.write_u16(0x1FF)).unwrap(); //! //! // Write 'R' (8 bits) to the USART -//! block!(tx.write(b'R')).unwrap_infallible(); +//! block!(tx.write_u8(b'R')).unwrap(); //! //! // Receive a data (9 bits) from the USART and store it in "received" //! let received = block!(rx.read_u16()).unwrap(); @@ -61,7 +61,6 @@ //! let received = block!(rx.read()).unwrap(); //! ``` -use core::convert::Infallible; use core::marker::PhantomData; use core::ops::Deref; use core::sync::atomic::{self, Ordering}; @@ -74,6 +73,9 @@ use crate::pac::{RCC, USART1, USART2, USART3}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::{Bps, U32Ext}; +mod hal_02; +mod hal_1; + // USART REMAPPING, see: https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf // Section 9.3.8 pub trait Pins { @@ -131,18 +133,25 @@ inst! { USART3 } -/// Serial error -#[derive(Debug)] +/// Serial error kind +/// +/// This represents a common set of serial operation errors. HAL implementations are +/// free to define more specific or additional error types. However, by providing +/// a mapping to these common serial errors, generic code can still react to them. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[non_exhaustive] pub enum Error { - /// Framing error - Framing, - /// Noise error - Noise, - /// RX buffer overrun + /// The peripheral receive buffer was overrun. Overrun, - /// Parity check error + /// Received data does not conform to the peripheral configuration. + /// Can be caused by a misconfigured device on either end of the serial line. + FrameFormat, + /// Parity check failed. Parity, + /// Serial line is too noisy to read valid data. + Noise, + /// A different error occurred. The original error may contain more information. + Other, } pub enum WordLength { @@ -329,7 +338,7 @@ impl Serial { &mut self, config: impl Into, clocks: &Clocks, - ) -> nb::Result<(), Infallible> { + ) -> nb::Result<(), Error> { reconfigure(&mut self.tx, &mut self.rx, config, clocks) } @@ -411,7 +420,7 @@ pub fn reconfigure( #[allow(unused_variables)] rx: &mut Rx, config: impl Into, clocks: &Clocks, -) -> nb::Result<(), Infallible> { +) -> nb::Result<(), Error> { // if we're currently busy transmitting, we have to wait until that is // over -- regarding reception, we assume that the caller -- with // exclusive access to the Serial instance due to &mut self -- knows @@ -427,7 +436,7 @@ impl Tx { /// If the UART/USART was configured with `WordLength::Bits9`, the 9 least significant bits will /// be transmitted and the other 7 bits will be ignored. Otherwise, the 8 least significant bits /// will be transmitted and the other 8 bits will be ignored. - pub fn write_u16(&mut self, word: u16) -> nb::Result<(), Infallible> { + pub fn write_u16(&mut self, word: u16) -> nb::Result<(), Error> { let usart = unsafe { &*USART::ptr() }; if usart.sr.read().txe().bit_is_set() { @@ -438,25 +447,25 @@ impl Tx { } } - pub fn write(&mut self, word: u8) -> nb::Result<(), Infallible> { + pub fn write_u8(&mut self, word: u8) -> nb::Result<(), Error> { self.write_u16(word as u16) } - pub fn bwrite_all_u16(&mut self, buffer: &[u16]) -> Result<(), Infallible> { + pub fn bwrite_all_u16(&mut self, buffer: &[u16]) -> Result<(), Error> { for &w in buffer { nb::block!(self.write_u16(w))?; } Ok(()) } - pub fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Infallible> { + pub fn bwrite_all_u8(&mut self, buffer: &[u8]) -> Result<(), Error> { for &w in buffer { - nb::block!(self.write(w))?; + nb::block!(self.write_u8(w))?; } Ok(()) } - pub fn flush(&mut self) -> nb::Result<(), Infallible> { + pub fn flush(&mut self) -> nb::Result<(), Error> { let usart = unsafe { &*USART::ptr() }; if usart.sr.read().tc().bit_is_set() { @@ -466,7 +475,7 @@ impl Tx { } } - pub fn bflush(&mut self) -> Result<(), Infallible> { + pub fn bflush(&mut self) -> Result<(), Error> { nb::block!(self.flush()) } @@ -490,58 +499,10 @@ impl Tx { } } -impl embedded_hal::serial::Write for Tx { - type Error = Infallible; - - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { - self.write(word) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.flush() - } -} - -impl embedded_hal::serial::Write for Tx { - type Error = Infallible; - - fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { - self.write_u16(word) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.flush() - } -} - -impl embedded_hal::blocking::serial::Write for Tx { - type Error = Infallible; - - fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { - self.bwrite_all(buffer) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.bflush() - } -} - -impl embedded_hal::blocking::serial::Write for Tx { - type Error = Infallible; - - fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Self::Error> { - self.bwrite_all_u16(buffer) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.bflush() - } -} - impl core::fmt::Write for Tx { fn write_str(&mut self, s: &str) -> core::fmt::Result { s.bytes() - .try_for_each(|c| nb::block!(self.write(c))) + .try_for_each(|c| nb::block!(self.write_u8(c))) .map_err(|_| core::fmt::Error) } } @@ -560,7 +521,7 @@ impl Rx { let err = if sr.pe().bit_is_set() { Some(Error::Parity) } else if sr.fe().bit_is_set() { - Some(Error::Framing) + Some(Error::FrameFormat) } else if sr.ne().bit_is_set() { Some(Error::Noise) } else if sr.ore().bit_is_set() { @@ -629,22 +590,6 @@ impl Rx { } } -impl embedded_hal::serial::Read for Rx { - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.read() - } -} - -impl embedded_hal::serial::Read for Rx { - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.read_u16() - } -} - /// Interrupt event pub enum Event { /// New data can be sent @@ -699,76 +644,12 @@ impl Serial { } } -impl embedded_hal::serial::Write for Serial { - type Error = Infallible; - - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { - self.tx.write(word) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.tx.flush() - } -} - -impl embedded_hal::serial::Write for Serial { - type Error = Infallible; - - fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { - self.tx.write_u16(word) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.tx.flush() - } -} - -impl embedded_hal::blocking::serial::Write for Serial { - type Error = Infallible; - - fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { - self.tx.bwrite_all(buffer) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.tx.bflush() - } -} - -impl embedded_hal::blocking::serial::Write for Serial { - type Error = Infallible; - - fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Self::Error> { - self.tx.bwrite_all_u16(buffer) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.tx.bflush() - } -} - impl core::fmt::Write for Serial { fn write_str(&mut self, s: &str) -> core::fmt::Result { self.tx.write_str(s) } } -impl embedded_hal::serial::Read for Serial { - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.rx.read() - } -} - -impl embedded_hal::serial::Read for Serial { - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.rx.read_u16() - } -} - pub type Rx1 = Rx; pub type Tx1 = Tx; pub type Rx2 = Rx; @@ -840,10 +721,6 @@ macro_rules! serialdma { } impl $rxdma { - #[deprecated(since = "0.7.1", note = "Please use release instead")] - pub fn split(self) -> (Rx<$USARTX>, $dmarxch) { - self.release() - } pub fn release(mut self) -> (Rx<$USARTX>, $dmarxch) { self.stop(); unsafe { (*$USARTX::ptr()).cr3.modify(|_, w| w.dmar().clear_bit()); } @@ -856,10 +733,6 @@ macro_rules! serialdma { } impl $txdma { - #[deprecated(since = "0.7.1", note = "Please use release instead")] - pub fn split(self) -> (Tx<$USARTX>, $dmatxch) { - self.release() - } pub fn release(mut self) -> (Tx<$USARTX>, $dmatxch) { self.stop(); unsafe { (*$USARTX::ptr()).cr3.modify(|_, w| w.dmat().clear_bit()); } diff --git a/src/serial/hal_02.rs b/src/serial/hal_02.rs new file mode 100644 index 00000000..fe766849 --- /dev/null +++ b/src/serial/hal_02.rs @@ -0,0 +1,132 @@ +use super::*; +use embedded_hal_02::{blocking::serial as blocking, serial}; + +impl serial::Write for Tx { + type Error = Error; + + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + self.write_u8(word) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.flush() + } +} + +impl serial::Write for Tx { + type Error = Error; + + fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { + self.write_u16(word) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.flush() + } +} + +impl serial::Read for Rx { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.read() + } +} + +impl serial::Read for Rx { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.read_u16() + } +} + +impl serial::Write for Serial { + type Error = Error; + + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + self.tx.write_u8(word) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.tx.flush() + } +} + +impl serial::Write for Serial { + type Error = Error; + + fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { + self.tx.write_u16(word) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.tx.flush() + } +} + +impl serial::Read for Serial { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.rx.read() + } +} + +impl serial::Read for Serial { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.rx.read_u16() + } +} + +// Blocking + +impl blocking::Write for Tx { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.bwrite_all_u8(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.bflush() + } +} + +impl blocking::Write for Tx { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Self::Error> { + self.bwrite_all_u16(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.bflush() + } +} + +impl blocking::Write for Serial { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.tx.bwrite_all_u8(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.tx.bflush() + } +} + +impl blocking::Write for Serial { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Self::Error> { + self.tx.bwrite_all_u16(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.tx.bflush() + } +} diff --git a/src/serial/hal_1.rs b/src/serial/hal_1.rs new file mode 100644 index 00000000..d9af44df --- /dev/null +++ b/src/serial/hal_1.rs @@ -0,0 +1,162 @@ +use super::*; + +mod nb { + use super::{Error, Instance, Rx, Serial, Tx}; + use embedded_hal_nb::serial::ErrorKind; + use embedded_hal_nb::{serial, serial::ErrorType}; + + impl embedded_hal_nb::serial::Error for Error { + fn kind(&self) -> ErrorKind { + match self { + Error::Overrun => ErrorKind::Overrun, + Error::FrameFormat => ErrorKind::FrameFormat, + Error::Parity => ErrorKind::Parity, + Error::Noise => ErrorKind::Noise, + Error::Other => ErrorKind::Other, + } + } + } + + impl ErrorType for Tx { + type Error = Error; + } + + impl ErrorType for Rx { + type Error = Error; + } + + impl ErrorType for Serial { + type Error = Error; + } + + impl serial::Write for Tx { + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + self.write_u8(word)?; + Ok(()) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.flush() + } + } + + impl serial::Write for Tx { + fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { + self.write_u16(word) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.flush() + } + } + + impl serial::Read for Rx { + fn read(&mut self) -> nb::Result { + self.read() + } + } + + impl serial::Read for Rx { + fn read(&mut self) -> nb::Result { + self.read_u16() + } + } + + impl serial::Write for Serial { + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + self.tx.write_u8(word).unwrap(); + Ok(()) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.tx.flush().unwrap(); + Ok(()) + } + } + + impl serial::Write for Serial { + fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { + self.tx.write_u16(word).unwrap(); + Ok(()) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.tx.flush().unwrap(); + Ok(()) + } + } + + impl serial::Read for Serial { + fn read(&mut self) -> nb::Result { + self.rx.read() + } + } + + impl serial::Read for Serial { + fn read(&mut self) -> nb::Result { + self.rx.read_u16() + } + } +} + +mod io { + use super::super::{Error, Instance, Rx, Serial, Tx}; + use embedded_io::Write; + + impl embedded_io::Error for Error { + // TODO: fix error conversion + fn kind(&self) -> embedded_io::ErrorKind { + embedded_io::ErrorKind::Other + } + } + + impl embedded_io::ErrorType for Serial { + type Error = Error; + } + + impl embedded_io::ErrorType for Tx { + type Error = Error; + } + + impl embedded_io::ErrorType for Rx { + type Error = Error; + } + + impl Write for Tx { + fn write(&mut self, bytes: &[u8]) -> Result { + let mut i = 0; + for byte in bytes.iter() { + match self.write_u8(*byte) { + Ok(_) => { + i += 1; + } + Err(nb::Error::WouldBlock) => { + return Ok(i); + } + Err(nb::Error::Other(e)) => { + return Err(e); + } + } + } + Ok(i) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + self.bflush()?; + Ok(()) + } + } + + impl Write for Serial + where + Tx: Write, + { + fn write(&mut self, bytes: &[u8]) -> Result { + self.tx.write(bytes) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Write::flush(&mut self.tx) + } + } +} diff --git a/src/spi.rs b/src/spi.rs index 74ad0083..eb3720ba 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -33,10 +33,12 @@ ``` */ +mod hal_02; +mod hal_1; + use core::ops::Deref; use core::ptr; -pub use crate::hal::spi::{FullDuplex, Mode, Phase, Polarity}; use crate::pac::{self, RCC}; use crate::afio::MAPR; @@ -51,6 +53,33 @@ use crate::time::Hertz; use core::sync::atomic::{self, Ordering}; use embedded_dma::{ReadBuffer, WriteBuffer}; +/// Clock polarity +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Polarity { + /// Clock signal low when idle + IdleLow, + /// Clock signal high when idle + IdleHigh, +} + +/// Clock phase +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Phase { + /// Data in "captured" on the first clock transition + CaptureOnFirstTransition, + /// Data in "captured" on the second clock transition + CaptureOnSecondTransition, +} + +/// SPI mode +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Mode { + /// Clock polarity + pub polarity: Polarity, + /// Clock phase + pub phase: Phase, +} + /// Interrupt event pub enum Event { /// New data has been received @@ -191,7 +220,7 @@ impl Spi { spi: pac::SPI1, pins: PINS, mapr: &mut MAPR, - mode: Mode, + mode: impl Into, freq: Hertz, clocks: Clocks, ) -> Self @@ -212,7 +241,7 @@ impl Spi { You can also use `NoMiso` or `NoMosi` if you don't want to use the pins */ - pub fn spi1_slave(spi: pac::SPI1, pins: PINS, mapr: &mut MAPR, mode: Mode) -> Self + pub fn spi1_slave(spi: pac::SPI1, pins: PINS, mapr: &mut MAPR, mode: impl Into) -> Self where REMAP: Remap, PINS: Pins, @@ -368,8 +397,6 @@ where loop { let sr = self.spi.sr.read(); if sr.txe().bit_is_set() { - // NOTE(write_volatile) see note above - // unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, *word) } self.write_data_reg(*word); if sr.modf().bit_is_set() { return Err(Error::ModeFault); @@ -379,24 +406,10 @@ where } } // Wait for final TXE - loop { - let sr = self.spi.sr.read(); - if sr.txe().bit_is_set() { - break; - } - } + while !self.is_tx_empty() {} // Wait for final !BSY - loop { - let sr = self.spi.sr.read(); - if !sr.bsy().bit_is_set() { - break; - } - } + while self.is_busy() {} // Clear OVR set due to dropped received values - // NOTE(read_volatile) see note above - // unsafe { - // let _ = ptr::read_volatile(&self.spi.dr as *const _ as *const u8); - // } let _ = self.read_data_reg(); let _ = self.spi.sr.read(); Ok(()) @@ -408,10 +421,6 @@ where SPI: Instance, FrameSize: Copy, { - #[deprecated(since = "0.6.0", note = "Please use release instead")] - pub fn free(self) -> (SPI, PINS) { - self.release() - } pub fn release(self) -> (SPI, PINS) { (self.spi, self.pins) } @@ -447,30 +456,36 @@ where } /// Returns true if the tx register is empty (and can accept data) + #[inline] pub fn is_tx_empty(&self) -> bool { self.spi.sr.read().txe().bit_is_set() } /// Returns true if the rx register is not empty (and can be read) + #[inline] pub fn is_rx_not_empty(&self) -> bool { self.spi.sr.read().rxne().bit_is_set() } + /// Returns true if the transfer is in progress + #[inline] + pub fn is_busy(&self) -> bool { + self.spi.sr.read().bsy().bit_is_set() + } + /// Returns true if data are received and the previous data have not yet been read from SPI_DR. + #[inline] pub fn is_overrun(&self) -> bool { self.spi.sr.read().ovr().bit_is_set() } - - pub fn is_busy(&self) -> bool { - self.spi.sr.read().bsy().bit_is_set() - } } impl Spi where SPI: Instance, { - fn configure(spi: SPI, pins: PINS, mode: Mode, freq: Hertz, clocks: Clocks) -> Self { + fn configure(spi: SPI, pins: PINS, mode: impl Into, freq: Hertz, clocks: Clocks) -> Self { + let mode = mode.into(); // enable or reset SPI let rcc = unsafe { &(*RCC::ptr()) }; SPI::enable(rcc); @@ -492,40 +507,28 @@ where }; spi.cr1.write(|w| { - w - // clock phase from config - .cpha() - .bit(mode.phase == Phase::CaptureOnSecondTransition) - // clock polarity from config - .cpol() - .bit(mode.polarity == Polarity::IdleHigh) - // mstr: master configuration - .mstr() - .set_bit() - // baudrate value - .br() - .bits(br) - // lsbfirst: MSB first - .lsbfirst() - .clear_bit() - // ssm: enable software slave management (NSS pin free for other uses) - .ssm() - .set_bit() - // ssi: set nss high = master mode - .ssi() - .set_bit() - // dff: 8 bit frames - .dff() - .clear_bit() - // bidimode: 2-line unidirectional - .bidimode() - .clear_bit() - // both TX and RX are used - .rxonly() - .clear_bit() - // spe: enable the SPI bus - .spe() - .set_bit() + // clock phase from config + w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition); + // clock polarity from config + w.cpol().bit(mode.polarity == Polarity::IdleHigh); + // mstr: master configuration + w.mstr().set_bit(); + // baudrate value + w.br().bits(br); + // lsbfirst: MSB first + w.lsbfirst().clear_bit(); + // ssm: enable software slave management (NSS pin free for other uses) + w.ssm().set_bit(); + // ssi: set nss high = master mode + w.ssi().set_bit(); + // dff: 8 bit frames + w.dff().clear_bit(); + // bidimode: 2-line unidirectional + w.bidimode().clear_bit(); + // both TX and RX are used + w.rxonly().clear_bit(); + // spe: enable the SPI bus + w.spe().set_bit() }); Spi { @@ -542,7 +545,8 @@ impl Spi where SPI: Instance, { - fn configure(spi: SPI, pins: PINS, mode: Mode) -> Self { + fn configure(spi: SPI, pins: PINS, mode: impl Into) -> Self { + let mode = mode.into(); // enable or reset SPI let rcc = unsafe { &(*RCC::ptr()) }; SPI::enable(rcc); @@ -552,37 +556,26 @@ where spi.cr2.write(|w| w.ssoe().clear_bit()); spi.cr1.write(|w| { - w - // clock phase from config - .cpha() - .bit(mode.phase == Phase::CaptureOnSecondTransition) - // clock polarity from config - .cpol() - .bit(mode.polarity == Polarity::IdleHigh) - // mstr: slave configuration - .mstr() - .clear_bit() - // lsbfirst: MSB first - .lsbfirst() - .clear_bit() - // ssm: enable software slave management (NSS pin free for other uses) - .ssm() - .set_bit() - // ssi: set nss low = slave mode - .ssi() - .clear_bit() - // dff: 8 bit frames - .dff() - .clear_bit() - // bidimode: 2-line unidirectional - .bidimode() - .clear_bit() - // both TX and RX are used - .rxonly() - .clear_bit() - // spe: enable the SPI bus - .spe() - .set_bit() + // clock phase from config + w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition); + // clock polarity from config + w.cpol().bit(mode.polarity == Polarity::IdleHigh); + // mstr: slave configuration + w.mstr().clear_bit(); + // lsbfirst: MSB first + w.lsbfirst().clear_bit(); + // ssm: enable software slave management (NSS pin free for other uses) + w.ssm().set_bit(); + // ssi: set nss low = slave mode + w.ssi().clear_bit(); + // dff: 8 bit frames + w.dff().clear_bit(); + // bidimode: 2-line unidirectional + w.bidimode().clear_bit(); + // both TX and RX are used + w.rxonly().clear_bit(); + // spe: enable the SPI bus + w.spe().set_bit() }); Spi { @@ -633,23 +626,20 @@ where } } -impl crate::hal::spi::FullDuplex - for Spi +impl Spi where SPI: Instance, FrameSize: Copy, { - type Error = Error; - - fn read(&mut self) -> nb::Result { + pub fn read_nonblocking(&mut self) -> nb::Result { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { - nb::Error::Other(Error::Overrun) + Error::Overrun.into() } else if sr.modf().bit_is_set() { - nb::Error::Other(Error::ModeFault) + Error::ModeFault.into() } else if sr.crcerr().bit_is_set() { - nb::Error::Other(Error::Crc) + Error::Crc.into() } else if sr.rxne().bit_is_set() { // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows // reading a half-word) @@ -658,14 +648,14 @@ where nb::Error::WouldBlock }) } - - fn send(&mut self, data: FrameSize) -> nb::Result<(), Error> { + pub fn write_nonblocking(&mut self, data: FrameSize) -> nb::Result<(), Error> { let sr = self.spi.sr.read(); + // NOTE: Error::Overrun was deleted in #408. Need check Err(if sr.modf().bit_is_set() { - nb::Error::Other(Error::ModeFault) + Error::ModeFault.into() } else if sr.crcerr().bit_is_set() { - nb::Error::Other(Error::Crc) + Error::Crc.into() } else if sr.txe().bit_is_set() { // NOTE(write_volatile) see note above self.write_data_reg(data); @@ -674,38 +664,7 @@ where nb::Error::WouldBlock }) } -} - -impl crate::hal::blocking::spi::transfer::Default - for Spi -where - SPI: Instance, - FrameSize: Copy, -{ -} - -impl crate::hal::blocking::spi::Write for Spi -where - SPI: Instance, -{ - type Error = Error; - - // Implement write as per the "Transmit only procedure" page 712 - // of RM0008 Rev 20. This is more than twice as fast as the - // default Write<> implementation (which reads and drops each - // received value) - fn write(&mut self, words: &[u8]) -> Result<(), Error> { - self.spi_write(words) - } -} - -impl crate::hal::blocking::spi::Write for Spi -where - SPI: Instance, -{ - type Error = Error; - - fn write(&mut self, words: &[u16]) -> Result<(), Error> { + pub fn write(&mut self, words: &[FrameSize]) -> Result<(), Error> { self.spi_write(words) } } @@ -851,25 +810,18 @@ macro_rules! spi_dma { atomic::compiler_fence(Ordering::Release); self.channel.ch().cr.modify(|_, w| { - w - // memory to memory mode disabled - .mem2mem() - .clear_bit() - // medium channel priority level - .pl() - .medium() - // 8-bit memory size - .msize() - .bits8() - // 8-bit peripheral size - .psize() - .bits8() - // circular mode disabled - .circ() - .clear_bit() - // write to memory - .dir() - .clear_bit() + // memory to memory mode disabled + w.mem2mem().clear_bit(); + // medium channel priority level + w.pl().medium(); + // 8-bit memory size + w.msize().bits8(); + // 8-bit peripheral size + w.psize().bits8(); + // circular mode disabled + w.circ().clear_bit(); + // write to memory + w.dir().clear_bit() }); self.start(); @@ -895,25 +847,18 @@ macro_rules! spi_dma { atomic::compiler_fence(Ordering::Release); self.channel.ch().cr.modify(|_, w| { - w - // memory to memory mode disabled - .mem2mem() - .clear_bit() - // medium channel priority level - .pl() - .medium() - // 8-bit memory size - .msize() - .bits8() - // 8-bit peripheral size - .psize() - .bits8() - // circular mode disabled - .circ() - .clear_bit() - // read from memory - .dir() - .set_bit() + // memory to memory mode disabled + w.mem2mem().clear_bit(); + // medium channel priority level + w.pl().medium(); + // 8-bit memory size + w.msize().bits8(); + // 8-bit peripheral size + w.psize().bits8(); + // circular mode disabled + w.circ().clear_bit(); + // read from memory + w.dir().set_bit() }); self.start(); @@ -957,46 +902,32 @@ macro_rules! spi_dma { atomic::compiler_fence(Ordering::Release); self.rxchannel.ch().cr.modify(|_, w| { - w - // memory to memory mode disabled - .mem2mem() - .clear_bit() - // medium channel priority level - .pl() - .medium() - // 8-bit memory size - .msize() - .bits8() - // 8-bit peripheral size - .psize() - .bits8() - // circular mode disabled - .circ() - .clear_bit() - // write to memory - .dir() - .clear_bit() + // memory to memory mode disabled + w.mem2mem().clear_bit(); + // medium channel priority level + w.pl().medium(); + // 8-bit memory size + w.msize().bits8(); + // 8-bit peripheral size + w.psize().bits8(); + // circular mode disabled + w.circ().clear_bit(); + // write to memory + w.dir().clear_bit() }); self.txchannel.ch().cr.modify(|_, w| { - w - // memory to memory mode disabled - .mem2mem() - .clear_bit() - // medium channel priority level - .pl() - .medium() - // 8-bit memory size - .msize() - .bits8() - // 8-bit peripheral size - .psize() - .bits8() - // circular mode disabled - .circ() - .clear_bit() - // read from memory - .dir() - .set_bit() + // memory to memory mode disabled + w.mem2mem().clear_bit(); + // medium channel priority level + w.pl().medium(); + // 8-bit memory size + w.msize().bits8(); + // 8-bit peripheral size + w.psize().bits8(); + // circular mode disabled + w.circ().clear_bit(); + // read from memory + w.dir().set_bit() }); self.start(); diff --git a/src/spi/hal_02.rs b/src/spi/hal_02.rs new file mode 100644 index 00000000..84e5b967 --- /dev/null +++ b/src/spi/hal_02.rs @@ -0,0 +1,70 @@ +use super::*; + +pub use embedded_hal_02::spi::{Mode, Phase, Polarity}; +use embedded_hal_02::{blocking::spi as blocking, spi}; + +impl From for super::Polarity { + fn from(p: Polarity) -> Self { + match p { + Polarity::IdleLow => Self::IdleLow, + Polarity::IdleHigh => Self::IdleHigh, + } + } +} + +impl From for super::Phase { + fn from(p: Phase) -> Self { + match p { + Phase::CaptureOnFirstTransition => Self::CaptureOnFirstTransition, + Phase::CaptureOnSecondTransition => Self::CaptureOnSecondTransition, + } + } +} + +impl From for super::Mode { + fn from(m: Mode) -> Self { + Self { + polarity: m.polarity.into(), + phase: m.phase.into(), + } + } +} + +impl spi::FullDuplex for Spi +where + SPI: Instance, + W: Copy, +{ + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.read_nonblocking() + } + + fn send(&mut self, data: W) -> nb::Result<(), Error> { + self.write_nonblocking(data) + } +} + +impl blocking::transfer::Default for Spi +where + SPI: Instance, + W: Copy, +{ +} + +impl blocking::Write for Spi { + type Error = Error; + + fn write(&mut self, words: &[u8]) -> Result<(), Error> { + self.write(words) + } +} + +impl blocking::Write for Spi { + type Error = Error; + + fn write(&mut self, words: &[u16]) -> Result<(), Error> { + self.write(words) + } +} diff --git a/src/spi/hal_1.rs b/src/spi/hal_1.rs new file mode 100644 index 00000000..a398dac0 --- /dev/null +++ b/src/spi/hal_1.rs @@ -0,0 +1,93 @@ +use super::*; +pub use embedded_hal::spi::{ErrorKind, ErrorType, Mode, Phase, Polarity}; + +impl From for super::Polarity { + fn from(p: Polarity) -> Self { + match p { + Polarity::IdleLow => Self::IdleLow, + Polarity::IdleHigh => Self::IdleHigh, + } + } +} + +impl From for super::Phase { + fn from(p: Phase) -> Self { + match p { + Phase::CaptureOnFirstTransition => Self::CaptureOnFirstTransition, + Phase::CaptureOnSecondTransition => Self::CaptureOnSecondTransition, + } + } +} + +impl From for super::Mode { + fn from(m: Mode) -> Self { + Self { + polarity: m.polarity.into(), + phase: m.phase.into(), + } + } +} + +impl embedded_hal::spi::Error for Error { + fn kind(&self) -> ErrorKind { + match self { + Self::Overrun => ErrorKind::Overrun, + Self::ModeFault => ErrorKind::ModeFault, + Self::Crc => ErrorKind::Other, + } + } +} + +impl ErrorType for Spi { + type Error = Error; +} + +mod nb { + use super::{Error, Instance, Spi}; + use embedded_hal_nb::spi::FullDuplex; + + impl FullDuplex for Spi + where + SPI: Instance, + W: Copy, + { + fn read(&mut self) -> nb::Result { + self.read_nonblocking() + } + + fn write(&mut self, data: W) -> nb::Result<(), Error> { + self.write_nonblocking(data) + } + } +} + +mod blocking { + use super::super::{Instance, Spi}; + use embedded_hal::spi::SpiBus; + + impl SpiBus for Spi + where + SPI: Instance, + W: Copy + 'static, + { + fn transfer_in_place(&mut self, _words: &mut [W]) -> Result<(), Self::Error> { + todo!() + } + + fn transfer(&mut self, _buff: &mut [W], _data: &[W]) -> Result<(), Self::Error> { + todo!() + } + + fn read(&mut self, _words: &mut [W]) -> Result<(), Self::Error> { + todo!() + } + + fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { + self.write(words) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } +} diff --git a/src/timer.rs b/src/timer.rs index 7faa1e7a..76896c3a 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -73,6 +73,7 @@ pub mod pwm; pub use pwm::*; mod hal_02; +mod hal_1; /// Timer wrapper pub struct Timer { @@ -683,12 +684,12 @@ impl FTimer { self.tim.set_prescaler(u16::try_from(psc - 1).unwrap()); } - /// Creates `Counter` that imlements [embedded_hal::timer::CountDown] + /// Creates `Counter` that imlements [embedded_hal_02::timer::CountDown] pub fn counter(self) -> Counter { Counter(self) } - /// Creates `Delay` that imlements [embedded_hal::blocking::delay] traits + /// Creates `Delay` that imlements [embedded_hal_02::blocking::delay] traits pub fn delay(self) -> Delay { Delay(self) } diff --git a/src/timer/counter.rs b/src/timer/counter.rs index 3bfdfc5e..2f811434 100644 --- a/src/timer/counter.rs +++ b/src/timer/counter.rs @@ -122,7 +122,7 @@ impl CounterHz { } } -/// Periodic non-blocking timer that imlements [embedded_hal::timer::CountDown] +/// Periodic non-blocking timer that imlements [embedded_hal_02::timer::CountDown] pub struct Counter(pub(super) FTimer); impl Deref for Counter { diff --git a/src/timer/delay.rs b/src/timer/delay.rs index ef5eb38e..fbbae298 100644 --- a/src/timer/delay.rs +++ b/src/timer/delay.rs @@ -58,7 +58,7 @@ impl SysDelay { } } -/// Periodic non-blocking timer that imlements [embedded_hal::blocking::delay] traits +/// Periodic non-blocking timer that imlements [embedded_hal_02::blocking::delay] traits pub struct Delay(pub(super) FTimer); impl Deref for Delay { diff --git a/src/timer/hal_02.rs b/src/timer/hal_02.rs index 39d94fde..42c4d26d 100644 --- a/src/timer/hal_02.rs +++ b/src/timer/hal_02.rs @@ -3,7 +3,7 @@ //! TIM2 and TIM5 are a general purpose 32-bit auto-reload up/downcounter with //! a 16-bit prescaler. -use embedded_hal::{ +use embedded_hal_02::{ blocking::delay::{DelayMs, DelayUs}, timer::{Cancel, CountDown, Periodic}, }; @@ -133,7 +133,7 @@ impl Cancel for SysCounter { } } -impl embedded_hal::PwmPin for PwmChannel { +impl embedded_hal_02::PwmPin for PwmChannel { type Duty = u16; fn disable(&mut self) { @@ -153,7 +153,7 @@ impl embedded_hal::PwmPin for PwmChannel embedded_hal::Pwm for PwmHz +impl embedded_hal_02::Pwm for PwmHz where TIM: Instance + WithPwm, REMAP: Remap, @@ -264,7 +264,7 @@ impl Cancel for Counter { } } -impl embedded_hal::Pwm for Pwm +impl embedded_hal_02::Pwm for Pwm where TIM: Instance + WithPwm, REMAP: Remap, diff --git a/src/timer/hal_1.rs b/src/timer/hal_1.rs new file mode 100644 index 00000000..d022771d --- /dev/null +++ b/src/timer/hal_1.rs @@ -0,0 +1,48 @@ +//! Delay implementation based on general-purpose 32 bit timers and System timer (SysTick). +//! +//! TIM2 and TIM5 are a general purpose 32-bit auto-reload up/downcounter with +//! a 16-bit prescaler. + +use core::convert::Infallible; +use embedded_hal::delay::DelayNs; + +use super::{Delay, Instance, PwmChannel, SysDelay, WithPwm}; +use fugit::ExtU32Ceil; + +impl DelayNs for SysDelay { + fn delay_ns(&mut self, ns: u32) { + self.delay(ns.nanos_at_least()); + } + + fn delay_ms(&mut self, ms: u32) { + self.delay(ms.millis_at_least()); + } +} + +impl DelayNs for Delay { + fn delay_ns(&mut self, ns: u32) { + self.delay(ns.micros_at_least()); + } + + fn delay_us(&mut self, us: u32) { + self.delay(us.micros_at_least()); + } + + fn delay_ms(&mut self, ms: u32) { + self.delay(ms.millis_at_least()); + } +} + +impl embedded_hal::pwm::ErrorType for PwmChannel { + type Error = Infallible; +} + +impl embedded_hal::pwm::SetDutyCycle for PwmChannel { + fn max_duty_cycle(&self) -> u16 { + self.get_max_duty() + } + fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { + self.set_duty(duty); + Ok(()) + } +} diff --git a/src/watchdog.rs b/src/watchdog.rs index da553b7c..8009585c 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -1,7 +1,7 @@ //! Watchdog peripherals use crate::{ - hal::watchdog::{Watchdog, WatchdogEnable}, + hal_02::watchdog::{Watchdog, WatchdogEnable}, pac::{DBGMCU as DBG, IWDG}, time::MilliSeconds, };