From 4b4fe7245ba62569bbee684b22c8e7155af55a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Wed, 6 Jul 2022 23:02:16 +0200 Subject: [PATCH 1/8] Add EH 0.2 impls + example docs --- .../src/shared_bus/blocking/i2c.rs | 59 ++++++++++++++++++ .../src/shared_bus/blocking/spi.rs | 60 +++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs index 2c762fe14..bfbcb6c2e 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs @@ -1,4 +1,21 @@ //! Blocking shared I2C bus +//! +//! # Example (nrf52) +//! +//! ```rust +//! use embassy_embedded_hal::shared_bus::blocking::i2c::I2cBusDevice; +//! use embassy::blocking_mutex::{NoopMutex, raw::NoopRawMutex}; +//! +//! static I2C_BUS: Forever>>> = Forever::new(); +//! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +//! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, Config::default()); +//! let i2c_bus = NoopMutex::new(RefCell::new(i2c)); +//! let i2c_bus = I2C_BUS.put(i2c_bus); +//! +//! let i2c_dev1 = I2cBusDevice::new(i2c_bus); +//! let mpu = Mpu6050::new(i2c_dev1); +//! ``` + use core::cell::RefCell; use embassy::blocking_mutex::raw::RawMutex; @@ -82,3 +99,45 @@ where todo!() } } + +impl<'a, M, BUS, E> embedded_hal_02::blocking::i2c::Write for I2cBusDevice<'_, M, BUS> +where + M: RawMutex, + BUS: embedded_hal_02::blocking::i2c::Write, +{ + type Error = I2cBusDeviceError; + + fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Self::Error> { + self.bus + .lock(|bus| bus.borrow_mut().write(addr, bytes).map_err(I2cBusDeviceError::I2c)) + } +} + +impl<'a, M, BUS, E> embedded_hal_02::blocking::i2c::Read for I2cBusDevice<'_, M, BUS> +where + M: RawMutex, + BUS: embedded_hal_02::blocking::i2c::Read, +{ + type Error = I2cBusDeviceError; + + fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Self::Error> { + self.bus + .lock(|bus| bus.borrow_mut().read(addr, bytes).map_err(I2cBusDeviceError::I2c)) + } +} + +impl<'a, M, BUS, E> embedded_hal_02::blocking::i2c::WriteRead for I2cBusDevice<'_, M, BUS> +where + M: RawMutex, + BUS: embedded_hal_02::blocking::i2c::WriteRead, +{ + type Error = I2cBusDeviceError; + + fn write_read<'w>(&mut self, addr: u8, bytes: &'w [u8], buffer: &'w mut [u8]) -> Result<(), Self::Error> { + self.bus.lock(|bus| { + bus.borrow_mut() + .write_read(addr, bytes, buffer) + .map_err(I2cBusDeviceError::I2c) + }) + } +} diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs index c08bcbf62..81cf97457 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs @@ -1,4 +1,23 @@ //! Blocking shared SPI bus +//! +//! # Example (nrf52) +//! +//! ```rust +//! use embassy_embedded_hal::shared_bus::blocking::spi::SpiBusDevice; +//! use embassy::blocking_mutex::{NoopMutex, raw::NoopRawMutex}; +//! +//! static SPI_BUS: Forever>>> = Forever::new(); +//! let irq = interrupt::take!(SPIM3); +//! let spi = Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, Config::default()); +//! let spi_bus = NoopMutex::new(RefCell::new(spi)); +//! let spi_bus = SPI_BUS.put(spi_bus); +//! +//! // Device 1, using embedded-hal compatible driver for ST7735 LCD display +//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard); +//! let spi_dev1 = SpiBusDevice::new(spi_bus, cs_pin1); +//! let display1 = ST7735::new(spi_dev1, dc1, rst1, Default::default(), false, 160, 128); +//! ``` + use core::cell::RefCell; use embassy::blocking_mutex::raw::RawMutex; @@ -55,3 +74,44 @@ where }) } } + +impl<'d, M, BUS, CS, BusErr, CsErr> embedded_hal_02::blocking::spi::Transfer for SpiBusDevice<'_, M, BUS, CS> +where + M: RawMutex, + BUS: embedded_hal_02::blocking::spi::Transfer, + CS: OutputPin, +{ + type Error = SpiBusDeviceError; + fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { + self.bus.lock(|bus| { + let mut bus = bus.borrow_mut(); + self.cs.set_low().map_err(SpiBusDeviceError::Cs)?; + let f_res = bus.transfer(words); + let cs_res = self.cs.set_high(); + let f_res = f_res.map_err(SpiBusDeviceError::Spi)?; + cs_res.map_err(SpiBusDeviceError::Cs)?; + Ok(f_res) + }) + } +} + +impl<'d, M, BUS, CS, BusErr, CsErr> embedded_hal_02::blocking::spi::Write for SpiBusDevice<'_, M, BUS, CS> +where + M: RawMutex, + BUS: embedded_hal_02::blocking::spi::Write, + CS: OutputPin, +{ + type Error = SpiBusDeviceError; + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + self.bus.lock(|bus| { + let mut bus = bus.borrow_mut(); + self.cs.set_low().map_err(SpiBusDeviceError::Cs)?; + let f_res = bus.write(words); + let cs_res = self.cs.set_high(); + let f_res = f_res.map_err(SpiBusDeviceError::Spi)?; + cs_res.map_err(SpiBusDeviceError::Cs)?; + Ok(f_res) + }) + } +} From 2460d21fa43e0f454ce4068761ac34f36929df8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Wed, 6 Jul 2022 23:25:38 +0200 Subject: [PATCH 2/8] Add EH 1.0 impls for stm32 i2c --- embassy-stm32/src/i2c/v1.rs | 69 +++++++++++++++++++++++++++++++++++++ embassy-stm32/src/i2c/v2.rs | 44 +++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 87a4f9699..cf6011c26 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -280,6 +280,75 @@ impl<'d, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T> { } } +#[cfg(feature = "unstable-traits")] +mod eh1 { + use super::super::{RxDma, TxDma}; + use super::*; + + impl embedded_hal_1::i2c::Error for Error { + fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { + match *self { + Self::Bus => embedded_hal_1::i2c::ErrorKind::Bus, + Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss, + Self::Nack => { + embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Unknown) + } + Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other, + Self::Crc => embedded_hal_1::i2c::ErrorKind::Other, + Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun, + Self::ZeroLengthTransfer => embedded_hal_1::i2c::ErrorKind::Other, + } + } + } + + impl<'d, T: Instance, TXDMA: TxDma, RXDMA: RxDma> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> { + type Error = Error; + } + + impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for I2c<'d, T> { + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, buffer) + } + + fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, buffer) + } + + fn write_iter(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error> + where + B: IntoIterator, + { + todo!(); + } + + fn write_iter_read(&mut self, _address: u8, _bytes: B, _buffer: &mut [u8]) -> Result<(), Self::Error> + where + B: IntoIterator, + { + todo!(); + } + + fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, wr_buffer, rd_buffer) + } + + fn transaction<'a>( + &mut self, + _address: u8, + _operations: &mut [embedded_hal_1::i2c::blocking::Operation<'a>], + ) -> Result<(), Self::Error> { + todo!(); + } + + fn transaction_iter<'a, O>(&mut self, _address: u8, _operations: O) -> Result<(), Self::Error> + where + O: IntoIterator>, + { + todo!(); + } + } +} + enum Mode { Fast, Standard, diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1a085e782..69988fd6e 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -854,6 +854,50 @@ mod eh1 { impl<'d, T: Instance, TXDMA: TxDma, RXDMA: RxDma> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> { type Error = Error; } + + + impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for I2c<'d, T> { + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, buffer) + } + + fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, buffer) + } + + fn write_iter(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error> + where + B: IntoIterator, + { + todo!(); + } + + fn write_iter_read(&mut self, _address: u8, _bytes: B, _buffer: &mut [u8]) -> Result<(), Self::Error> + where + B: IntoIterator, + { + todo!(); + } + + fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, wr_buffer, rd_buffer) + } + + fn transaction<'a>( + &mut self, + _address: u8, + _operations: &mut [embedded_hal_1::i2c::blocking::Operation<'a>], + ) -> Result<(), Self::Error> { + todo!(); + } + + fn transaction_iter<'a, O>(&mut self, _address: u8, _operations: O) -> Result<(), Self::Error> + where + O: IntoIterator>, + { + todo!(); + } + } } cfg_if::cfg_if! { From 02812754ec8fb13c26163e0e741b46f12abba202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Wed, 6 Jul 2022 23:31:30 +0200 Subject: [PATCH 3/8] rustfmt --- embassy-stm32/src/i2c/v2.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 69988fd6e..9309d7725 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -855,7 +855,6 @@ mod eh1 { type Error = Error; } - impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for I2c<'d, T> { fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { self.blocking_read(address, buffer) From 1ed5b387f98ceae501d73675994ccb64ccd4985f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Wed, 6 Jul 2022 23:45:08 +0200 Subject: [PATCH 4/8] v2 fix --- embassy-stm32/src/i2c/v2.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 9309d7725..9d8dd5ca1 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -855,7 +855,9 @@ mod eh1 { type Error = Error; } - impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for I2c<'d, T> { + impl<'d, T: Instance, TXDMA: TxDma, RXDMA: RxDma> embedded_hal_1::i2c::blocking::I2c + for I2c<'d, T, TXDMA, RXDMA> + { fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { self.blocking_read(address, buffer) } From 0fe818f4f8343668baa9e04697a7095de830f5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Wed, 6 Jul 2022 23:56:44 +0200 Subject: [PATCH 5/8] v1 fix --- embassy-stm32/src/i2c/v1.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index cf6011c26..72cc46c04 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -301,7 +301,7 @@ mod eh1 { } } - impl<'d, T: Instance, TXDMA: TxDma, RXDMA: RxDma> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> { + impl<'d, T: Instance> embedded_hal_1::i2c::ErrorType for I2c<'d, T> { type Error = Error; } From be731b222e24e7463dcdf907c60077cd6b1c3f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Thu, 7 Jul 2022 00:00:17 +0200 Subject: [PATCH 6/8] Cleanup --- embassy-stm32/src/i2c/v1.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 72cc46c04..f56e50f9b 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -282,7 +282,6 @@ impl<'d, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T> { #[cfg(feature = "unstable-traits")] mod eh1 { - use super::super::{RxDma, TxDma}; use super::*; impl embedded_hal_1::i2c::Error for Error { From 399e7a47916a0f7cf8f7da654aa09eebe924054b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Thu, 7 Jul 2022 08:32:00 +0200 Subject: [PATCH 7/8] NoDma --- embassy-stm32/src/i2c/v2.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 9d8dd5ca1..d7aa65a16 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -855,9 +855,7 @@ mod eh1 { type Error = Error; } - impl<'d, T: Instance, TXDMA: TxDma, RXDMA: RxDma> embedded_hal_1::i2c::blocking::I2c - for I2c<'d, T, TXDMA, RXDMA> - { + impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for I2c<'d, T, NoDma, NoDma> { fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { self.blocking_read(address, buffer) } From 01ef03f446f59bacff8a617d96f497f9bc46902e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 7 Jul 2022 15:45:59 +0200 Subject: [PATCH 8/8] stm32/i2c: impl ErrorType for all. --- embassy-stm32/src/i2c/v2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index d7aa65a16..3161d9d53 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -851,7 +851,7 @@ mod eh1 { } } - impl<'d, T: Instance, TXDMA: TxDma, RXDMA: RxDma> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> { + impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> { type Error = Error; }