Skip to content

Commit 519e99c

Browse files
Dirbaiolachlansneff
andcommitted
Add embedded-hal-async crate.
Co-authored-by: Lachlan Sneff <[email protected]>
1 parent 02f1371 commit 519e99c

File tree

8 files changed

+575
-1
lines changed

8 files changed

+575
-1
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
**/*.rs.bk
22
.#*
3-
/target/
3+
target
44
Cargo.lock

embedded-hal-async/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "embedded-hal-async"
3+
version = "0.1.0"
4+
edition = "2021"
5+
categories = ["asynchronous", "embedded", "hardware-support", "no-std"]
6+
description = " A Hardware Abstraction Layer (HAL) for embedded systems, async version"
7+
documentation = "https://docs.rs/embedded-hal-async"
8+
keywords = ["hal", "IO", "async"]
9+
license = "MIT OR Apache-2.0"
10+
readme = "README.md"
11+
repository = "https://github.com/rust-embedded/embedded-hal"
12+
13+
[dependencies]
14+
nb = "1"
15+
embedded-hal = { version = "1.0.0-alpha.6", path = ".." }

embedded-hal-async/src/delay.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//! Delays
2+
3+
use core::future::Future;
4+
5+
/// Microsecond delay
6+
pub trait DelayUs {
7+
/// Enumeration of errors
8+
type Error: core::fmt::Debug;
9+
10+
/// The future returned by the `delay_us` function.
11+
type DelayUsFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
12+
where
13+
Self: 'a;
14+
15+
/// Pauses execution for at minimum `us` microseconds. Pause can be longer
16+
/// if the implementation requires it due to precision/timing issues.
17+
fn delay_us(&mut self, us: u32) -> Self::DelayUsFuture<'_>;
18+
19+
/// The future returned by the `delay_ms` function.
20+
type DelayMsFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
21+
where
22+
Self: 'a;
23+
24+
/// Pauses execution for at minimum `ms` milliseconds. Pause can be longer
25+
/// if the implementation requires it due to precision/timing issues.
26+
fn delay_ms(&mut self, ms: u32) -> Self::DelayMsFuture<'_>;
27+
}
28+
29+
impl<T> DelayUs for &mut T
30+
where
31+
T: DelayUs,
32+
{
33+
type Error = T::Error;
34+
35+
type DelayUsFuture<'a>
36+
where
37+
Self: 'a,
38+
= T::DelayUsFuture<'a>;
39+
40+
fn delay_us(&mut self, us: u32) -> Self::DelayUsFuture<'_> {
41+
T::delay_us(self, us)
42+
}
43+
44+
type DelayMsFuture<'a>
45+
where
46+
Self: 'a,
47+
= T::DelayMsFuture<'a>;
48+
49+
fn delay_ms(&mut self, ms: u32) -> Self::DelayMsFuture<'_> {
50+
T::delay_ms(self, ms)
51+
}
52+
}

embedded-hal-async/src/digital.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//! Asynchronous digital I/O
2+
//!
3+
//! # Example
4+
//!
5+
//! ```rust
6+
//! # use embedded_hal_async::digital::WaitForHigh;
7+
//! /// Asynchronously wait until the `ready_pin` becomes high.
8+
//! async fn wait_until_ready<P>(ready_pin: &mut P)
9+
//! where
10+
//! P: WaitForHigh,
11+
//! {
12+
//! ready_pin
13+
//! .wait_for_high()
14+
//! .await
15+
//! .expect("failed to await input pin")
16+
//! }
17+
//! ```
18+
19+
use core::future::Future;
20+
21+
/// Asynchronously wait for a pin to be high.
22+
pub trait WaitForHigh {
23+
/// Enumeration of errors.
24+
type Error: core::fmt::Debug;
25+
26+
/// The future returned by the `wait_for_high` function.
27+
type WaitForHighFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
28+
where
29+
Self: 'a;
30+
31+
/// Returns a future that resolves when this pin _is_ high. If the pin
32+
/// is already high, the future resolves immediately.
33+
///
34+
/// # Note for implementers
35+
/// The pin may have switched back to low before the task was run after
36+
/// being woken. The future should still resolve in that case.
37+
fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a>;
38+
}
39+
40+
/// Asynchronously wait for a pin to be low.
41+
pub trait WaitForLow {
42+
/// Enumeration of errors.
43+
type Error: core::fmt::Debug;
44+
45+
/// The future returned by `wait_for_low`.
46+
type WaitForLowFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
47+
where
48+
Self: 'a;
49+
50+
/// Returns a future that resolves when this pin _is_ low. If the pin
51+
/// is already low, the future resolves immediately.
52+
///
53+
/// # Note for implementers
54+
/// The pin may have switched back to high before the task was run after
55+
/// being woken. The future should still resolve in that case.
56+
fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a>;
57+
}
58+
59+
/// Wait for a rising edge (transition from low to high).
60+
pub trait WaitForRisingEdge {
61+
/// Enumeration of errors.
62+
type Error: core::fmt::Debug;
63+
64+
/// The future returned from `wait_for_rising_edge`.
65+
type WaitForRisingEdgeFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
66+
where
67+
Self: 'a;
68+
69+
/// Returns a future that resolves when this pin transitions from low to high.
70+
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a>;
71+
}
72+
73+
/// Wait for a falling edge (transition from high to low).
74+
pub trait WaitForFallingEdge {
75+
/// Enumeration of errors.
76+
type Error: core::fmt::Debug;
77+
78+
/// The future returned from `wait_for_falling_edge`.
79+
type WaitForFallingEdgeFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
80+
where
81+
Self: 'a;
82+
83+
/// Returns a future that resolves when this pin transitions from high to low.
84+
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a>;
85+
}
86+
87+
/// Wait for any edge (transition from low to high OR high to low).
88+
pub trait WaitForAnyEdge {
89+
/// Enumeration of errors.
90+
type Error: core::fmt::Debug;
91+
92+
/// The future returned from `wait_for_any_edge`.
93+
type WaitForAnyEdgeFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
94+
where
95+
Self: 'a;
96+
97+
/// Returns a future that resolves when this pin undergoes any transition, e.g.
98+
/// low to high OR high to low.
99+
fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a>;
100+
}

embedded-hal-async/src/i2c.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
//! Async I2C API
2+
//!
3+
//! This API supports 7-bit and 10-bit addresses. Traits feature an `AddressMode`
4+
//! marker type parameter. Two implementation of the `AddressMode` exist:
5+
//! `SevenBitAddress` and `TenBitAddress`.
6+
//!
7+
//! Through this marker types it is possible to implement each address mode for
8+
//! the traits independently in `embedded-hal` implementations and device drivers
9+
//! can depend only on the mode that they support.
10+
//!
11+
//! Additionally, the I2C 10-bit address mode has been developed to be fully
12+
//! backwards compatible with the 7-bit address mode. This allows for a
13+
//! software-emulated 10-bit addressing implementation if the address mode
14+
//! is not supported by the hardware.
15+
//!
16+
//! Since 7-bit addressing is the mode of the majority of I2C devices,
17+
//! `SevenBitAddress` has been set as default mode and thus can be omitted if desired.
18+
19+
use core::future::Future;
20+
pub use embedded_hal::i2c::{
21+
AddressMode, Error, ErrorKind, NoAcknowledgeSource, SevenBitAddress, TenBitAddress,
22+
};
23+
24+
/// Async read
25+
pub trait Read<A: AddressMode = SevenBitAddress> {
26+
/// Error type
27+
type Error: Error;
28+
/// The future associated with the `read` method.
29+
type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
30+
where
31+
Self: 'a;
32+
33+
/// Reads enough bytes from slave with `address` to fill `buffer`
34+
///
35+
/// # I2C Events (contract)
36+
///
37+
/// ``` text
38+
/// Master: ST SAD+R MAK MAK ... NMAK SP
39+
/// Slave: SAK B0 B1 ... BN
40+
/// ```
41+
///
42+
/// Where
43+
///
44+
/// - `ST` = start condition
45+
/// - `SAD+R` = slave address followed by bit 1 to indicate reading
46+
/// - `SAK` = slave acknowledge
47+
/// - `Bi` = ith byte of data
48+
/// - `MAK` = master acknowledge
49+
/// - `NMAK` = master no acknowledge
50+
/// - `SP` = stop condition
51+
fn read<'a>(&'a mut self, address: A, read: &'a mut [u8]) -> Self::ReadFuture<'a>;
52+
}
53+
54+
impl<A: AddressMode, T: Read<A>> Read<A> for &mut T {
55+
type Error = T::Error;
56+
57+
type ReadFuture<'a>
58+
where
59+
Self: 'a,
60+
= T::ReadFuture<'a>;
61+
62+
fn read<'a>(&'a mut self, address: A, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
63+
T::read(self, address, buffer)
64+
}
65+
}
66+
67+
/// Async write
68+
pub trait Write<A: AddressMode = SevenBitAddress> {
69+
/// Error type
70+
type Error: Error;
71+
/// The future associated with the `write` method.
72+
type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
73+
where
74+
Self: 'a;
75+
76+
/// Writes bytes to slave with address `address`
77+
///
78+
/// # I2C Events (contract)
79+
///
80+
/// ``` text
81+
/// Master: ST SAD+W B0 B1 ... BN SP
82+
/// Slave: SAK SAK SAK ... SAK
83+
/// ```
84+
///
85+
/// Where
86+
///
87+
/// - `ST` = start condition
88+
/// - `SAD+W` = slave address followed by bit 0 to indicate writing
89+
/// - `SAK` = slave acknowledge
90+
/// - `Bi` = ith byte of data
91+
/// - `SP` = stop condition
92+
fn write<'a>(&'a mut self, address: A, write: &'a [u8]) -> Self::WriteFuture<'a>;
93+
}
94+
95+
impl<A: AddressMode, T: Write<A>> Write<A> for &mut T {
96+
type Error = T::Error;
97+
98+
type WriteFuture<'a>
99+
where
100+
Self: 'a,
101+
= T::WriteFuture<'a>;
102+
103+
fn write<'a>(&'a mut self, address: A, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
104+
T::write(self, address, bytes)
105+
}
106+
}
107+
108+
/// Async write + read
109+
pub trait WriteRead<A: AddressMode = SevenBitAddress> {
110+
/// Error type
111+
type Error: Error;
112+
/// The future associated with the `write_read` method.
113+
type WriteReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
114+
where
115+
Self: 'a;
116+
117+
/// Writes bytes to slave with address `address` and then reads enough bytes to fill `read` *in a
118+
/// single transaction*.
119+
///
120+
/// # I2C Events (contract)
121+
///
122+
/// ``` text
123+
/// Master: ST SAD+W O0 O1 ... OM SR SAD+R MAK MAK ... NMAK SP
124+
/// Slave: SAK SAK SAK ... SAK SAK I0 I1 ... IN
125+
/// ```
126+
///
127+
/// Where
128+
///
129+
/// - `ST` = start condition
130+
/// - `SAD+W` = slave address followed by bit 0 to indicate writing
131+
/// - `SAK` = slave acknowledge
132+
/// - `Oi` = ith outgoing byte of data
133+
/// - `SR` = repeated start condition
134+
/// - `SAD+R` = slave address followed by bit 1 to indicate reading
135+
/// - `Ii` = ith incoming byte of data
136+
/// - `MAK` = master acknowledge
137+
/// - `NMAK` = master no acknowledge
138+
/// - `SP` = stop condition
139+
fn write_read<'a>(
140+
&'a mut self,
141+
address: A,
142+
write: &'a [u8],
143+
read: &'a mut [u8],
144+
) -> Self::WriteReadFuture<'a>;
145+
}
146+
147+
impl<A: AddressMode, T: WriteRead<A>> WriteRead<A> for &mut T {
148+
type Error = T::Error;
149+
150+
type WriteReadFuture<'a>
151+
where
152+
Self: 'a,
153+
= T::WriteReadFuture<'a>;
154+
155+
fn write_read<'a>(
156+
&'a mut self,
157+
address: A,
158+
bytes: &'a [u8],
159+
buffer: &'a mut [u8],
160+
) -> Self::WriteReadFuture<'a> {
161+
T::write_read(self, address, bytes, buffer)
162+
}
163+
}

embedded-hal-async/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(generic_associated_types)]
2+
#![no_std]
3+
#![deny(missing_docs)]
4+
5+
//! Asynchronous APIs
6+
//!
7+
//! This traits use `core::future::Future` and generic associated types.
8+
9+
pub mod delay;
10+
pub mod digital;
11+
pub mod i2c;
12+
pub mod serial;
13+
pub mod spi;

0 commit comments

Comments
 (0)