From f30ff9cadcf575100a4e08c972d2f161172a3fc9 Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Fri, 8 Jul 2022 15:47:47 +0200 Subject: Shared buses with SetConfig --- .../src/shared_bus/blocking/i2c.rs | 84 ++++++++++++++++++++++ .../src/shared_bus/blocking/spi.rs | 50 +++++++++++++ embassy-embedded-hal/src/shared_bus/i2c.rs | 78 ++++++++++++++++++++ embassy-embedded-hal/src/shared_bus/spi.rs | 61 ++++++++++++++++ 4 files changed, 273 insertions(+) (limited to 'embassy-embedded-hal/src/shared_bus') diff --git a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs index 2c762fe14..6f5f07051 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs @@ -7,6 +7,7 @@ use embedded_hal_1::i2c::blocking::{I2c, Operation}; use embedded_hal_1::i2c::ErrorType; use crate::shared_bus::i2c::I2cBusDeviceError; +use crate::SetConfig; pub struct I2cBusDevice<'a, M: RawMutex, BUS> { bus: &'a Mutex>, @@ -82,3 +83,86 @@ where todo!() } } + +pub struct I2cBusDeviceWithConfig<'a, M: RawMutex, BUS, C> { + bus: &'a Mutex>, + config: C, +} + +impl<'a, M: RawMutex, BUS, C> I2cBusDeviceWithConfig<'a, M, BUS, C> { + pub fn new(bus: &'a Mutex>, config: C) -> Self { + Self { bus, config } + } +} + +impl<'a, M: RawMutex, BUS, C> ErrorType for I2cBusDeviceWithConfig<'a, M, BUS, C> +where + BUS: ErrorType, +{ + type Error = I2cBusDeviceError; +} + +impl I2c for I2cBusDeviceWithConfig<'_, M, BUS, C> +where + M: RawMutex, + BUS: I2c + SetConfig, +{ + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.bus.lock(|bus| { + let mut bus = bus.borrow_mut(); + bus.set_config(&self.config); + bus.read(address, buffer).map_err(I2cBusDeviceError::I2c) + }) + } + + fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { + self.bus.lock(|bus| { + let mut bus = bus.borrow_mut(); + bus.set_config(&self.config); + bus.write(address, bytes).map_err(I2cBusDeviceError::I2c) + }) + } + + fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> { + self.bus.lock(|bus| { + let mut bus = bus.borrow_mut(); + bus.set_config(&self.config); + bus.write_read(address, wr_buffer, rd_buffer) + .map_err(I2cBusDeviceError::I2c) + }) + } + + fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> { + let _ = address; + let _ = operations; + todo!() + } + + fn write_iter>(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error> { + let _ = addr; + let _ = bytes; + todo!() + } + + fn write_iter_read>( + &mut self, + addr: u8, + bytes: B, + buffer: &mut [u8], + ) -> Result<(), Self::Error> { + let _ = addr; + let _ = bytes; + let _ = buffer; + todo!() + } + + fn transaction_iter<'a, O: IntoIterator>>( + &mut self, + address: u8, + operations: O, + ) -> Result<(), Self::Error> { + let _ = address; + let _ = operations; + todo!() + } +} diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs index c08bcbf62..d54ca6bfa 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs @@ -8,6 +8,7 @@ use embedded_hal_1::spi; use embedded_hal_1::spi::blocking::{SpiBusFlush, SpiDevice}; use crate::shared_bus::spi::SpiBusDeviceError; +use crate::SetConfig; pub struct SpiBusDevice<'a, M: RawMutex, BUS, CS> { bus: &'a Mutex>, @@ -55,3 +56,52 @@ where }) } } + +pub struct SpiBusDeviceWithConfig<'a, M: RawMutex, BUS, CS, C> { + bus: &'a Mutex>, + cs: CS, + config: C, +} + +impl<'a, M: RawMutex, BUS, CS, C> SpiBusDeviceWithConfig<'a, M, BUS, CS, C> { + pub fn new(bus: &'a Mutex>, cs: CS, config: C) -> Self { + Self { bus, cs, config } + } +} + +impl<'a, M: RawMutex, BUS, CS, C> spi::ErrorType for SpiBusDeviceWithConfig<'a, M, BUS, CS, C> +where + BUS: spi::ErrorType, + CS: OutputPin, +{ + type Error = SpiBusDeviceError; +} + +impl SpiDevice for SpiBusDeviceWithConfig<'_, M, BUS, CS, C> +where + M: RawMutex, + BUS: SpiBusFlush + SetConfig, + CS: OutputPin, +{ + type Bus = BUS; + + fn transaction(&mut self, f: impl FnOnce(&mut Self::Bus) -> Result) -> Result { + self.bus.lock(|bus| { + let mut bus = bus.borrow_mut(); + bus.set_config(&self.config); + self.cs.set_low().map_err(SpiBusDeviceError::Cs)?; + + let f_res = f(&mut bus); + + // On failure, it's important to still flush and deassert CS. + let flush_res = bus.flush(); + let cs_res = self.cs.set_high(); + + let f_res = f_res.map_err(SpiBusDeviceError::Spi)?; + flush_res.map_err(SpiBusDeviceError::Spi)?; + cs_res.map_err(SpiBusDeviceError::Cs)?; + + Ok(f_res) + }) + } +} diff --git a/embassy-embedded-hal/src/shared_bus/i2c.rs b/embassy-embedded-hal/src/shared_bus/i2c.rs index e8131288a..0e964773c 100644 --- a/embassy-embedded-hal/src/shared_bus/i2c.rs +++ b/embassy-embedded-hal/src/shared_bus/i2c.rs @@ -29,6 +29,8 @@ use embassy::blocking_mutex::raw::RawMutex; use embassy::mutex::Mutex; use embedded_hal_async::i2c; +use crate::SetConfig; + #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum I2cBusDeviceError { I2c(BUS), @@ -116,3 +118,79 @@ where async move { todo!() } } } + +pub struct I2cBusDeviceWithConfig<'a, M: RawMutex, BUS, C> { + bus: &'a Mutex, + config: C, +} + +impl<'a, M: RawMutex, BUS, C> I2cBusDeviceWithConfig<'a, M, BUS, C> { + pub fn new(bus: &'a Mutex, config: C) -> Self { + Self { bus, config } + } +} + +impl<'a, M: RawMutex, BUS, C> i2c::ErrorType for I2cBusDeviceWithConfig<'a, M, BUS, C> +where + BUS: i2c::ErrorType, +{ + type Error = I2cBusDeviceError; +} + +impl i2c::I2c for I2cBusDeviceWithConfig<'_, M, BUS, C> +where + M: RawMutex + 'static, + BUS: i2c::I2c + SetConfig + 'static, +{ + type ReadFuture<'a> = impl Future> + 'a where Self: 'a; + + fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { + async move { + let mut bus = self.bus.lock().await; + bus.set_config(&self.config); + bus.read(address, buffer).await.map_err(I2cBusDeviceError::I2c)?; + Ok(()) + } + } + + type WriteFuture<'a> = impl Future> + 'a where Self: 'a; + + fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { + async move { + let mut bus = self.bus.lock().await; + bus.set_config(&self.config); + bus.write(address, bytes).await.map_err(I2cBusDeviceError::I2c)?; + Ok(()) + } + } + + type WriteReadFuture<'a> = impl Future> + 'a where Self: 'a; + + fn write_read<'a>( + &'a mut self, + address: u8, + wr_buffer: &'a [u8], + rd_buffer: &'a mut [u8], + ) -> Self::WriteReadFuture<'a> { + async move { + let mut bus = self.bus.lock().await; + bus.set_config(&self.config); + bus.write_read(address, wr_buffer, rd_buffer) + .await + .map_err(I2cBusDeviceError::I2c)?; + Ok(()) + } + } + + type TransactionFuture<'a, 'b> = impl Future> + 'a where Self: 'a, 'b: 'a; + + fn transaction<'a, 'b>( + &'a mut self, + address: u8, + operations: &'a mut [embedded_hal_async::i2c::Operation<'b>], + ) -> Self::TransactionFuture<'a, 'b> { + let _ = address; + let _ = operations; + async move { todo!() } + } +} diff --git a/embassy-embedded-hal/src/shared_bus/spi.rs b/embassy-embedded-hal/src/shared_bus/spi.rs index fd4b6d565..04378c330 100644 --- a/embassy-embedded-hal/src/shared_bus/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/spi.rs @@ -34,6 +34,8 @@ use embedded_hal_1::digital::blocking::OutputPin; use embedded_hal_1::spi::ErrorType; use embedded_hal_async::spi; +use crate::SetConfig; + #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum SpiBusDeviceError { Spi(BUS), @@ -109,3 +111,62 @@ where } } } + +pub struct SpiBusDeviceWithConfig<'a, M: RawMutex, BUS, CS, C> { + bus: &'a Mutex, + cs: CS, + config: C, +} + +impl<'a, M: RawMutex, BUS, CS, C> SpiBusDeviceWithConfig<'a, M, BUS, CS, C> { + pub fn new(bus: &'a Mutex, cs: CS, config: C) -> Self { + Self { bus, cs, config } + } +} + +impl<'a, M: RawMutex, BUS, CS, C> spi::ErrorType for SpiBusDeviceWithConfig<'a, M, BUS, CS, C> +where + BUS: spi::ErrorType, + CS: OutputPin, +{ + type Error = SpiBusDeviceError; +} + +impl spi::SpiDevice for SpiBusDeviceWithConfig<'_, M, BUS, CS, C> +where + M: RawMutex + 'static, + BUS: spi::SpiBusFlush + SetConfig + 'static, + CS: OutputPin, +{ + type Bus = BUS; + + type TransactionFuture<'a, R, F, Fut> = impl Future> + 'a + where + Self: 'a, R: 'a, F: FnOnce(*mut Self::Bus) -> Fut + 'a, + Fut: Future::Error>> + 'a; + + fn transaction<'a, R, F, Fut>(&'a mut self, f: F) -> Self::TransactionFuture<'a, R, F, Fut> + where + R: 'a, + F: FnOnce(*mut Self::Bus) -> Fut + 'a, + Fut: Future::Error>> + 'a, + { + async move { + let mut bus = self.bus.lock().await; + bus.set_config(&self.config); + self.cs.set_low().map_err(SpiBusDeviceError::Cs)?; + + let f_res = f(&mut *bus).await; + + // On failure, it's important to still flush and deassert CS. + let flush_res = bus.flush().await; + let cs_res = self.cs.set_high(); + + let f_res = f_res.map_err(SpiBusDeviceError::Spi)?; + flush_res.map_err(SpiBusDeviceError::Spi)?; + cs_res.map_err(SpiBusDeviceError::Cs)?; + + Ok(f_res) + } + } +} -- cgit