Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions embassy-embedded-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ features = ["std"]
[features]
std = []
time = ["dep:embassy-time"]
default = ["time"]
default = ["time", "embedded-hal-02"]

#! Support legacy for embedded hal 0.2 traits
embedded-hal-02 = ["dep:embedded-hal-02"]

[dependencies]
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-sync = { version = "0.5.0", path = "../embassy-sync" }
embassy-time = { version = "0.3.0", path = "../embassy-time", optional = true }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [
"unproven",
] }
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
], optional = true }
embedded-hal = "1.0"
embedded-hal-async = { version = "1.0" }
embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" }
Expand Down
221 changes: 154 additions & 67 deletions embassy-embedded-hal/src/adapter/blocking_async.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use embedded_hal_02::blocking;

/// Wrapper that implements async traits using blocking implementations.
///
/// This allows driver writers to depend on the async traits while still supporting embedded-hal peripheral implementations.
Expand All @@ -17,92 +15,181 @@ impl<T> BlockingAsync<T> {
Self { wrapped }
}
}
#[cfg(feature = "embedded-hal-02")]
mod embedded_hal_02 {
use embedded_hal_02::blocking;

use super::BlockingAsync;
//
// I2C implementations
//
impl<T, E> embedded_hal::i2c::ErrorType for BlockingAsync<T>
where
E: embedded_hal::i2c::Error + 'static,
T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>,
{
type Error = E;
}

//
// I2C implementations
//
impl<T, E> embedded_hal_1::i2c::ErrorType for BlockingAsync<T>
where
E: embedded_hal_1::i2c::Error + 'static,
T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>,
{
type Error = E;
}
impl<T, E> embedded_hal_async::i2c::I2c for BlockingAsync<T>
where
E: embedded_hal::i2c::Error + 'static,
T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>,
{
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.read(address, read)
}

impl<T, E> embedded_hal_async::i2c::I2c for BlockingAsync<T>
where
E: embedded_hal_1::i2c::Error + 'static,
T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>,
{
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.read(address, read)
}
async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(address, write)
}

async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.write_read(address, write, read)
}

async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(address, write)
async fn transaction(
&mut self,
address: u8,
operations: &mut [embedded_hal::i2c::Operation<'_>],
) -> Result<(), Self::Error> {
let _ = address;
let _ = operations;
todo!()
}
}

async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.write_read(address, write, read)
//
// SPI implementatinos
//

impl<T, E> embedded_hal_async::spi::ErrorType for BlockingAsync<T>
where
E: embedded_hal::spi::Error,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
type Error = E;
}

async fn transaction(
&mut self,
address: u8,
operations: &mut [embedded_hal_1::i2c::Operation<'_>],
) -> Result<(), Self::Error> {
let _ = address;
let _ = operations;
todo!()
impl<T, E> embedded_hal_async::spi::SpiBus<u8> for BlockingAsync<T>
where
E: embedded_hal::spi::Error + 'static,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}

async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(data)?;
Ok(())
}

async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(data)?;
Ok(())
}

async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
// Ensure we write the expected bytes
for i in 0..core::cmp::min(read.len(), write.len()) {
read[i] = write[i].clone();
}
self.wrapped.transfer(read)?;
Ok(())
}

async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(data)?;
Ok(())
}
}
}
#[cfg(not(feature = "embedded-hal-02"))]
mod embedded_hal {
use super::BlockingAsync;

//
// I2C implementations
//
impl<T, E> embedded_hal::i2c::ErrorType for BlockingAsync<T>
where
E: embedded_hal::i2c::Error + 'static,
T: embedded_hal::i2c::I2c + embedded_hal_async::i2c::ErrorType<Error = E>,
{
type Error = E;
}

//
// SPI implementatinos
//
impl<T, E> embedded_hal_async::i2c::I2c for BlockingAsync<T>
where
E: embedded_hal::i2c::Error + 'static,
T: embedded_hal::i2c::I2c + embedded_hal_async::i2c::ErrorType<Error = E>,
{
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.read(address, read)
}

impl<T, E> embedded_hal_async::spi::ErrorType for BlockingAsync<T>
where
E: embedded_hal_1::spi::Error,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
type Error = E;
}
async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(address, write)
}

impl<T, E> embedded_hal_async::spi::SpiBus<u8> for BlockingAsync<T>
where
E: embedded_hal_1::spi::Error + 'static,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.write_read(address, write, read)
}

async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(data)?;
Ok(())
async fn transaction(
&mut self,
address: u8,
operations: &mut [embedded_hal::i2c::Operation<'_>],
) -> Result<(), Self::Error> {
let _ = address;
let _ = operations;
todo!()
}
}

async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(data)?;
Ok(())
//
// SPI implementatinos
//

impl<T, E> embedded_hal_async::spi::ErrorType for BlockingAsync<T>
where
E: embedded_hal::spi::Error,
T: embedded_hal::spi::SpiBus<u8> + embedded_hal_async::spi::ErrorType<Error = E>,
{
type Error = E;
}

async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
// Ensure we write the expected bytes
for i in 0..core::cmp::min(read.len(), write.len()) {
read[i] = write[i].clone();
impl<T, E> embedded_hal_async::spi::SpiBus<u8> for BlockingAsync<T>
where
E: embedded_hal::spi::Error + 'static,
T: embedded_hal::spi::SpiBus<u8> + embedded_hal_async::spi::ErrorType<Error = E>,
{
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
self.wrapped.transfer(read)?;
Ok(())
}

async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(data)?;
Ok(())
async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(data)?;
Ok(())
}

async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.read(data)?;
Ok(())
}

async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(read, write)?;
Ok(())
}

async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer_in_place(data)?;
Ok(())
}
}
}

/// NOR flash wrapper
use embedded_storage::nor_flash::{ErrorType, MultiwriteNorFlash, NorFlash, ReadNorFlash};
use embedded_storage_async::nor_flash::{
Expand Down
6 changes: 3 additions & 3 deletions embassy-embedded-hal/src/adapter/yielding_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ impl<T> YieldingAsync<T> {
//
// I2C implementations
//
impl<T> embedded_hal_1::i2c::ErrorType for YieldingAsync<T>
impl<T> embedded_hal::i2c::ErrorType for YieldingAsync<T>
where
T: embedded_hal_1::i2c::ErrorType,
T: embedded_hal::i2c::ErrorType,
{
type Error = T::Error;
}
Expand Down Expand Up @@ -50,7 +50,7 @@ where
async fn transaction(
&mut self,
address: u8,
operations: &mut [embedded_hal_1::i2c::Operation<'_>],
operations: &mut [embedded_hal::i2c::Operation<'_>],
) -> Result<(), Self::Error> {
self.wrapped.transaction(address, operations).await?;
yield_now().await;
Expand Down
4 changes: 2 additions & 2 deletions embassy-embedded-hal/src/shared_bus/asynch/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@

use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::mutex::Mutex;
use embedded_hal_1::digital::OutputPin;
use embedded_hal_1::spi::Operation;
use embedded_hal::digital::OutputPin;
use embedded_hal::spi::Operation;
use embedded_hal_async::spi;

use crate::shared_bus::SpiDeviceError;
Expand Down
Loading