Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async: switch to async-fn-in-traits, release v0.2.0-alpha.0 #407

Merged
merged 3 commits into from
Nov 23, 2022
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
profile: minimal
# embedded-hal-async needs nightly.
# Use a pinned version to avoid spontaneous breakages (new clippy lints are added often)
toolchain: nightly-2022-09-25
toolchain: nightly-2022-11-22
override: true
components: clippy
- run: cargo clippy -- --deny=warnings
6 changes: 5 additions & 1 deletion embedded-hal-async/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [v0.2.0-alpha.0] - 2022-11-23

- Switch all traits to use [`async_fn_in_trait`](https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-in-trait-nightly.html) (AFIT). Requires `nightly-2022-11-22` or newer.

## [v0.1.0-alpha.3] - 2022-10-26

Expand Down Expand Up @@ -34,7 +37,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
First release to crates.io


[Unreleased]: https://github.com/rust-embedded/embedded-hal/compare/embedded-hal-async-v0.1.0-alpha.3...HEAD
[Unreleased]: https://github.com/rust-embedded/embedded-hal/compare/embedded-hal-async-v0.2.0-alpha.0...HEAD
[v0.2.0-alpha.0]: https://github.com/rust-embedded/embedded-hal/compare/embedded-hal-async-v0.1.0-alpha.3...embedded-hal-async-v0.2.0-alpha.0
[v0.1.0-alpha.3]: https://github.com/rust-embedded/embedded-hal/compare/embedded-hal-async-v0.1.0-alpha.2...embedded-hal-async-v0.1.0-alpha.3
[v0.1.0-alpha.2]: https://github.com/rust-embedded/embedded-hal/compare/embedded-hal-async-v0.1.0-alpha.1...embedded-hal-async-v0.1.0-alpha.2
[v0.1.0-alpha.1]: https://github.com/rust-embedded/embedded-hal/compare/embedded-hal-async-v0.1.0-alpha.0...embedded-hal-async-v0.1.0-alpha.1
Expand Down
2 changes: 1 addition & 1 deletion embedded-hal-async/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0"
name = "embedded-hal-async"
readme = "README.md"
repository = "https://github.com/rust-embedded/embedded-hal"
version = "0.1.0-alpha.3"
version = "0.2.0-alpha.0"

[dependencies]
embedded-hal = { version = "=1.0.0-alpha.9", path = "../embedded-hal" }
28 changes: 6 additions & 22 deletions embedded-hal-async/src/delay.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
//! Delays

use core::future::Future;

/// Microsecond delay
pub trait DelayUs {
/// Enumeration of errors
type Error: core::fmt::Debug;

/// The future returned by the `delay_us` function.
type DelayUsFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;

/// Pauses execution for at minimum `us` microseconds. Pause can be longer
/// if the implementation requires it due to precision/timing issues.
fn delay_us(&mut self, us: u32) -> Self::DelayUsFuture<'_>;

/// The future returned by the `delay_ms` function.
type DelayMsFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;
async fn delay_us(&mut self, us: u32) -> Result<(), Self::Error>;

/// Pauses execution for at minimum `ms` milliseconds. Pause can be longer
/// if the implementation requires it due to precision/timing issues.
fn delay_ms(&mut self, ms: u32) -> Self::DelayMsFuture<'_>;
async fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error>;
}

impl<T> DelayUs for &mut T
Expand All @@ -32,15 +20,11 @@ where
{
type Error = T::Error;

type DelayUsFuture<'a> = T::DelayUsFuture<'a> where Self: 'a;

fn delay_us(&mut self, us: u32) -> Self::DelayUsFuture<'_> {
T::delay_us(self, us)
async fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
T::delay_us(self, us).await
}

type DelayMsFuture<'a> = T::DelayMsFuture<'a> where Self: 'a;

fn delay_ms(&mut self, ms: u32) -> Self::DelayMsFuture<'_> {
T::delay_ms(self, ms)
async fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
T::delay_ms(self, ms).await
}
}
67 changes: 15 additions & 52 deletions embedded-hal-async/src/digital.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,93 +16,56 @@
//! }
//! ```

use core::future::Future;

/// Asynchronously wait for GPIO pin state.
pub trait Wait: embedded_hal::digital::ErrorType {
/// The future returned by the `wait_for_high` function.
type WaitForHighFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;

/// Wait until the pin is high. If it is already high, return immediately.
///
/// # Note for implementers
/// The pin may have switched back to low before the task was run after
/// being woken. The future should still resolve in that case.
fn wait_for_high(&mut self) -> Self::WaitForHighFuture<'_>;

/// The future returned by `wait_for_low`.
type WaitForLowFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;
async fn wait_for_high(&mut self) -> Result<(), Self::Error>;

/// Wait until the pin is low. If it is already low, return immediately.
///
/// # Note for implementers
/// The pin may have switched back to high before the task was run after
/// being woken. The future should still resolve in that case.
fn wait_for_low(&mut self) -> Self::WaitForLowFuture<'_>;

/// The future returned from `wait_for_rising_edge`.
type WaitForRisingEdgeFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;
async fn wait_for_low(&mut self) -> Result<(), Self::Error>;

/// Wait for the pin to undergo a transition from low to high.
///
/// If the pin is already high, this does *not* return immediately, it'll wait for the
/// pin to go low and then high again.
fn wait_for_rising_edge(&mut self) -> Self::WaitForRisingEdgeFuture<'_>;

/// The future returned from `wait_for_falling_edge`.
type WaitForFallingEdgeFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error>;

/// Wait for the pin to undergo a transition from high to low.
///
/// If the pin is already low, this does *not* return immediately, it'll wait for the
/// pin to go high and then low again.
fn wait_for_falling_edge(&mut self) -> Self::WaitForFallingEdgeFuture<'_>;

/// The future returned from `wait_for_any_edge`.
type WaitForAnyEdgeFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error>;

/// Wait for the pin to undergo any transition, i.e low to high OR high to low.
fn wait_for_any_edge(&mut self) -> Self::WaitForAnyEdgeFuture<'_>;
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error>;
}

impl<T: Wait> Wait for &mut T {
type WaitForHighFuture<'a> = T::WaitForHighFuture<'a> where Self: 'a;

fn wait_for_high(&mut self) -> Self::WaitForHighFuture<'_> {
T::wait_for_high(self)
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
T::wait_for_high(self).await
}

type WaitForLowFuture<'a> = T::WaitForLowFuture<'a> where Self: 'a;

fn wait_for_low(&mut self) -> Self::WaitForLowFuture<'_> {
T::wait_for_low(self)
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
T::wait_for_low(self).await
}

type WaitForRisingEdgeFuture<'a> = T::WaitForRisingEdgeFuture<'a> where Self: 'a;

fn wait_for_rising_edge(&mut self) -> Self::WaitForRisingEdgeFuture<'_> {
T::wait_for_rising_edge(self)
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
T::wait_for_rising_edge(self).await
}

type WaitForFallingEdgeFuture<'a> = T::WaitForFallingEdgeFuture<'a> where Self: 'a;

fn wait_for_falling_edge(&mut self) -> Self::WaitForFallingEdgeFuture<'_> {
T::wait_for_falling_edge(self)
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
T::wait_for_falling_edge(self).await
}

type WaitForAnyEdgeFuture<'a> = T::WaitForAnyEdgeFuture<'a> where Self: 'a;

fn wait_for_any_edge(&mut self) -> Self::WaitForAnyEdgeFuture<'_> {
T::wait_for_any_edge(self)
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
T::wait_for_any_edge(self).await
}
}
62 changes: 16 additions & 46 deletions embedded-hal-async/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,13 @@
//! 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.

use core::future::Future;
pub use embedded_hal::i2c::Operation;
pub use embedded_hal::i2c::{
AddressMode, Error, ErrorKind, ErrorType, NoAcknowledgeSource, SevenBitAddress, TenBitAddress,
};

/// Async i2c
pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// Future returned by the `read` method.
type ReadFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;

/// Reads enough bytes from slave with `address` to fill `buffer`
///
/// # I2C Events (contract)
Expand All @@ -47,12 +41,7 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
fn read<'a>(&'a mut self, address: A, read: &'a mut [u8]) -> Self::ReadFuture<'a>;

/// Future returned by the `write` method.
type WriteFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;
async fn read<'a>(&'a mut self, address: A, read: &'a mut [u8]) -> Result<(), Self::Error>;

/// Writes bytes to slave with address `address`
///
Expand All @@ -70,12 +59,7 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `SAK` = slave acknowledge
/// - `Bi` = ith byte of data
/// - `SP` = stop condition
fn write<'a>(&'a mut self, address: A, write: &'a [u8]) -> Self::WriteFuture<'a>;

/// Future returned by the `write_read` method.
type WriteReadFuture<'a>: Future<Output = Result<(), Self::Error>>
where
Self: 'a;
async fn write<'a>(&'a mut self, address: A, write: &'a [u8]) -> Result<(), Self::Error>;

/// Writes bytes to slave with address `address` and then reads enough bytes to fill `read` *in a
/// single transaction*.
Expand All @@ -99,18 +83,12 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
fn write_read<'a>(
async fn write_read<'a>(
&'a mut self,
address: A,
write: &'a [u8],
read: &'a mut [u8],
) -> Self::WriteReadFuture<'a>;

/// Future returned by the `transaction` method.
type TransactionFuture<'a, 'b>: Future<Output = Result<(), Self::Error>>
where
Self: 'a,
'b: 'a;
) -> Result<(), Self::Error>;

/// Execute the provided operations on the I2C bus as a single transaction.
///
Expand All @@ -125,44 +103,36 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
/// - `SR` = repeated start condition
/// - `SP` = stop condition
fn transaction<'a, 'b>(
async fn transaction<'a, 'b>(
&'a mut self,
address: A,
operations: &'a mut [Operation<'b>],
) -> Self::TransactionFuture<'a, 'b>;
) -> Result<(), Self::Error>;
}

impl<A: AddressMode, T: I2c<A>> I2c<A> for &mut T {
type ReadFuture<'a> = T::ReadFuture<'a> where Self: 'a;

fn read<'a>(&'a mut self, address: A, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
T::read(self, address, buffer)
async fn read<'a>(&'a mut self, address: A, buffer: &'a mut [u8]) -> Result<(), Self::Error> {
T::read(self, address, buffer).await
}

type WriteFuture<'a> = T::WriteFuture<'a> where Self: 'a;

fn write<'a>(&'a mut self, address: A, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
T::write(self, address, bytes)
async fn write<'a>(&'a mut self, address: A, bytes: &'a [u8]) -> Result<(), Self::Error> {
T::write(self, address, bytes).await
}

type WriteReadFuture<'a> = T::WriteReadFuture<'a> where Self: 'a;

fn write_read<'a>(
async fn write_read<'a>(
&'a mut self,
address: A,
bytes: &'a [u8],
buffer: &'a mut [u8],
) -> Self::WriteReadFuture<'a> {
T::write_read(self, address, bytes, buffer)
) -> Result<(), Self::Error> {
T::write_read(self, address, bytes, buffer).await
}

type TransactionFuture<'a, 'b> = T::TransactionFuture<'a, 'b> where Self: 'a, 'b: 'a;

fn transaction<'a, 'b>(
async fn transaction<'a, 'b>(
&'a mut self,
address: A,
operations: &'a mut [Operation<'b>],
) -> Self::TransactionFuture<'a, 'b> {
T::transaction(self, address, operations)
) -> Result<(), Self::Error> {
T::transaction(self, address, operations).await
}
}
3 changes: 2 additions & 1 deletion embedded-hal-async/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

#![warn(missing_docs)]
#![no_std]
#![feature(type_alias_impl_trait)]
#![allow(incomplete_features)]
#![feature(async_fn_in_trait, impl_trait_projections)]

pub mod delay;
pub mod digital;
Expand Down
Loading