From 4032fc06556312eab27488f05efe1803ade47b45 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 Jan 2022 22:39:06 +0100 Subject: Support unstable-trait feature for stm32 --- embassy-traits/src/adapter.rs | 200 ++++++++++++++++++++++++++++++------------ embassy-traits/src/gpio.rs | 57 ------------ embassy-traits/src/i2c.rs | 192 ---------------------------------------- embassy-traits/src/lib.rs | 4 - embassy-traits/src/spi.rs | 61 ------------- embassy-traits/src/uart.rs | 36 -------- 6 files changed, 145 insertions(+), 405 deletions(-) delete mode 100644 embassy-traits/src/gpio.rs delete mode 100644 embassy-traits/src/i2c.rs delete mode 100644 embassy-traits/src/spi.rs delete mode 100644 embassy-traits/src/uart.rs (limited to 'embassy-traits/src') diff --git a/embassy-traits/src/adapter.rs b/embassy-traits/src/adapter.rs index ce7dd411f..415b5e814 100644 --- a/embassy-traits/src/adapter.rs +++ b/embassy-traits/src/adapter.rs @@ -1,6 +1,6 @@ use core::future::Future; -use embedded_hal::blocking; -use embedded_hal::serial; +use embedded_hal_02::blocking; +use embedded_hal_02::serial; /// BlockingAsync is a wrapper that implements async traits using blocking peripherals. This allows /// driver writers to depend on the async traits while still supporting embedded-hal peripheral implementations. @@ -20,24 +20,37 @@ impl BlockingAsync { } // -// I2C implementatinos +// I2C implementations // - -impl crate::i2c::I2c for BlockingAsync +impl embedded_hal_1::i2c::ErrorType for BlockingAsync where - E: 'static, + E: embedded_hal_1::i2c::Error + 'static, T: blocking::i2c::WriteRead + blocking::i2c::Read + blocking::i2c::Write, { type Error = E; +} - #[rustfmt::skip] - type WriteFuture<'a> where Self: 'a = impl Future> + 'a; - #[rustfmt::skip] - type ReadFuture<'a> where Self: 'a = impl Future> + 'a; - #[rustfmt::skip] - type WriteReadFuture<'a> where Self: 'a = impl Future> + 'a; +impl embedded_hal_async::i2c::I2c for BlockingAsync +where + E: embedded_hal_1::i2c::Error + 'static, + T: blocking::i2c::WriteRead + + blocking::i2c::Read + + blocking::i2c::Write, +{ + type WriteFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + type ReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + type WriteReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { self.wrapped.read(address, buffer) } @@ -55,33 +68,46 @@ where ) -> Self::WriteReadFuture<'a> { async move { self.wrapped.write_read(address, bytes, buffer) } } + + type TransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn transaction<'a>( + &'a mut self, + address: u8, + operations: &mut [embedded_hal_async::i2c::Operation<'a>], + ) -> Self::TransactionFuture<'a> { + let _ = address; + let _ = operations; + async move { todo!() } + } } // // SPI implementatinos // -impl crate::spi::Spi for BlockingAsync +impl embedded_hal_async::spi::ErrorType for BlockingAsync where - T: blocking::spi::Write, + E: embedded_hal_1::spi::Error, + T: blocking::spi::Transfer + blocking::spi::Write, { type Error = E; } -impl crate::spi::FullDuplex for BlockingAsync +impl embedded_hal_async::spi::ReadWrite for BlockingAsync where - E: 'static, - Word: Clone, - T: blocking::spi::Transfer + blocking::spi::Write, + E: embedded_hal_1::spi::Error + 'static, + T: blocking::spi::Transfer + blocking::spi::Write, { - #[rustfmt::skip] - type WriteReadFuture<'a> where Word: 'a, Self: 'a = impl Future> + 'a; + type TransferFuture<'a> + where + Self: 'a, + = impl Future> + 'a; - fn read_write<'a>( - &'a mut self, - read: &'a mut [Word], - write: &'a [Word], - ) -> Self::WriteReadFuture<'a> { + fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Self::TransferFuture<'a> { async move { // Ensure we write the expected bytes for i in 0..core::cmp::min(read.len(), write.len()) { @@ -91,53 +117,111 @@ where Ok(()) } } + + type TransferInPlaceFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn transfer_in_place<'a>(&'a mut self, _: &'a mut [u8]) -> Self::TransferInPlaceFuture<'a> { + async move { todo!() } + } + + type TransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn transaction<'a>( + &'a mut self, + _: &'a mut [embedded_hal_async::spi::Operation<'a, u8>], + ) -> Self::TransactionFuture<'a> { + async move { todo!() } + } } -impl crate::spi::Write for BlockingAsync +impl embedded_hal_async::spi::Write for BlockingAsync where - E: 'static, - Word: Clone, - T: blocking::spi::Write, + E: embedded_hal_1::spi::Error + 'static, + T: blocking::spi::Transfer + blocking::spi::Write, { - #[rustfmt::skip] - type WriteFuture<'a> where Word: 'a, Self: 'a = impl Future> + 'a; + type WriteFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { + async move { + self.wrapped.write(data)?; + Ok(()) + } + } + + type WriteTransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; - fn write<'a>(&'a mut self, data: &'a [Word]) -> Self::WriteFuture<'a> { - async move { self.wrapped.write(data) } + fn write_transaction<'a>(&'a mut self, _: &'a [&'a [u8]]) -> Self::WriteTransactionFuture<'a> { + async move { todo!() } } } -impl crate::spi::Read for BlockingAsync +impl embedded_hal_async::spi::Read for BlockingAsync where - E: 'static, - Word: Clone, - T: blocking::spi::Transfer + blocking::spi::Write, + E: embedded_hal_1::spi::Error + 'static, + T: blocking::spi::Transfer + blocking::spi::Write, { - #[rustfmt::skip] - type ReadFuture<'a> where Word: 'a, Self: 'a = impl Future> + 'a; + type ReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; - fn read<'a>(&'a mut self, data: &'a mut [Word]) -> Self::ReadFuture<'a> { + fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { self.wrapped.transfer(data)?; Ok(()) } } + + type ReadTransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn read_transaction<'a>( + &'a mut self, + _: &'a mut [&'a mut [u8]], + ) -> Self::ReadTransactionFuture<'a> { + async move { todo!() } + } } // Uart implementatinos -impl crate::uart::Read for BlockingAsync +impl embedded_hal_1::serial::ErrorType for BlockingAsync +where + T: serial::Read, + E: embedded_hal_1::serial::Error + 'static, +{ + type Error = E; +} + +impl embedded_hal_async::serial::Read for BlockingAsync where - T: serial::Read, + T: serial::Read, + E: embedded_hal_1::serial::Error + 'static, { - #[rustfmt::skip] - type ReadFuture<'a> where T: 'a = impl Future> + 'a; + type ReadFuture<'a> + where + T: 'a, + = impl Future> + 'a; fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { let mut pos = 0; while pos < buf.len() { match self.wrapped.read() { Err(nb::Error::WouldBlock) => {} - Err(_) => return Err(crate::uart::Error::Other), + Err(nb::Error::Other(e)) => return Err(e), Ok(b) => { buf[pos] = b; pos += 1; @@ -149,18 +233,24 @@ where } } -impl crate::uart::Write for BlockingAsync +impl embedded_hal_async::serial::Write for BlockingAsync where - T: blocking::serial::Write, + T: blocking::serial::Write + serial::Read, + E: embedded_hal_1::serial::Error + 'static, { - #[rustfmt::skip] - type WriteFuture<'a> where T: 'a = impl Future> + 'a; + type WriteFuture<'a> + where + T: 'a, + = impl Future> + 'a; fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { - async move { - self.wrapped - .bwrite_all(buf) - .map_err(|_| crate::uart::Error::Other)?; - self.wrapped.bflush().map_err(|_| crate::uart::Error::Other) - } + async move { self.wrapped.bwrite_all(buf) } + } + + type FlushFuture<'a> + where + T: 'a, + = impl Future> + 'a; + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + async move { self.wrapped.bflush() } } } diff --git a/embassy-traits/src/gpio.rs b/embassy-traits/src/gpio.rs deleted file mode 100644 index 3752c8d60..000000000 --- a/embassy-traits/src/gpio.rs +++ /dev/null @@ -1,57 +0,0 @@ -use core::future::Future; - -/// Wait for a pin to become high. -pub trait WaitForHigh { - type Future<'a>: Future + 'a - where - Self: 'a; - - /// Wait for a pin to become high. - /// - /// If the pin is already high, the future completes immediately. - /// Otherwise, it completes when it becomes high. - fn wait_for_high(&mut self) -> Self::Future<'_>; -} - -/// Wait for a pin to become low. -pub trait WaitForLow { - type Future<'a>: Future + 'a - where - Self: 'a; - - /// Wait for a pin to become low. - /// - /// If the pin is already low, the future completes immediately. - /// Otherwise, it completes when it becomes low. - fn wait_for_low(&mut self) -> Self::Future<'_>; -} - -/// Wait for a rising edge (transition from low to high) -pub trait WaitForRisingEdge { - type Future<'a>: Future + 'a - where - Self: 'a; - - /// Wait for a rising edge (transition from low to high) - fn wait_for_rising_edge(&mut self) -> Self::Future<'_>; -} - -/// Wait for a falling edge (transition from high to low) -pub trait WaitForFallingEdge { - type Future<'a>: Future + 'a - where - Self: 'a; - - /// Wait for a falling edge (transition from high to low) - fn wait_for_falling_edge(&'_ mut self) -> Self::Future<'_>; -} - -/// Wait for any edge (any transition, high to low or low to high) -pub trait WaitForAnyEdge { - type Future<'a>: Future + 'a - where - Self: 'a; - - /// Wait for any edge (any transition, high to low or low to high) - fn wait_for_any_edge(&mut self) -> Self::Future<'_>; -} diff --git a/embassy-traits/src/i2c.rs b/embassy-traits/src/i2c.rs deleted file mode 100644 index 4e2e8e2f0..000000000 --- a/embassy-traits/src/i2c.rs +++ /dev/null @@ -1,192 +0,0 @@ -//! Async I2C API -//! -//! This API supports 7-bit and 10-bit addresses. Traits feature an `AddressMode` -//! marker type parameter. Two implementation of the `AddressMode` exist: -//! `SevenBitAddress` and `TenBitAddress`. -//! -//! Through this marker types it is possible to implement each address mode for -//! the traits independently in `embedded-hal` implementations and device drivers -//! can depend only on the mode that they support. -//! -//! Additionally, the I2C 10-bit address mode has been developed to be fully -//! backwards compatible with the 7-bit address mode. This allows for a -//! software-emulated 10-bit addressing implementation if the address mode -//! is not supported by the hardware. -//! -//! Since 7-bit addressing is the mode of the majority of I2C devices, -//! `SevenBitAddress` has been set as default mode and thus can be omitted if desired. -//! -//! ### Device driver compatible only with 7-bit addresses -//! -//! For demonstration purposes the address mode parameter has been omitted in this example. -//! -//! ``` -//! # use embassy_traits::i2c::I2c; -//! const ADDR: u8 = 0x15; -//! # const TEMP_REGISTER: u8 = 0x1; -//! pub struct TemperatureSensorDriver { -//! i2c: I2C, -//! } -//! -//! impl TemperatureSensorDriver -//! where -//! I2C: I2c, -//! { -//! pub fn read_temperature(&mut self) -> Result { -//! let mut temp = [0]; -//! self.i2c -//! .write_read(ADDR, &[TEMP_REGISTER], &mut temp) -//! .await -//! .and(Ok(temp[0])) -//! } -//! } -//! ``` -//! -//! ### Device driver compatible only with 10-bit addresses -//! -//! ``` -//! # use embassy_traits::i2c::{TenBitAddress, I2c}; -//! const ADDR: u16 = 0x158; -//! # const TEMP_REGISTER: u8 = 0x1; -//! pub struct TemperatureSensorDriver { -//! i2c: I2C, -//! } -//! -//! impl TemperatureSensorDriver -//! where -//! I2C: I2c, -//! { -//! pub fn read_temperature(&mut self) -> Result { -//! let mut temp = [0]; -//! self.i2c -//! .write_read(ADDR, &[TEMP_REGISTER], &mut temp) -//! .await -//! .and(Ok(temp[0])) -//! } -//! } -//! ``` - -use core::future::Future; - -mod private { - pub trait Sealed {} -} - -/// Address mode (7-bit / 10-bit) -/// -/// Note: This trait is sealed and should not be implemented outside of this crate. -pub trait AddressMode: private::Sealed {} - -/// 7-bit address mode type -pub type SevenBitAddress = u8; - -/// 10-bit address mode type -pub type TenBitAddress = u16; - -impl private::Sealed for SevenBitAddress {} -impl private::Sealed for TenBitAddress {} - -impl AddressMode for SevenBitAddress {} - -impl AddressMode for TenBitAddress {} - -pub trait I2c { - /// Error type - type Error; - - type WriteFuture<'a>: Future> + 'a - where - Self: 'a; - type ReadFuture<'a>: Future> + 'a - where - Self: 'a; - type WriteReadFuture<'a>: Future> + 'a - where - Self: 'a; - - /// Reads enough bytes from slave with `address` to fill `buffer` - /// - /// # I2C Events (contract) - /// - /// ``` text - /// Master: ST SAD+R MAK MAK ... NMAK SP - /// Slave: SAK B0 B1 ... BN - /// ``` - /// - /// Where - /// - /// - `ST` = start condition - /// - `SAD+R` = slave address followed by bit 1 to indicate reading - /// - `SAK` = slave acknowledge - /// - `Bi` = ith byte of data - /// - `MAK` = master acknowledge - /// - `NMAK` = master no acknowledge - /// - `SP` = stop condition - fn read<'a>(&'a mut self, address: A, buffer: &'a mut [u8]) -> Self::ReadFuture<'a>; - - /// Sends bytes to slave with address `address` - /// - /// # I2C Events (contract) - /// - /// ``` text - /// Master: ST SAD+W B0 B1 ... BN SP - /// Slave: SAK SAK SAK ... SAK - /// ``` - /// - /// Where - /// - /// - `ST` = start condition - /// - `SAD+W` = slave address followed by bit 0 to indicate writing - /// - `SAK` = slave acknowledge - /// - `Bi` = ith byte of data - /// - `SP` = stop condition - fn write<'a>(&'a mut self, address: A, bytes: &'a [u8]) -> Self::WriteFuture<'a>; - - /// Sends bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a - /// single transaction* - /// - /// # I2C Events (contract) - /// - /// ``` text - /// Master: ST SAD+W O0 O1 ... OM SR SAD+R MAK MAK ... NMAK SP - /// Slave: SAK SAK SAK ... SAK SAK I0 I1 ... IN - /// ``` - /// - /// Where - /// - /// - `ST` = start condition - /// - `SAD+W` = slave address followed by bit 0 to indicate writing - /// - `SAK` = slave acknowledge - /// - `Oi` = ith outgoing byte of data - /// - `SR` = repeated start condition - /// - `SAD+R` = slave address followed by bit 1 to indicate reading - /// - `Ii` = ith incoming byte of data - /// - `MAK` = master acknowledge - /// - `NMAK` = master no acknowledge - /// - `SP` = stop condition - fn write_read<'a>( - &'a mut self, - address: A, - bytes: &'a [u8], - buffer: &'a mut [u8], - ) -> Self::WriteReadFuture<'a>; -} - -pub trait WriteIter { - /// Error type - type Error; - - type WriteIterFuture<'a, V>: Future> + 'a - where - V: 'a + IntoIterator, - Self: 'a; - - /// Sends bytes to slave with address `address` - /// - /// # I2C Events (contract) - /// - /// Same as `I2c::write` - fn write_iter<'a, U>(&'a mut self, address: A, bytes: U) -> Self::WriteIterFuture<'a, U> - where - U: IntoIterator + 'a; -} diff --git a/embassy-traits/src/lib.rs b/embassy-traits/src/lib.rs index a5342b77e..a41d0106f 100644 --- a/embassy-traits/src/lib.rs +++ b/embassy-traits/src/lib.rs @@ -5,8 +5,4 @@ pub mod adapter; pub mod delay; pub mod flash; -pub mod gpio; -pub mod i2c; pub mod rng; -pub mod spi; -pub mod uart; diff --git a/embassy-traits/src/spi.rs b/embassy-traits/src/spi.rs deleted file mode 100644 index 6beb442ba..000000000 --- a/embassy-traits/src/spi.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Async SPI API - -use core::future::Future; - -/// Full duplex (master mode) -/// -/// # Notes -/// -/// - It's the task of the user of this interface to manage the slave select lines -/// -/// - Due to how full duplex SPI works each `read` call must be preceded by a `write` call. -/// -/// - `read` calls only return the data received with the last `write` call. -/// Previously received data is discarded -/// -/// - Data is only guaranteed to be clocked out when the `read` call succeeds. -/// The slave select line shouldn't be released before that. -/// -/// - Some SPIs can work with 8-bit *and* 16-bit words. You can overload this trait with different -/// `Word` types to allow operation in both modes. - -pub trait Spi { - /// An enumeration of SPI errors - type Error; -} - -pub trait FullDuplex: Spi + Write + Read { - type WriteReadFuture<'a>: Future> + 'a - where - Self: 'a, - Word: 'a; - - /// The `read` array must be at least as long as the `write` array, - /// but is guaranteed to only be filled with bytes equal to the - /// length of the `write` array. - fn read_write<'a>( - &'a mut self, - read: &'a mut [Word], - write: &'a [Word], - ) -> Self::WriteReadFuture<'a>; -} - -pub trait Write: Spi { - type WriteFuture<'a>: Future> + 'a - where - Self: 'a, - Word: 'a; - - /// Writes `data` to the peripheral, ignoring all the incoming words. - fn write<'a>(&'a mut self, data: &'a [Word]) -> Self::WriteFuture<'a>; -} - -pub trait Read: Write { - type ReadFuture<'a>: Future> + 'a - where - Self: 'a, - Word: 'a; - - /// Reads words into `data` from the peripheral. - fn read<'a>(&'a mut self, data: &'a mut [Word]) -> Self::ReadFuture<'a>; -} diff --git a/embassy-traits/src/uart.rs b/embassy-traits/src/uart.rs deleted file mode 100644 index 4984bc89c..000000000 --- a/embassy-traits/src/uart.rs +++ /dev/null @@ -1,36 +0,0 @@ -use core::future::Future; - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - Other, -} - -pub trait Read { - type ReadFuture<'a>: Future> - where - Self: 'a; - - /// Receive into the buffer until the buffer is full. - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a>; -} - -pub trait ReadUntilIdle { - type ReadUntilIdleFuture<'a>: Future> - where - Self: 'a; - - /// Receive into the buffer until the buffer is full or the line is idle after some bytes are received - /// Return the number of bytes received - fn read_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a>; -} - -pub trait Write { - type WriteFuture<'a>: Future> - where - Self: 'a; - - /// Write all bytes in `buf`. - fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a>; -} -- cgit