From 2408e36b61ca6828b59803720210134ede248a83 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Fri, 19 Nov 2021 13:13:48 +0300 Subject: [PATCH] both embedded-hals for SPI --- src/gpio/hal_02.rs | 2 +- src/gpio/hal_1.rs | 2 +- src/spi.rs | 187 +++++++++----------------------------------- src/spi/hal_02.rs | 178 ++++++++++++++++++++++++++++++++++++++++++ src/spi/hal_1.rs | 191 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 406 insertions(+), 154 deletions(-) create mode 100644 src/spi/hal_02.rs create mode 100644 src/spi/hal_1.rs diff --git a/src/gpio/hal_02.rs b/src/gpio/hal_02.rs index 39cb16aa1..1cb36554a 100644 --- a/src/gpio/hal_02.rs +++ b/src/gpio/hal_02.rs @@ -11,7 +11,7 @@ use embedded_hal::digital::v2::{ }; impl From for super::PinState { - fn from(state: PinState) -> super::PinState { + fn from(state: PinState) -> Self { match state { PinState::Low => Self::Low, PinState::High => Self::High, diff --git a/src/gpio/hal_1.rs b/src/gpio/hal_1.rs index 2884052d0..5ae330310 100644 --- a/src/gpio/hal_1.rs +++ b/src/gpio/hal_1.rs @@ -11,7 +11,7 @@ use embedded_hal_one::digital::blocking::{ pub use embedded_hal_one::digital::PinState; impl From for super::PinState { - fn from(state: PinState) -> super::PinState { + fn from(state: PinState) -> Self { match state { PinState::Low => Self::Low, PinState::High => Self::High, diff --git a/src/spi.rs b/src/spi.rs index 839ee4e53..541118ccb 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -4,8 +4,36 @@ use core::ptr; use crate::dma::traits::PeriAddress; use crate::gpio::{Const, NoPin, 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; +mod hal_1; #[allow(unused)] #[cfg(feature = "gpiod")] @@ -438,7 +466,7 @@ where pub fn new( spi: SPI, mut pins: (SCK, MISO, MOSI), - mode: Mode, + mode: impl Into, freq: impl Into, clocks: &Clocks, ) -> Self { @@ -458,7 +486,7 @@ where pins, transfer_mode: TransferModeNormal, } - .pre_init(mode, freq.into(), SPI::clock(clocks)) + .pre_init(mode.into(), freq.into(), SPI::clock(clocks)) .init() } @@ -480,7 +508,7 @@ where pub fn new_bidi( spi: SPI, mut pins: (SCK, MISO, MOSI), - mode: Mode, + mode: impl Into, freq: impl Into, clocks: &Clocks, ) -> Self { @@ -500,7 +528,7 @@ where pins, transfer_mode: TransferModeBidi, } - .pre_init(mode, freq.into(), SPI::clock(&clocks)) + .pre_init(mode.into(), freq.into(), SPI::clock(&clocks)) .init() } @@ -593,7 +621,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()); @@ -809,148 +837,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 000000000..54d7b9d87 --- /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(()) + } + } +} diff --git a/src/spi/hal_1.rs b/src/spi/hal_1.rs new file mode 100644 index 000000000..24c4a807b --- /dev/null +++ b/src/spi/hal_1.rs @@ -0,0 +1,191 @@ +pub use embedded_hal_one::spi::{Error, ErrorKind, 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 Error for super::Error { + fn kind(&self) -> ErrorKind { + match self { + Self::Overrun => ErrorKind::Overrun, + Self::ModeFault => ErrorKind::ModeFault, + Self::Crc => ErrorKind::Other, + } + } +} + +mod nb { + use super::super::{Error, Instance, Spi, TransferModeBidi, TransferModeNormal}; + use embedded_hal_one::spi::nb::FullDuplex; + + impl FullDuplex for Spi + where + SPI: Instance, + { + type Error = Error; + + fn read(&mut self) -> nb::Result { + self.check_read() + } + + fn write(&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 write(&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_one::spi::{ + blocking::{Operation, Transactional, TransferInplace, Write, WriteIter}, + nb::FullDuplex, + }; + + impl TransferInplace for Spi + where + Self: FullDuplex, + SPI: Instance, + { + type Error = Error; + + fn transfer_inplace(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + for word in words.iter_mut() { + nb::block!(self.write(*word))?; + *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!(>::write(self, *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!(>::write(self, *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!(>::write(self, 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!(>::write(self, word))?; + } + + Ok(()) + } + } + + impl Transactional for Spi + where + Self: Write + TransferInplace, + { + 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::TransferInplace(t) => self.transfer_inplace(t)?, + _ => todo!(), + } + } + + Ok(()) + } + } +}