diff --git a/embedded-hal-bus/src/spi/critical_section.rs b/embedded-hal-bus/src/spi/critical_section.rs index 5bad960af..4334cf1fe 100644 --- a/embedded-hal-bus/src/spi/critical_section.rs +++ b/embedded-hal-bus/src/spi/critical_section.rs @@ -5,6 +5,7 @@ use embedded_hal::digital::OutputPin; use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice}; use super::DeviceError; +use crate::spi::shared::transaction; /// `critical-section`-based shared bus [`SpiDevice`] implementation. /// @@ -66,29 +67,7 @@ where critical_section::with(|cs| { let bus = &mut *self.bus.borrow_ref_mut(cs); - self.cs.set_low().map_err(DeviceError::Cs)?; - - let op_res = operations.iter_mut().try_for_each(|op| match op { - Operation::Read(buf) => bus.read(buf), - Operation::Write(buf) => bus.write(buf), - Operation::Transfer(read, write) => bus.transfer(read, write), - Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), - Operation::DelayUs(us) => { - bus.flush()?; - self.delay.delay_us(*us); - Ok(()) - } - }); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - op_res.map_err(DeviceError::Spi)?; - flush_res.map_err(DeviceError::Spi)?; - cs_res.map_err(DeviceError::Cs)?; - - Ok(()) + transaction(operations, bus, &mut self.delay, &mut self.cs) }) } } diff --git a/embedded-hal-bus/src/spi/mod.rs b/embedded-hal-bus/src/spi/mod.rs index 090f44649..8a5f2b83f 100644 --- a/embedded-hal-bus/src/spi/mod.rs +++ b/embedded-hal-bus/src/spi/mod.rs @@ -12,6 +12,8 @@ mod mutex; #[cfg(feature = "std")] pub use mutex::*; mod critical_section; +mod shared; + pub use self::critical_section::*; #[cfg(feature = "defmt-03")] diff --git a/embedded-hal-bus/src/spi/mutex.rs b/embedded-hal-bus/src/spi/mutex.rs index d1288b995..059fae26e 100644 --- a/embedded-hal-bus/src/spi/mutex.rs +++ b/embedded-hal-bus/src/spi/mutex.rs @@ -4,6 +4,7 @@ use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice}; use std::sync::Mutex; use super::DeviceError; +use crate::spi::shared::transaction; /// `std` `Mutex`-based shared bus [`SpiDevice`] implementation. /// @@ -63,28 +64,6 @@ where fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> { let bus = &mut *self.bus.lock().unwrap(); - self.cs.set_low().map_err(DeviceError::Cs)?; - - let op_res = operations.iter_mut().try_for_each(|op| match op { - Operation::Read(buf) => bus.read(buf), - Operation::Write(buf) => bus.write(buf), - Operation::Transfer(read, write) => bus.transfer(read, write), - Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), - Operation::DelayUs(us) => { - bus.flush()?; - self.delay.delay_us(*us); - Ok(()) - } - }); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - op_res.map_err(DeviceError::Spi)?; - flush_res.map_err(DeviceError::Spi)?; - cs_res.map_err(DeviceError::Cs)?; - - Ok(()) + transaction(operations, bus, &mut self.delay, &mut self.cs) } } diff --git a/embedded-hal-bus/src/spi/refcell.rs b/embedded-hal-bus/src/spi/refcell.rs index d407620be..414f4d12e 100644 --- a/embedded-hal-bus/src/spi/refcell.rs +++ b/embedded-hal-bus/src/spi/refcell.rs @@ -4,6 +4,7 @@ use embedded_hal::digital::OutputPin; use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice}; use super::DeviceError; +use crate::spi::shared::transaction; /// `RefCell`-based shared bus [`SpiDevice`] implementation. /// @@ -62,28 +63,6 @@ where fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> { let bus = &mut *self.bus.borrow_mut(); - self.cs.set_low().map_err(DeviceError::Cs)?; - - let op_res = operations.iter_mut().try_for_each(|op| match op { - Operation::Read(buf) => bus.read(buf), - Operation::Write(buf) => bus.write(buf), - Operation::Transfer(read, write) => bus.transfer(read, write), - Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), - Operation::DelayUs(us) => { - bus.flush()?; - self.delay.delay_us(*us); - Ok(()) - } - }); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - op_res.map_err(DeviceError::Spi)?; - flush_res.map_err(DeviceError::Spi)?; - cs_res.map_err(DeviceError::Cs)?; - - Ok(()) + transaction(operations, bus, &mut self.delay, &mut self.cs) } } diff --git a/embedded-hal-bus/src/spi/shared.rs b/embedded-hal-bus/src/spi/shared.rs new file mode 100644 index 000000000..233169ced --- /dev/null +++ b/embedded-hal-bus/src/spi/shared.rs @@ -0,0 +1,44 @@ +use embedded_hal::delay::DelayUs; +use embedded_hal::digital::OutputPin; +use embedded_hal::spi::{ErrorType, Operation, SpiBus}; + +use crate::spi::DeviceError; + +/// Common implementation to perform a transaction against the device. +#[inline] +pub fn transaction( + operations: &mut [Operation], + bus: &mut BUS, + delay: &mut D, + cs: &mut CS, +) -> Result<(), DeviceError> +where + BUS: SpiBus + ErrorType, + CS: OutputPin, + D: DelayUs, + Word: Copy, +{ + cs.set_low().map_err(DeviceError::Cs)?; + + let op_res = operations.iter_mut().try_for_each(|op| match op { + Operation::Read(buf) => bus.read(buf), + Operation::Write(buf) => bus.write(buf), + Operation::Transfer(read, write) => bus.transfer(read, write), + Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), + Operation::DelayUs(us) => { + bus.flush()?; + delay.delay_us(*us); + Ok(()) + } + }); + + // On failure, it's important to still flush and deassert CS. + let flush_res = bus.flush(); + let cs_res = cs.set_high(); + + op_res.map_err(DeviceError::Spi)?; + flush_res.map_err(DeviceError::Spi)?; + cs_res.map_err(DeviceError::Cs)?; + + Ok(()) +}