From 78c820c14f7713b0ea7e8160554a43bef8f96d08 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 09:55:40 +0300 Subject: [PATCH 1/9] move embedded-hal_02 to subdir for gpio --- src/gpio.rs | 201 ++------------------- src/gpio/erased.rs | 66 ------- src/gpio/hal_02.rs | 335 +++++++++++++++++++++++++++++++++++ src/gpio/partially_erased.rs | 66 ------- 4 files changed, 353 insertions(+), 315 deletions(-) create mode 100644 src/gpio/hal_02.rs diff --git a/src/gpio.rs b/src/gpio.rs index a6501876..ef3f50ce 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -43,14 +43,8 @@ //! ownership reasons, you can use the closure based `with_` functions to temporarily change the pin type, do //! some output or input, and then have it change back once done. -use core::convert::Infallible; use core::marker::PhantomData; -pub use embedded_hal::digital::v2::PinState; -use embedded_hal::digital::v2::{ - InputPin, IoPin, OutputPin, StatefulOutputPin, ToggleableOutputPin, -}; - use crate::pac::EXTI; use crate::syscfg::SysCfg; @@ -62,6 +56,24 @@ mod partially_erased; pub use partially_erased::{PEPin, PartiallyErasedPin}; mod erased; pub use erased::{EPin, ErasedPin}; +mod hal_02; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum PinState { + /// Low pin state + Low, + /// High pin state + High, +} + +impl From for PinState { + fn from(value: bool) -> Self { + match value { + false => PinState::Low, + true => PinState::High, + } + } +} /// A filler pin type pub struct NoPin; @@ -481,44 +493,6 @@ impl Pin, P, N> { } } -impl OutputPin for Pin, P, N> { - 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 Pin, P, N> { - #[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 Pin, P, N> { - type Error = Infallible; - - #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - impl Pin, P, N> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -531,20 +505,6 @@ impl Pin, P, N> { } } -impl InputPin for Pin, P, N> { - 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 Pin, P, N> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -557,131 +517,6 @@ impl Pin, P, N> { } } -impl InputPin for Pin, P, N> { - 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 IoPin for Pin, P, N> { - type Error = Infallible; - fn into_input_pin(self) -> Result { - Ok(self) - } - fn into_output_pin(mut self, state: PinState) -> Result { - self.set_state(state); - Ok(self) - } -} - -impl IoPin, P, N>, Self> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result, P, N>, Self::Error> { - Ok(self.into_floating_input()) - } - fn into_output_pin(mut self, state: PinState) -> Result { - self.set_state(state); - Ok(self) - } -} - -impl IoPin, P, N>> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result { - Ok(self) - } - fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { - Ok(self.into_open_drain_output_in_state(state)) - } -} - -impl IoPin, P, N>, Self> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result, P, N>, Self::Error> { - Ok(self.into_floating_input()) - } - fn into_output_pin(mut self, state: PinState) -> Result { - self.set_state(state); - Ok(self) - } -} - -impl IoPin, P, N>> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result { - Ok(self) - } - fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { - Ok(self.into_push_pull_output_in_state(state)) - } -} - -impl IoPin, P, N>, Self> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result, P, N>, Self::Error> { - Ok(self.into_pull_up_input()) - } - fn into_output_pin(mut self, state: PinState) -> Result { - self.set_state(state); - Ok(self) - } -} - -impl IoPin, P, N>> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result { - Ok(self) - } - fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { - Ok(self.into_push_pull_output_in_state(state)) - } -} - -impl IoPin, P, N>, Self> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result, P, N>, Self::Error> { - Ok(self.into_pull_down_input()) - } - fn into_output_pin(mut self, state: PinState) -> Result { - self.set_state(state); - Ok(self) - } -} - -impl IoPin, P, N>> - for Pin, P, N> -{ - type Error = Infallible; - fn into_input_pin(self) -> Result { - Ok(self) - } - fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { - Ok(self.into_push_pull_output_in_state(state)) - } -} - macro_rules! gpio { ($GPIOX:ident, $gpiox:ident, $PEPin:ident, $port_id:expr, $PXn:ident, [ $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+ diff --git a/src/gpio/erased.rs b/src/gpio/erased.rs index f6416c63..cd69bfcf 100644 --- a/src/gpio/erased.rs +++ b/src/gpio/erased.rs @@ -107,44 +107,6 @@ impl ErasedPin> { } } -impl OutputPin for ErasedPin> { - type Error = core::convert::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 ErasedPin> { - #[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 ErasedPin> { - type Error = Infallible; - - #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - impl ErasedPin> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -157,20 +119,6 @@ impl ErasedPin> { } } -impl InputPin for ErasedPin> { - type Error = core::convert::Infallible; - - #[inline(always)] - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - #[inline(always)] - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - impl ErasedPin> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -182,17 +130,3 @@ impl ErasedPin> { self.block().idr.read().bits() & (1 << self.pin_id()) == 0 } } - -impl InputPin for ErasedPin> { - type Error = core::convert::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/gpio/hal_02.rs b/src/gpio/hal_02.rs new file mode 100644 index 00000000..1cb36554 --- /dev/null +++ b/src/gpio/hal_02.rs @@ -0,0 +1,335 @@ +use core::convert::Infallible; + +use super::{ + ErasedPin, Floating, Input, OpenDrain, Output, PartiallyErasedPin, Pin, PullDown, PullUp, + PushPull, +}; + +pub use embedded_hal::digital::v2::PinState; +use embedded_hal::digital::v2::{ + InputPin, IoPin, OutputPin, StatefulOutputPin, ToggleableOutputPin, +}; + +impl From for super::PinState { + fn from(state: PinState) -> Self { + match state { + PinState::Low => Self::Low, + PinState::High => Self::High, + } + } +} + +// Implementations for `Pin` + +impl OutputPin for Pin, P, N> { + 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 Pin, P, N> { + #[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 Pin, P, N> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for Pin, P, N> { + 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 Pin, P, N> { + 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 IoPin for Pin, P, N> { + type Error = Infallible; + fn into_input_pin(self) -> Result { + Ok(self) + } + fn into_output_pin(mut self, state: PinState) -> Result { + self.set_state(state.into()); + Ok(self) + } +} + +impl IoPin, P, N>, Self> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result, P, N>, Self::Error> { + Ok(self.into_floating_input()) + } + fn into_output_pin(mut self, state: PinState) -> Result { + self.set_state(state.into()); + Ok(self) + } +} + +impl IoPin, P, N>> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result { + Ok(self) + } + fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { + Ok(self.into_open_drain_output_in_state(state.into())) + } +} + +impl IoPin, P, N>, Self> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result, P, N>, Self::Error> { + Ok(self.into_floating_input()) + } + fn into_output_pin(mut self, state: PinState) -> Result { + self.set_state(state.into()); + Ok(self) + } +} + +impl IoPin, P, N>> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result { + Ok(self) + } + fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { + Ok(self.into_push_pull_output_in_state(state.into())) + } +} + +impl IoPin, P, N>, Self> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result, P, N>, Self::Error> { + Ok(self.into_pull_up_input()) + } + fn into_output_pin(mut self, state: PinState) -> Result { + self.set_state(state.into()); + Ok(self) + } +} + +impl IoPin, P, N>> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result { + Ok(self) + } + fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { + Ok(self.into_push_pull_output_in_state(state.into())) + } +} + +impl IoPin, P, N>, Self> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result, P, N>, Self::Error> { + Ok(self.into_pull_down_input()) + } + fn into_output_pin(mut self, state: PinState) -> Result { + self.set_state(state.into()); + Ok(self) + } +} + +impl IoPin, P, N>> + for Pin, P, N> +{ + type Error = Infallible; + fn into_input_pin(self) -> Result { + Ok(self) + } + fn into_output_pin(self, state: PinState) -> Result, P, N>, Self::Error> { + Ok(self.into_push_pull_output_in_state(state.into())) + } +} + +// Implementations for `ErasedPin` + +impl OutputPin for ErasedPin> { + type Error = core::convert::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 ErasedPin> { + #[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 ErasedPin> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for ErasedPin> { + type Error = core::convert::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 ErasedPin> { + type Error = core::convert::Infallible; + + #[inline(always)] + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + #[inline(always)] + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + +// Implementations for `PartiallyErasedPin` + +impl OutputPin for PartiallyErasedPin, P> { + 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, P> { + #[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, P> { + type Error = Infallible; + + #[inline(always)] + fn toggle(&mut self) -> Result<(), Self::Error> { + self.toggle(); + Ok(()) + } +} + +impl InputPin for PartiallyErasedPin, P> { + 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, P> { + 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/gpio/partially_erased.rs b/src/gpio/partially_erased.rs index 79f344c1..aab27918 100644 --- a/src/gpio/partially_erased.rs +++ b/src/gpio/partially_erased.rs @@ -88,44 +88,6 @@ impl PartiallyErasedPin, P> { } } -impl OutputPin for PartiallyErasedPin, P> { - 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, P> { - #[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, P> { - type Error = Infallible; - - #[inline(always)] - fn toggle(&mut self) -> Result<(), Self::Error> { - self.toggle(); - Ok(()) - } -} - impl PartiallyErasedPin, P> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -139,20 +101,6 @@ impl PartiallyErasedPin, P> { } } -impl InputPin for PartiallyErasedPin, P> { - 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, P> { #[inline(always)] pub fn is_high(&self) -> bool { @@ -165,17 +113,3 @@ impl PartiallyErasedPin, P> { unsafe { (*Gpio::

::ptr()).idr.read().bits() & (1 << self.i) == 0 } } } - -impl InputPin for PartiallyErasedPin, P> { - 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()) - } -} From ce82aadd14f2ac9be44762f81629dc959d633ebe Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 11:19:01 +0300 Subject: [PATCH 2/9] move embedded-hal_02 to subdir for serial --- src/serial.rs | 234 +------------------------------------------ src/serial/hal_02.rs | 233 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+), 229 deletions(-) create mode 100644 src/serial/hal_02.rs diff --git a/src/serial.rs b/src/serial.rs index f09237e5..1bb19779 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -20,11 +20,10 @@ use core::fmt; use core::marker::PhantomData; use crate::rcc; -use embedded_hal::blocking; -use embedded_hal::prelude::*; -use embedded_hal::serial; use nb::block; +mod hal_02; + use crate::gpio::{Const, PinA, PushPull, SetAlternate}; use crate::pac::{RCC, USART1, USART2, USART6}; @@ -592,71 +591,6 @@ where } } -impl serial::Read for Serial -where - USART: Instance, - Rx: serial::Read, -{ - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.rx.read() - } -} - -impl serial::Read for Rx -where - USART: Instance, -{ - type Error = Error; - - fn read(&mut self) -> nb::Result { - // Delegate to the Read implementation, then truncate to 8 bits - Rx::::new().read().map(|word16| word16 as u8) - } -} - -/// Reads 9-bit words from the UART/USART -/// -/// If the UART/USART was configured with `WordLength::DataBits9`, the returned value will contain -/// 9 received data bits and all other bits set to zero. Otherwise, the returned value will contain -/// 8 received data bits and all other bits set to zero. -impl serial::Read for Rx -where - USART: Instance, -{ - type Error = Error; - - fn read(&mut self) -> nb::Result { - // NOTE(unsafe) atomic read with no side effects - let sr = unsafe { (*USART::ptr()).sr.read() }; - - // Any error requires the dr to be read to clear - if sr.pe().bit_is_set() - || sr.fe().bit_is_set() - || sr.nf().bit_is_set() - || sr.ore().bit_is_set() - { - unsafe { (*USART::ptr()).dr.read() }; - } - - Err(if sr.pe().bit_is_set() { - Error::Parity.into() - } else if sr.fe().bit_is_set() { - Error::Framing.into() - } else if sr.nf().bit_is_set() { - Error::Noise.into() - } else if sr.ore().bit_is_set() { - Error::Overrun.into() - } else if sr.rxne().bit_is_set() { - // NOTE(unsafe) atomic read from stateless register - return Ok(unsafe { &*USART::ptr() }.dr.read().dr().bits()); - } else { - nb::Error::WouldBlock - }) - } -} - unsafe impl PeriAddress for Rx where USART: Instance, @@ -669,22 +603,6 @@ where type MemSize = u8; } -impl serial::Write for Serial -where - USART: Instance, - Tx: serial::Write, -{ - type Error = Error; - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.tx.flush() - } - - fn write(&mut self, byte: WORD) -> nb::Result<(), Self::Error> { - self.tx.write(byte) - } -} - unsafe impl PeriAddress for Tx where USART: Instance, @@ -697,149 +615,6 @@ where type MemSize = u8; } -impl serial::Write for Tx -where - USART: Instance, -{ - type Error = Error; - - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { - // Delegate to u16 version - Tx::::new().write(u16::from(word)) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - // Delegate to u16 version - Tx::::new().flush() - } -} - -/// Writes 9-bit words to the UART/USART -/// -/// If the UART/USART was configured with `WordLength::DataBits9`, 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. -impl serial::Write for Tx -where - USART: Instance, -{ - type Error = Error; - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - // NOTE(unsafe) atomic read with no side effects - let sr = unsafe { (*USART::ptr()).sr.read() }; - - if sr.tc().bit_is_set() { - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } - - fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { - // NOTE(unsafe) atomic read with no side effects - let sr = unsafe { (*USART::ptr()).sr.read() }; - - if sr.txe().bit_is_set() { - // NOTE(unsafe) atomic write to stateless register - unsafe { &*USART::ptr() }.dr.write(|w| w.dr().bits(word)); - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } -} - -impl blocking::serial::Write for Tx -where - USART: Instance, -{ - type Error = Error; - - fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Self::Error> { - for &b in buffer { - loop { - match self.write(b) { - Err(nb::Error::WouldBlock) => continue, - Err(nb::Error::Other(err)) => return Err(err), - Ok(()) => break, - } - } - } - Ok(()) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - loop { - match >::flush(self) { - Ok(()) => return Ok(()), - Err(nb::Error::WouldBlock) => continue, - Err(nb::Error::Other(err)) => return Err(err), - } - } - } -} - -impl blocking::serial::Write for Tx -where - USART: Instance, -{ - type Error = Error; - - fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { - for &b in bytes { - loop { - match self.write(b) { - Err(nb::Error::WouldBlock) => continue, - Err(nb::Error::Other(err)) => return Err(err), - Ok(()) => break, - } - } - } - Ok(()) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - loop { - match >::flush(self) { - Ok(()) => return Ok(()), - Err(nb::Error::WouldBlock) => continue, - Err(nb::Error::Other(err)) => return Err(err), - } - } - } -} - -impl blocking::serial::Write for Serial -where - USART: Instance, -{ - type Error = Error; - - fn bwrite_all(&mut self, bytes: &[u16]) -> Result<(), Self::Error> { - self.tx.bwrite_all(bytes) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.tx.bflush() - } -} - -impl blocking::serial::Write for Serial -where - USART: Instance, -{ - type Error = Error; - - fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { - self.tx.bwrite_all(bytes) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.tx.bflush() - } -} - impl Serial where USART: Instance, @@ -978,7 +753,7 @@ halUsart! { UART10 } impl fmt::Write for Serial where - Tx: serial::Write, + Tx: embedded_hal::serial::Write, { fn write_str(&mut self, s: &str) -> fmt::Result { self.tx.write_str(s) @@ -987,9 +762,10 @@ where impl fmt::Write for Tx where - Tx: serial::Write, + Tx: embedded_hal::serial::Write, { fn write_str(&mut self, s: &str) -> fmt::Result { + use embedded_hal::serial::Write; s.bytes() .try_for_each(|c| block!(self.write(c))) .map_err(|_| fmt::Error) diff --git a/src/serial/hal_02.rs b/src/serial/hal_02.rs new file mode 100644 index 00000000..e08fcb56 --- /dev/null +++ b/src/serial/hal_02.rs @@ -0,0 +1,233 @@ +mod nb { + use super::super::{Error, Instance, Rx, Serial, Tx}; + use embedded_hal::serial::{Read, Write}; + + impl Read for Serial + where + USART: Instance, + Rx: Read, + { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.rx.read() + } + } + + impl Read for Rx + where + USART: Instance, + { + type Error = Error; + + fn read(&mut self) -> nb::Result { + // Delegate to the Read implementation, then truncate to 8 bits + Rx::::new().read().map(|word16| word16 as u8) + } + } + + /// Reads 9-bit words from the UART/USART + /// + /// If the UART/USART was configured with `WordLength::DataBits9`, the returned value will contain + /// 9 received data bits and all other bits set to zero. Otherwise, the returned value will contain + /// 8 received data bits and all other bits set to zero. + impl Read for Rx + where + USART: Instance, + { + type Error = Error; + + fn read(&mut self) -> nb::Result { + // NOTE(unsafe) atomic read with no side effects + let sr = unsafe { (*USART::ptr()).sr.read() }; + + // Any error requires the dr to be read to clear + if sr.pe().bit_is_set() + || sr.fe().bit_is_set() + || sr.nf().bit_is_set() + || sr.ore().bit_is_set() + { + unsafe { (*USART::ptr()).dr.read() }; + } + + Err(if sr.pe().bit_is_set() { + Error::Parity.into() + } else if sr.fe().bit_is_set() { + Error::Framing.into() + } else if sr.nf().bit_is_set() { + Error::Noise.into() + } else if sr.ore().bit_is_set() { + Error::Overrun.into() + } else if sr.rxne().bit_is_set() { + // NOTE(unsafe) atomic read from stateless register + return Ok(unsafe { &*USART::ptr() }.dr.read().dr().bits()); + } else { + nb::Error::WouldBlock + }) + } + } + + impl Write for Serial + where + USART: Instance, + Tx: Write, + { + type Error = Error; + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.tx.flush() + } + + fn write(&mut self, byte: WORD) -> nb::Result<(), Self::Error> { + self.tx.write(byte) + } + } + + impl Write for Tx + where + USART: Instance, + { + type Error = Error; + + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + // Delegate to u16 version + Tx::::new().write(u16::from(word)) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + // Delegate to u16 version + Tx::::new().flush() + } + } + + /// Writes 9-bit words to the UART/USART + /// + /// If the UART/USART was configured with `WordLength::DataBits9`, 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. + impl Write for Tx + where + USART: Instance, + { + type Error = Error; + + fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { + // NOTE(unsafe) atomic read with no side effects + let sr = unsafe { (*USART::ptr()).sr.read() }; + + if sr.txe().bit_is_set() { + // NOTE(unsafe) atomic write to stateless register + unsafe { &*USART::ptr() }.dr.write(|w| w.dr().bits(word)); + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + // NOTE(unsafe) atomic read with no side effects + let sr = unsafe { (*USART::ptr()).sr.read() }; + + if sr.tc().bit_is_set() { + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } + } +} + +mod blocking { + use super::super::{Error, Instance, Serial, Tx}; + use embedded_hal::{blocking::serial::Write, serial}; + + impl Write for Tx + where + USART: Instance, + { + type Error = Error; + + fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { + for &b in bytes { + loop { + match >::write(self, b) { + Err(nb::Error::WouldBlock) => continue, + Err(nb::Error::Other(err)) => return Err(err), + Ok(()) => break, + } + } + } + Ok(()) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + loop { + match >::flush(self) { + Ok(()) => return Ok(()), + Err(nb::Error::WouldBlock) => continue, + Err(nb::Error::Other(err)) => return Err(err), + } + } + } + } + + impl Write for Serial + where + USART: Instance, + { + type Error = Error; + + fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { + self.tx.bwrite_all(bytes) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.tx.bflush() + } + } + + impl Write for Tx + where + USART: Instance, + { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Self::Error> { + for &b in buffer { + loop { + match >::write(self, b) { + Err(nb::Error::WouldBlock) => continue, + Err(nb::Error::Other(err)) => return Err(err), + Ok(()) => break, + } + } + } + Ok(()) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + loop { + match >::flush(self) { + Ok(()) => return Ok(()), + Err(nb::Error::WouldBlock) => continue, + Err(nb::Error::Other(err)) => return Err(err), + } + } + } + } + + impl Write for Serial + where + USART: Instance, + { + type Error = Error; + + fn bwrite_all(&mut self, bytes: &[u16]) -> Result<(), Self::Error> { + self.tx.bwrite_all(bytes) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.tx.bflush() + } + } +} From 237cb286b0bb85573930540c90a4b173bc7b8bb0 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 12:05:22 +0300 Subject: [PATCH 3/9] changes in ADC to support advanced hal impls --- src/adc.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index 0c026d1d..5e7182d9 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -12,7 +12,6 @@ use crate::dma::traits::PeriAddress; use crate::rcc::{Enable, Reset}; use crate::{gpio::*, pac, signature::VrefCal, signature::VDDA_CALIB}; use core::fmt; -use embedded_hal::adc::{Channel, OneShot}; /// Vref internal signal, used for calibration pub struct Vref; @@ -26,7 +25,7 @@ pub struct Temperature; macro_rules! adc_pins { ($($pin:ty => ($adc:ident, $chan:expr)),+ $(,)*) => { $( - impl Channel for $pin { + impl embedded_hal::adc::Channel for $pin { type ID = u8; fn channel() -> u8 { $chan } } @@ -897,7 +896,7 @@ macro_rules! adc { /// to sample for at a given ADC clock frequency pub fn configure_channel(&mut self, _channel: &CHANNEL, sequence: config::Sequence, sample_time: config::SampleTime) where - CHANNEL: Channel + CHANNEL: embedded_hal::adc::Channel { //Check the sequence is long enough self.adc_reg.sqr1.modify(|r, w| { @@ -977,7 +976,7 @@ macro_rules! adc { /// Note that it reconfigures the adc sequence and doesn't restore it pub fn convert(&mut self, pin: &PIN, sample_time: config::SampleTime) -> u16 where - PIN: Channel + PIN: embedded_hal::adc::Channel { self.adc_reg.cr2.modify(|_, w| w .dma().clear_bit() //Disable dma @@ -1008,13 +1007,10 @@ macro_rules! adc { } } - impl OneShot for Adc - where - PIN: Channel, - { - type Error = (); - - fn read(&mut self, pin: &mut PIN) -> nb::Result { + impl Adc { + fn read(&mut self, pin: &mut PIN) -> nb::Result + where PIN: embedded_hal::adc::Channel, + { let enabled = self.is_enabled(); if !enabled { self.enable(); @@ -1030,6 +1026,17 @@ macro_rules! adc { } } + impl embedded_hal::adc::OneShot for Adc + where + PIN: embedded_hal::adc::Channel, + { + type Error = (); + + fn read(&mut self, pin: &mut PIN) -> nb::Result { + self.read::(pin) + } + } + unsafe impl PeriAddress for Adc { #[inline(always)] fn address(&self) -> u32 { From 883b825f25cee412fd48d7f39e5b46f083964baa Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 14:26:30 +0300 Subject: [PATCH 4/9] move embedded-hal_02 to subdir for I2C --- src/fmpi2c.rs | 141 +--------------------------------------- src/fmpi2c/hal_02.rs | 143 +++++++++++++++++++++++++++++++++++++++++ src/i2c.rs | 107 ++---------------------------- src/i2c/hal_02.rs | 150 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+), 241 deletions(-) create mode 100644 src/fmpi2c/hal_02.rs create mode 100644 src/i2c/hal_02.rs diff --git a/src/fmpi2c.rs b/src/fmpi2c.rs index 40bf7f3d..ddcfc199 100644 --- a/src/fmpi2c.rs +++ b/src/fmpi2c.rs @@ -1,5 +1,4 @@ use core::ops::Deref; -use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; use crate::gpio::{Const, OpenDrain, PinA, SetAlternate}; use crate::i2c::{Error, Scl, Sda}; @@ -7,6 +6,8 @@ use crate::pac::{fmpi2c1, FMPI2C1, RCC}; use crate::rcc::{Enable, Reset}; use crate::time::{Hertz, U32Ext}; +mod hal_02; + /// I2C FastMode+ abstraction pub struct FMPI2c { i2c: I2C, @@ -200,141 +201,3 @@ where Ok(value) } } - -impl WriteRead for FMPI2c -where - I2C: Deref, -{ - type Error = Error; - - fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { - // Set up current slave address for writing and disable autoending - self.i2c.cr2.modify(|_, w| { - w.sadd() - .bits(u16::from(addr) << 1) - .nbytes() - .bits(bytes.len() as u8) - .rd_wrn() - .clear_bit() - .autoend() - .clear_bit() - }); - - // Send a START condition - self.i2c.cr2.modify(|_, w| w.start().set_bit()); - - // Wait until the transmit buffer is empty and there hasn't been any error condition - while { - let isr = self.i2c.isr.read(); - self.check_and_clear_error_flags(&isr)?; - isr.txis().bit_is_clear() && isr.tc().bit_is_clear() - } {} - - // Send out all individual bytes - for c in bytes { - self.send_byte(*c)?; - } - - // Wait until data was sent - while { - let isr = self.i2c.isr.read(); - self.check_and_clear_error_flags(&isr)?; - isr.tc().bit_is_clear() - } {} - - // Set up current address for reading - self.i2c.cr2.modify(|_, w| { - w.sadd() - .bits(u16::from(addr) << 1) - .nbytes() - .bits(buffer.len() as u8) - .rd_wrn() - .set_bit() - }); - - // Send another START condition - self.i2c.cr2.modify(|_, w| w.start().set_bit()); - - // Send the autoend after setting the start to get a restart - self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); - - // Now read in all bytes - for c in buffer.iter_mut() { - *c = self.recv_byte()?; - } - - // Check and clear flags if they somehow ended up set - self.check_and_clear_error_flags(&self.i2c.isr.read())?; - - Ok(()) - } -} - -impl Read for FMPI2c -where - I2C: Deref, -{ - type Error = Error; - - fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { - // Set up current address for reading - self.i2c.cr2.modify(|_, w| { - w.sadd() - .bits(u16::from(addr) << 1) - .nbytes() - .bits(buffer.len() as u8) - .rd_wrn() - .set_bit() - }); - - // Send a START condition - self.i2c.cr2.modify(|_, w| w.start().set_bit()); - - // Send the autoend after setting the start to get a restart - self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); - - // Now read in all bytes - for c in buffer.iter_mut() { - *c = self.recv_byte()?; - } - - // Check and clear flags if they somehow ended up set - self.check_and_clear_error_flags(&self.i2c.isr.read())?; - - Ok(()) - } -} - -impl Write for FMPI2c -where - I2C: Deref, -{ - type Error = Error; - - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { - // Set up current slave address for writing and enable autoending - self.i2c.cr2.modify(|_, w| { - w.sadd() - .bits(u16::from(addr) << 1) - .nbytes() - .bits(bytes.len() as u8) - .rd_wrn() - .clear_bit() - .autoend() - .set_bit() - }); - - // Send a START condition - self.i2c.cr2.modify(|_, w| w.start().set_bit()); - - // Send out all individual bytes - for c in bytes { - self.send_byte(*c)?; - } - - // Check and clear flags if they somehow ended up set - self.check_and_clear_error_flags(&self.i2c.isr.read())?; - - Ok(()) - } -} diff --git a/src/fmpi2c/hal_02.rs b/src/fmpi2c/hal_02.rs new file mode 100644 index 00000000..2c90d1a1 --- /dev/null +++ b/src/fmpi2c/hal_02.rs @@ -0,0 +1,143 @@ +mod blocking { + use super::super::{fmpi2c1, Error, FMPI2c}; + use core::ops::Deref; + use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; + + impl WriteRead for FMPI2c + where + I2C: Deref, + { + type Error = Error; + + fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { + // Set up current slave address for writing and disable autoending + self.i2c.cr2.modify(|_, w| { + w.sadd() + .bits(u16::from(addr) << 1) + .nbytes() + .bits(bytes.len() as u8) + .rd_wrn() + .clear_bit() + .autoend() + .clear_bit() + }); + + // Send a START condition + self.i2c.cr2.modify(|_, w| w.start().set_bit()); + + // Wait until the transmit buffer is empty and there hasn't been any error condition + while { + let isr = self.i2c.isr.read(); + self.check_and_clear_error_flags(&isr)?; + isr.txis().bit_is_clear() && isr.tc().bit_is_clear() + } {} + + // Send out all individual bytes + for c in bytes { + self.send_byte(*c)?; + } + + // Wait until data was sent + while { + let isr = self.i2c.isr.read(); + self.check_and_clear_error_flags(&isr)?; + isr.tc().bit_is_clear() + } {} + + // Set up current address for reading + self.i2c.cr2.modify(|_, w| { + w.sadd() + .bits(u16::from(addr) << 1) + .nbytes() + .bits(buffer.len() as u8) + .rd_wrn() + .set_bit() + }); + + // Send another START condition + self.i2c.cr2.modify(|_, w| w.start().set_bit()); + + // Send the autoend after setting the start to get a restart + self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); + + // Now read in all bytes + for c in buffer.iter_mut() { + *c = self.recv_byte()?; + } + + // Check and clear flags if they somehow ended up set + self.check_and_clear_error_flags(&self.i2c.isr.read())?; + + Ok(()) + } + } + + impl Read for FMPI2c + where + I2C: Deref, + { + type Error = Error; + + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { + // Set up current address for reading + self.i2c.cr2.modify(|_, w| { + w.sadd() + .bits(u16::from(addr) << 1) + .nbytes() + .bits(buffer.len() as u8) + .rd_wrn() + .set_bit() + }); + + // Send a START condition + self.i2c.cr2.modify(|_, w| w.start().set_bit()); + + // Send the autoend after setting the start to get a restart + self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); + + // Now read in all bytes + for c in buffer.iter_mut() { + *c = self.recv_byte()?; + } + + // Check and clear flags if they somehow ended up set + self.check_and_clear_error_flags(&self.i2c.isr.read())?; + + Ok(()) + } + } + + impl Write for FMPI2c + where + I2C: Deref, + { + type Error = Error; + + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + // Set up current slave address for writing and enable autoending + self.i2c.cr2.modify(|_, w| { + w.sadd() + .bits(u16::from(addr) << 1) + .nbytes() + .bits(bytes.len() as u8) + .rd_wrn() + .clear_bit() + .autoend() + .set_bit() + }); + + // Send a START condition + self.i2c.cr2.modify(|_, w| w.start().set_bit()); + + // Send out all individual bytes + for c in bytes { + self.send_byte(*c)?; + } + + // Check and clear flags if they somehow ended up set + self.check_and_clear_error_flags(&self.i2c.isr.read())?; + + Ok(()) + } + } +} diff --git a/src/i2c.rs b/src/i2c.rs index e800427e..e6ce1519 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -1,5 +1,4 @@ use core::ops::Deref; -use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; use crate::pac::i2c1; use crate::rcc::{Enable, Reset}; @@ -18,6 +17,8 @@ use crate::gpio::{gpioa, gpiob, gpioc, gpioh}; use crate::rcc::Clocks; use crate::time::{Hertz, U32Ext}; +mod hal_02; + #[derive(Debug, Eq, PartialEq)] pub enum DutyCycle { Ratio2to1, @@ -264,7 +265,7 @@ where } trait I2cCommon { - fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error>; + fn write_bytes(&mut self, addr: u8, bytes: impl Iterator) -> Result<(), Error>; fn send_byte(&self, byte: u8) -> Result<(), Error>; @@ -275,7 +276,7 @@ impl I2cCommon for I2c where I2C: Instance, { - fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + fn write_bytes(&mut self, addr: u8, bytes: impl Iterator) -> Result<(), Error> { // Send a START condition self.i2c.cr1.modify(|_, w| w.start().set_bit()); @@ -313,7 +314,7 @@ where // Send bytes for c in bytes { - self.send_byte(*c)?; + self.send_byte(c)?; } // Fallthrough is success @@ -349,101 +350,3 @@ where Ok(value) } } - -impl WriteRead for I2c -where - I2C: Instance, -{ - type Error = Error; - - fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { - self.write_bytes(addr, bytes)?; - self.read(addr, buffer)?; - - Ok(()) - } -} - -impl Write for I2c -where - I2C: Instance, -{ - type Error = Error; - - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { - self.write_bytes(addr, bytes)?; - - // Send a STOP condition - self.i2c.cr1.modify(|_, w| w.stop().set_bit()); - - // Wait for STOP condition to transmit. - while self.i2c.cr1.read().stop().bit_is_set() {} - - // Fallthrough is success - Ok(()) - } -} - -impl Read for I2c -where - I2C: Instance, -{ - type Error = Error; - - fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { - if let Some((last, buffer)) = buffer.split_last_mut() { - // Send a START condition and set ACK bit - self.i2c - .cr1 - .modify(|_, w| w.start().set_bit().ack().set_bit()); - - // Wait until START condition was generated - while self.i2c.sr1.read().sb().bit_is_clear() {} - - // Also wait until signalled we're master and everything is waiting for us - loop { - let sr2 = self.i2c.sr2.read(); - if !(sr2.msl().bit_is_clear() && sr2.busy().bit_is_clear()) { - break; - } - } - - // Set up current address, we're trying to talk to - self.i2c - .dr - .write(|w| unsafe { w.bits((u32::from(addr) << 1) + 1) }); - - // Wait until address was sent - loop { - self.check_and_clear_error_flags()?; - if self.i2c.sr1.read().addr().bit_is_set() { - break; - } - } - - // Clear condition by reading SR2 - self.i2c.sr2.read(); - - // Receive bytes into buffer - for c in buffer { - *c = self.recv_byte()?; - } - - // Prepare to send NACK then STOP after next byte - self.i2c - .cr1 - .modify(|_, w| w.ack().clear_bit().stop().set_bit()); - - // Receive last byte - *last = self.recv_byte()?; - - // Wait for the STOP to be sent. - while self.i2c.cr1.read().stop().bit_is_set() {} - - // Fallthrough is success - Ok(()) - } else { - Err(Error::OVERRUN) - } - } -} diff --git a/src/i2c/hal_02.rs b/src/i2c/hal_02.rs new file mode 100644 index 00000000..440c0678 --- /dev/null +++ b/src/i2c/hal_02.rs @@ -0,0 +1,150 @@ +mod blocking { + use super::super::{Error, I2c, I2cCommon, Instance}; + use embedded_hal::blocking::i2c::{Read, Write, WriteIter, WriteIterRead, WriteRead}; + + impl WriteRead for I2c + where + I2C: Instance, + { + type Error = Error; + + fn write_read( + &mut self, + addr: u8, + bytes: &[u8], + buffer: &mut [u8], + ) -> Result<(), Self::Error> { + self.write_bytes(addr, bytes.iter().cloned())?; + self.read(addr, buffer)?; + + Ok(()) + } + } + + impl WriteIterRead for I2c + where + I2C: Instance, + { + type Error = Error; + + fn write_iter_read( + &mut self, + addr: u8, + bytes: B, + buffer: &mut [u8], + ) -> Result<(), Self::Error> + where + B: IntoIterator, + { + self.write_bytes(addr, bytes.into_iter())?; + self.read(addr, buffer)?; + + Ok(()) + } + } + + impl Write for I2c + where + I2C: Instance, + { + type Error = Error; + + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + self.write_bytes(addr, bytes.iter().cloned())?; + + // Send a STOP condition + self.i2c.cr1.modify(|_, w| w.stop().set_bit()); + + // Wait for STOP condition to transmit. + while self.i2c.cr1.read().stop().bit_is_set() {} + + // Fallthrough is success + Ok(()) + } + } + + impl WriteIter for I2c + where + I2C: Instance, + { + type Error = Error; + + fn write(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error> + where + B: IntoIterator, + { + self.write_bytes(addr, bytes.into_iter())?; + + // Send a STOP condition + self.i2c.cr1.modify(|_, w| w.stop().set_bit()); + + // Wait for STOP condition to transmit. + while self.i2c.cr1.read().stop().bit_is_set() {} + + // Fallthrough is success + Ok(()) + } + } + + impl Read for I2c + where + I2C: Instance, + { + type Error = Error; + + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + if let Some((last, buffer)) = buffer.split_last_mut() { + // Send a START condition and set ACK bit + self.i2c + .cr1 + .modify(|_, w| w.start().set_bit().ack().set_bit()); + + // Wait until START condition was generated + while self.i2c.sr1.read().sb().bit_is_clear() {} + + // Also wait until signalled we're master and everything is waiting for us + while { + let sr2 = self.i2c.sr2.read(); + sr2.msl().bit_is_clear() && sr2.busy().bit_is_clear() + } {} + + // Set up current address, we're trying to talk to + self.i2c + .dr + .write(|w| unsafe { w.bits((u32::from(addr) << 1) + 1) }); + + // Wait until address was sent + loop { + self.check_and_clear_error_flags()?; + if self.i2c.sr1.read().addr().bit_is_set() { + break; + } + } + + // Clear condition by reading SR2 + self.i2c.sr2.read(); + + // Receive bytes into buffer + for c in buffer { + *c = self.recv_byte()?; + } + + // Prepare to send NACK then STOP after next byte + self.i2c + .cr1 + .modify(|_, w| w.ack().clear_bit().stop().set_bit()); + + // Receive last byte + *last = self.recv_byte()?; + + // Wait for the STOP to be sent. + while self.i2c.cr1.read().stop().bit_is_set() {} + + // Fallthrough is success + Ok(()) + } else { + Err(Error::OVERRUN) + } + } + } +} From 0a7e710c378da070258d9fe78fbb2b85a1bcfac0 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 15:02:06 +0300 Subject: [PATCH 5/9] changes to support advanced PwmPin impls --- src/pwm.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pwm.rs b/src/pwm.rs index 77ca00fa..4e255fc0 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -1,5 +1,5 @@ use crate::{ - bb, hal as pwm, + bb, time::Hertz, timer::{General, Timer}, }; @@ -104,8 +104,9 @@ macro_rules! pwm_pin { } } - impl pwm::PwmPin for PwmChannel<$TIMX, $C> { + impl embedded_hal::PwmPin for PwmChannel<$TIMX, $C> { type Duty = u16; + fn disable(&mut self) { self.disable() } From d229c2795c0ff5da955212f9569128b929fd7fcc Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 15:41:50 +0300 Subject: [PATCH 6/9] move embedded-hal_02 to subdir for Delay --- src/delay/hal_02.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++ src/delay/mod.rs | 84 +++++++++++++++++++++++++- src/delay/syst.rs | 79 ------------------------ src/delay/timer.rs | 139 ------------------------------------------ src/dwt.rs | 5 +- 5 files changed, 227 insertions(+), 223 deletions(-) create mode 100644 src/delay/hal_02.rs delete mode 100644 src/delay/syst.rs delete mode 100644 src/delay/timer.rs diff --git a/src/delay/hal_02.rs b/src/delay/hal_02.rs new file mode 100644 index 00000000..248422ce --- /dev/null +++ b/src/delay/hal_02.rs @@ -0,0 +1,143 @@ +//! 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 cast::{u16, u32}; +use cortex_m::peripheral::SYST; +use embedded_hal::blocking::delay::{DelayMs, DelayUs}; + +use super::{Delay, Wait}; + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u32) { + // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF. + const MAX_RVR: u32 = 0x00FF_FFFF; + + let mut total_rvr = us * (self.clk.0 / 8_000_000); + + while total_rvr != 0 { + let current_rvr = if total_rvr <= MAX_RVR { + total_rvr + } else { + MAX_RVR + }; + + self.tim.set_reload(current_rvr); + self.tim.clear_current(); + self.tim.enable_counter(); + + // Update the tracking variable while we are waiting... + total_rvr -= current_rvr; + + while !self.tim.has_wrapped() {} + + self.tim.disable_counter(); + } + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u32) { + self.delay_us(ms * 1_000); + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u16) { + self.delay_us(u32(us)) + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u16) { + self.delay_ms(u32(ms)); + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u8) { + self.delay_us(u32(us)) + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u8) { + self.delay_ms(u32(ms)); + } +} + +impl DelayUs for Delay +where + Self: Wait, +{ + /// Sleep for up to 2^32-1 microseconds (~71 minutes). + fn delay_us(&mut self, us: u32) { + // Set up prescaler so that a tick takes exactly 1 µs. + // + // For example, if the clock is set to 48 MHz, with a prescaler of 48 + // we'll get ticks that are 1 µs long. This means that we can write the + // delay value directly to the auto-reload register (ARR). + let psc = u16(self.clk.0 / 1_000_000).expect("Prescaler does not fit in u16"); + let arr = us; + self.wait(psc, arr); + } +} + +impl DelayMs for Delay +where + Self: Wait, +{ + /// Sleep for up to (2^32)/2-1 milliseconds (~24 days). + /// If the `ms` value is larger than 2147483647, the code will panic. + fn delay_ms(&mut self, ms: u32) { + // See next section for explanation why the usable range is reduced. + assert!(ms <= 2_147_483_647); // (2^32)/2-1 + + // Set up prescaler so that a tick takes exactly 0.5 ms. + // + // For example, if the clock is set to 48 MHz, with a prescaler of 24'000 + // we'll get ticks that are 0.5 ms long. This means that we can write the + // delay value multipled by two to the auto-reload register (ARR). + // + // Note that we cannot simply use a prescaler value where the tick corresponds + // to 1 ms, because then a clock of 100 MHz would correspond to a prescaler + // value of 100'000, which doesn't fit in the 16-bit PSC register. + // + // Unfortunately this means that only one half of the full 32-bit range + // can be used, but 24 days should be plenty of usable delay time. + let psc = u16(self.clk.0 / 1000 / 2).expect("Prescaler does not fit in u16"); + + // Since PSC = 0.5 ms, double the value for the ARR + let arr = ms << 1; + + self.wait(psc, arr); + } +} + +impl DelayUs for Delay +where + Self: Wait, +{ + /// Sleep for up to 2^16-1 microseconds (~65 milliseconds). + fn delay_us(&mut self, us: u16) { + // See DelayUs for explanations. + let psc = u16(self.clk.0 / 1_000_000).expect("Prescaler does not fit in u16"); + let arr = u32(us); + self.wait(psc, arr); + } +} + +impl DelayMs for Delay +where + Self: Wait, +{ + /// Sleep for up to (2^16)-1 milliseconds (~65 seconds). + fn delay_ms(&mut self, ms: u16) { + // See DelayMs for explanations. Since the value range is only 16 bit, + // we don't need an assert here. + let psc = u16(self.clk.0 / 1000 / 2).expect("Prescaler does not fit in u16"); + let arr = u32(ms) << 1; + self.wait(psc, arr); + } +} diff --git a/src/delay/mod.rs b/src/delay/mod.rs index 2e1fbb09..fd4b98b7 100644 --- a/src/delay/mod.rs +++ b/src/delay/mod.rs @@ -1,7 +1,14 @@ //! Delays -mod syst; +mod hal_02; +use crate::{ + pac, + rcc::Clocks, + timer::{General, Timer}, +}; +use core::cmp::max; +use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use crate::time::Hertz; @@ -19,4 +26,77 @@ impl Delay { } } -mod timer; +impl Delay { + /// Configures the system timer (SysTick) as a delay provider + pub fn new(mut tim: SYST, clocks: &Clocks) -> Self { + tim.set_clock_source(SystClkSource::External); + Self { + tim, + clk: clocks.hclk(), + } + } +} + +mod sealed { + pub trait Wait { + fn wait(&mut self, prescaler: u16, auto_reload_register: u32); + } +} +use sealed::Wait; + +macro_rules! hal { + ($($TIM:ty: ($tim:ident),)+) => { + $( + impl Timer<$TIM> { + pub fn delay(self) -> Delay<$TIM> { + let Self { tim, clk } = self; + + // Enable one-pulse mode (counter stops counting at the next update + // event, clearing the CEN bit) + tim.cr1.modify(|_, w| w.opm().enabled()); + + Delay { tim, clk } + } + } + + impl Delay<$TIM> { + /// Configures the timer as a delay provider + pub fn $tim(tim: $TIM, clocks: &Clocks) -> Self { + Timer::new(tim, clocks).delay() + } + } + + impl Wait for Delay<$TIM> { + fn wait(&mut self, prescaler: u16, auto_reload_register: u32) { + // Write Prescaler (PSC) + self.tim.set_prescaler(prescaler); + + // Write Auto-Reload Register (ARR) + // Note: Make it impossible to set the ARR value to 0, since this + // would cause an infinite loop. + self.tim.set_auto_reload(max(1, auto_reload_register)).unwrap(); + + // Trigger update event (UEV) in the event generation register (EGR) + // in order to immediately apply the config + self.tim.trigger_update(); + + // Configure the counter in one-pulse mode (counter stops counting at + // the next updateevent, clearing the CEN bit) and enable the counter. + self.tim.cr1.write(|w| w.opm().set_bit().cen().set_bit()); + + // Wait for CEN bit to clear + while self.tim.is_counter_enabled() { /* wait */ } + } + } + )+ + } +} + +hal! { + pac::TIM5: (tim5), +} + +#[cfg(feature = "tim2")] +hal! { + pac::TIM2: (tim2), +} diff --git a/src/delay/syst.rs b/src/delay/syst.rs deleted file mode 100644 index f80dcf7c..00000000 --- a/src/delay/syst.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! System timer (SysTick) as a delay provider. - -use cast::u32; -use cortex_m::peripheral::syst::SystClkSource; -use cortex_m::peripheral::SYST; - -use crate::rcc::Clocks; -use embedded_hal::blocking::delay::{DelayMs, DelayUs}; - -use super::Delay; - -impl Delay { - /// Configures the system timer (SysTick) as a delay provider - pub fn new(mut tim: SYST, clocks: &Clocks) -> Self { - tim.set_clock_source(SystClkSource::External); - Self { - tim, - clk: clocks.hclk(), - } - } -} - -impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u32) { - self.delay_us(ms * 1_000); - } -} - -impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u16) { - self.delay_ms(u32(ms)); - } -} - -impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u8) { - self.delay_ms(u32(ms)); - } -} - -impl DelayUs for Delay { - fn delay_us(&mut self, us: u32) { - // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF. - const MAX_RVR: u32 = 0x00FF_FFFF; - - let mut total_rvr = us * (self.clk.0 / 8_000_000); - - while total_rvr != 0 { - let current_rvr = if total_rvr <= MAX_RVR { - total_rvr - } else { - MAX_RVR - }; - - self.tim.set_reload(current_rvr); - self.tim.clear_current(); - self.tim.enable_counter(); - - // Update the tracking variable while we are waiting... - total_rvr -= current_rvr; - - while !self.tim.has_wrapped() {} - - self.tim.disable_counter(); - } - } -} - -impl DelayUs for Delay { - fn delay_us(&mut self, us: u16) { - self.delay_us(u32(us)) - } -} - -impl DelayUs for Delay { - fn delay_us(&mut self, us: u8) { - self.delay_us(u32(us)) - } -} diff --git a/src/delay/timer.rs b/src/delay/timer.rs deleted file mode 100644 index 157aa53d..00000000 --- a/src/delay/timer.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! Delay implementation based on general-purpose 32 bit timers. -//! -//! TIM2 and TIM5 are a general purpose 32-bit auto-reload up/downcounter with -//! a 16-bit prescaler. - -use core::cmp::max; - -use cast::{u16, u32}; -use embedded_hal::blocking::delay::{DelayMs, DelayUs}; - -use crate::{ - pac, - rcc::Clocks, - timer::{General, Timer}, -}; - -use super::Delay; - -macro_rules! hal { - ($($TIM:ty: ($tim:ident, $waitfn:ident),)+) => { - $( - fn $waitfn(tim: &mut $TIM, prescaler: u16, auto_reload_register: u32) { - // Write Prescaler (PSC) - tim.set_prescaler(prescaler); - - // Write Auto-Reload Register (ARR) - // Note: Make it impossible to set the ARR value to 0, since this - // would cause an infinite loop. - tim.set_auto_reload(max(1, auto_reload_register)).unwrap(); - - // Trigger update event (UEV) in the event generation register (EGR) - // in order to immediately apply the config - tim.trigger_update(); - - // Configure the counter in one-pulse mode (counter stops counting at - // the next updateevent, clearing the CEN bit) and enable the counter. - tim.cr1.write(|w| w.opm().set_bit().cen().set_bit()); - - // Wait for CEN bit to clear - while tim.is_counter_enabled() { /* wait */ } - } - - impl Timer<$TIM> { - pub fn delay(self) -> Delay<$TIM> { - let Self { tim, clk } = self; - - // Enable one-pulse mode (counter stops counting at the next update - // event, clearing the CEN bit) - tim.cr1.modify(|_, w| w.opm().enabled()); - - Delay { tim, clk } - } - } - - impl Delay<$TIM> { - /// Configures the timer as a delay provider - pub fn $tim(tim: $TIM, clocks: &Clocks) -> Self { - Timer::new(tim, clocks).delay() - } - } - - impl DelayUs for Delay<$TIM> { - /// Sleep for up to 2^32-1 microseconds (~71 minutes). - fn delay_us(&mut self, us: u32) { - // Set up prescaler so that a tick takes exactly 1 µs. - // - // For example, if the clock is set to 48 MHz, with a prescaler of 48 - // we'll get ticks that are 1 µs long. This means that we can write the - // delay value directly to the auto-reload register (ARR). - let psc = u16(self.clk.0 / 1_000_000) - .expect("Prescaler does not fit in u16"); - let arr = us; - $waitfn(&mut self.tim, psc, arr); - } - } - - impl DelayUs for Delay<$TIM> { - /// Sleep for up to 2^16-1 microseconds (~65 milliseconds). - fn delay_us(&mut self, us: u16) { - // See DelayUs for explanations. - let psc = u16(self.clk.0 / 1_000_000) - .expect("Prescaler does not fit in u16"); - let arr = u32(us); - $waitfn(&mut self.tim, psc, arr); - } - } - - impl DelayMs for Delay<$TIM> { - /// Sleep for up to (2^32)/2-1 milliseconds (~24 days). - /// If the `ms` value is larger than 2147483647, the code will panic. - fn delay_ms(&mut self, ms: u32) { - // See next section for explanation why the usable range is reduced. - assert!(ms <= 2_147_483_647); // (2^32)/2-1 - - // Set up prescaler so that a tick takes exactly 0.5 ms. - // - // For example, if the clock is set to 48 MHz, with a prescaler of 24'000 - // we'll get ticks that are 0.5 ms long. This means that we can write the - // delay value multipled by two to the auto-reload register (ARR). - // - // Note that we cannot simply use a prescaler value where the tick corresponds - // to 1 ms, because then a clock of 100 MHz would correspond to a prescaler - // value of 100'000, which doesn't fit in the 16-bit PSC register. - // - // Unfortunately this means that only one half of the full 32-bit range - // can be used, but 24 days should be plenty of usable delay time. - let psc = u16(self.clk.0 / 1000 / 2) - .expect("Prescaler does not fit in u16"); - - // Since PSC = 0.5 ms, double the value for the ARR - let arr = ms << 1; - - $waitfn(&mut self.tim, psc, arr); - } - } - - impl DelayMs for Delay<$TIM> { - /// Sleep for up to (2^16)-1 milliseconds (~65 seconds). - fn delay_ms(&mut self, ms: u16) { - // See DelayMs for explanations. Since the value range is only 16 bit, - // we don't need an assert here. - let psc = u16(self.clk.0 / 1000 / 2) - .expect("Prescaler does not fit in u16"); - let arr = u32(ms) << 1; - $waitfn(&mut self.tim, psc, arr); - } - } - )+ - } -} - -hal! { - pac::TIM5: (tim5, wait_tim5), -} - -#[cfg(feature = "tim2")] -hal! { - pac::TIM2: (tim2, wait_tim2), -} diff --git a/src/dwt.rs b/src/dwt.rs index 66db5dd2..cc8ba047 100644 --- a/src/dwt.rs +++ b/src/dwt.rs @@ -3,7 +3,6 @@ use crate::rcc::Clocks; use crate::time::Hertz; use cortex_m::peripheral::{DCB, DWT}; -use embedded_hal::blocking::delay::{DelayMs, DelayUs}; pub trait DwtExt { fn constrain(self, dcb: DCB, clocks: &Clocks) -> Dwt; @@ -98,7 +97,7 @@ impl Delay { } // Implement DelayUs/DelayMs for various integer types -impl> DelayUs for Delay { +impl> embedded_hal::blocking::delay::DelayUs for Delay { fn delay_us(&mut self, us: T) { // Convert us to ticks let start = DWT::get_cycle_count(); @@ -106,7 +105,7 @@ impl> DelayUs for Delay { Delay::delay_ticks(start, ticks); } } -impl> DelayMs for Delay { +impl> embedded_hal::blocking::delay::DelayMs for Delay { fn delay_ms(&mut self, ms: T) { // Convert ms to ticks let start = DWT::get_cycle_count(); From f92c090429e1c50f27b4278eead49008e2f5e779 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 16:42:45 +0300 Subject: [PATCH 7/9] changes to support advanced Qei impls --- src/qei.rs | 15 +++++---------- src/rng.rs | 2 +- src/watchdog.rs | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/qei.rs b/src/qei.rs index 9ebf89fd..85745fb5 100644 --- a/src/qei.rs +++ b/src/qei.rs @@ -1,10 +1,5 @@ //! # Quadrature Encoder Interface -use crate::{ - hal::{self, Direction}, - pac::RCC, - rcc, - timer::General, -}; +use crate::{pac::RCC, rcc, timer::General}; pub trait Pins {} use crate::timer::{CPin, C1, C2}; @@ -48,18 +43,18 @@ impl Qei { } } -impl hal::Qei for Qei { +impl embedded_hal::Qei for Qei { type Count = TIM::Width; fn count(&self) -> Self::Count { self.tim.read_count() as Self::Count } - fn direction(&self) -> Direction { + fn direction(&self) -> embedded_hal::Direction { if self.tim.read_direction() { - hal::Direction::Upcounting + embedded_hal::Direction::Upcounting } else { - hal::Direction::Downcounting + embedded_hal::Direction::Downcounting } } } diff --git a/src/rng.rs b/src/rng.rs index 0e0d74d4..159cd11c 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -23,13 +23,13 @@ use core::cmp; use core::mem; -use crate::hal::blocking::rng; use crate::pac; use crate::pac::RNG; use crate::rcc::{Clocks, Enable, Reset}; use crate::time::U32Ext; use core::num::NonZeroU32; use core::ops::Shl; +use embedded_hal::blocking::rng; use rand_core::RngCore; /// Random number generator specific errors diff --git a/src/watchdog.rs b/src/watchdog.rs index 904a8cb4..23f9a552 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -1,10 +1,10 @@ //! Watchdog peripherals use crate::{ - hal::watchdog::{Watchdog, WatchdogEnable}, pac::{DBGMCU, IWDG}, time::MilliSeconds, }; +use embedded_hal::watchdog::{Watchdog, WatchdogEnable}; /// Wraps the Independent Watchdog (IWDG) peripheral pub struct IndependentWatchdog { From 0efa16a835d5dd2a9136b7dc132e43e5f13739b4 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 13:13:48 +0300 Subject: [PATCH 8/9] move embedded-hal_02 to subdir for SPI --- src/spi.rs | 186 +++++++++------------------------------------- src/spi/hal_02.rs | 178 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+), 152 deletions(-) create mode 100644 src/spi/hal_02.rs diff --git a/src/spi.rs b/src/spi.rs index 9fed1da2..1938918a 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -4,8 +4,35 @@ use core::ptr; use crate::dma::traits::PeriAddress; use crate::gpio::{Const, NoPin, PinA, PushPull, SetAlternate}; -use embedded_hal::spi; -pub use embedded_hal::spi::{Mode, Phase, Polarity}; + +/// 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, +} + +mod hal_02; use crate::pac::{spi1, RCC, SPI1, SPI2}; use crate::rcc; @@ -141,7 +168,7 @@ where pub fn new( spi: SPI, mut pins: PINS, - mode: Mode, + mode: impl Into, freq: impl Into, clocks: &Clocks, ) -> Self { @@ -155,7 +182,7 @@ where pins.set_alt_mode(); Self::_new(spi, pins) - .pre_init(mode, freq.into(), SPI::clock(clocks)) + .pre_init(mode.into(), freq.into(), SPI::clock(clocks)) .init() } @@ -174,7 +201,7 @@ where pub fn new_bidi( spi: SPI, mut pins: PINS, - mode: Mode, + mode: impl Into, freq: impl Into, clocks: &Clocks, ) -> Self { @@ -188,7 +215,7 @@ where pins.set_alt_mode(); Self::_new(spi, pins) - .pre_init(mode, freq.into(), SPI::clock(clocks)) + .pre_init(mode.into(), freq.into(), SPI::clock(clocks)) .init() } @@ -277,7 +304,7 @@ where } /// Pre initializing the SPI bus. - pub fn pre_init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self { + fn pre_init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self { // disable SS output self.spi.cr2.write(|w| w.ssoe().clear_bit()); @@ -493,148 +520,3 @@ where type MemSize = u8; } - -impl spi::FullDuplex for Spi -where - SPI: Instance, -{ - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.check_read() - } - - fn send(&mut self, byte: u8) -> nb::Result<(), Error> { - self.check_send(byte) - } -} - -impl spi::FullDuplex for Spi -where - SPI: Instance, -{ - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.spi.cr1.modify(|_, w| w.bidioe().clear_bit()); - self.check_read() - } - - fn send(&mut self, byte: u8) -> nb::Result<(), Error> { - self.spi.cr1.modify(|_, w| w.bidioe().set_bit()); - self.check_send(byte) - } -} - -mod blocking { - use super::{Error, Instance, Spi, TransferModeBidi, TransferModeNormal}; - use embedded_hal::blocking::spi::{Operation, Transactional, Transfer, Write, WriteIter}; - use embedded_hal::spi::FullDuplex; - - impl Transfer for Spi - where - Self: FullDuplex, - SPI: Instance, - { - type Error = Error; - - fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { - for word in words.iter_mut() { - nb::block!(self.send(*word))?; - *word = nb::block!(self.read())?; - } - - Ok(words) - } - } - - impl Write for Spi - where - Self: FullDuplex, - SPI: Instance, - { - type Error = Error; - - fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { - for word in words { - nb::block!(self.send(*word))?; - nb::block!(self.read())?; - } - - Ok(()) - } - } - - impl Write for Spi - where - Self: FullDuplex, - SPI: Instance, - { - type Error = Error; - - fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { - for word in words { - nb::block!(self.send(*word))?; - } - - Ok(()) - } - } - - impl WriteIter for Spi - where - Self: FullDuplex, - SPI: Instance, - { - type Error = Error; - - fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> - where - WI: IntoIterator, - { - for word in words.into_iter() { - nb::block!(self.send(word))?; - nb::block!(self.read())?; - } - - Ok(()) - } - } - - impl WriteIter for Spi - where - Self: FullDuplex, - SPI: Instance, - { - type Error = Error; - - fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> - where - WI: IntoIterator, - { - for word in words.into_iter() { - nb::block!(self.send(word))?; - } - - Ok(()) - } - } - - impl Transactional for Spi - where - Self: Write + Transfer, - { - type Error = Error; - - fn exec<'a>(&mut self, operations: &mut [Operation<'a, W>]) -> Result<(), Error> { - for op in operations { - match op { - Operation::Write(w) => self.write(w)?, - Operation::Transfer(t) => self.transfer(t).map(|_| ())?, - } - } - - Ok(()) - } - } -} diff --git a/src/spi/hal_02.rs b/src/spi/hal_02.rs new file mode 100644 index 00000000..54d7b9d8 --- /dev/null +++ b/src/spi/hal_02.rs @@ -0,0 +1,178 @@ +pub use embedded_hal::spi::{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(), + } + } +} + +mod nb { + use super::super::{Error, Instance, Spi, TransferModeBidi, TransferModeNormal}; + use embedded_hal::spi::FullDuplex; + + impl FullDuplex for Spi + where + SPI: Instance, + { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.check_read() + } + + fn send(&mut self, byte: u8) -> nb::Result<(), Error> { + self.check_send(byte) + } + } + + impl FullDuplex for Spi + where + SPI: Instance, + { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.spi.cr1.modify(|_, w| w.bidioe().clear_bit()); + self.check_read() + } + + fn send(&mut self, byte: u8) -> nb::Result<(), Error> { + self.spi.cr1.modify(|_, w| w.bidioe().set_bit()); + self.check_send(byte) + } + } +} + +mod blocking { + use super::super::{Error, Instance, Spi, TransferModeBidi, TransferModeNormal}; + use embedded_hal::blocking::spi::{Operation, Transactional, Transfer, Write, WriteIter}; + use embedded_hal::spi::FullDuplex; + + impl Transfer for Spi + where + Self: FullDuplex, + SPI: Instance, + { + type Error = Error; + + fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { + for word in words.iter_mut() { + nb::block!(self.send(*word))?; + *word = nb::block!(self.read())?; + } + + Ok(words) + } + } + + impl Write for Spi + where + Self: FullDuplex, + SPI: Instance, + { + type Error = Error; + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + for word in words { + nb::block!(self.send(*word))?; + nb::block!(self.read())?; + } + + Ok(()) + } + } + + impl Write for Spi + where + Self: FullDuplex, + SPI: Instance, + { + type Error = Error; + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + for word in words { + nb::block!(self.send(*word))?; + } + + Ok(()) + } + } + + impl WriteIter for Spi + where + Self: FullDuplex, + SPI: Instance, + { + type Error = Error; + + fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> + where + WI: IntoIterator, + { + for word in words.into_iter() { + nb::block!(self.send(word))?; + nb::block!(self.read())?; + } + + Ok(()) + } + } + + impl WriteIter for Spi + where + Self: FullDuplex, + SPI: Instance, + { + type Error = Error; + + fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> + where + WI: IntoIterator, + { + for word in words.into_iter() { + nb::block!(self.send(word))?; + } + + Ok(()) + } + } + + impl Transactional for Spi + where + Self: Write + Transfer, + { + type Error = Error; + + fn exec<'a>(&mut self, operations: &mut [Operation<'a, W>]) -> Result<(), Error> { + for op in operations { + match op { + Operation::Write(w) => self.write(w)?, + Operation::Transfer(t) => self.transfer(t).map(|_| ())?, + } + } + + Ok(()) + } + } +} From 4678607af512a7c2cbcbc86bcccd0f14e11a8eaf Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 27 Dec 2021 22:40:58 +0300 Subject: [PATCH 9/9] changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe916cf9..ac20736a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed +- Move `embedded-hal` implementations to subdirs [#404] - Qei macro cleanups [#403] - Update RTIC to 1.0 [#401] - Finish SDIO data transmission before querying card status in `write_block` [#395] @@ -51,7 +52,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). [#393]: https://github.com/stm32-rs/stm32f4xx-hal/pull/393 [#395]: https://github.com/stm32-rs/stm32f4xx-hal/pull/395 [#401]: https://github.com/stm32-rs/stm32f4xx-hal/pull/401 -[#401]: https://github.com/stm32-rs/stm32f4xx-hal/pull/403 +[#403]: https://github.com/stm32-rs/stm32f4xx-hal/pull/403 +[#404]: https://github.com/stm32-rs/stm32f4xx-hal/pull/404 ## [v0.10.1] - 2021-10-26