Skip to content

Commit 61285e4

Browse files
bors[bot]Dirbaio
andauthored
Merge #348
348: async: add i2c r=eldruin a=Dirbaio This mirrors the blocking i2c trait (including the changes proposed in #339 ), except the following: - Removed all `iter` methods since they don't play well with DMA. Co-authored-by: Dario Nieuwenhuis <[email protected]>
2 parents 599f8bd + dc8bdf2 commit 61285e4

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed

embedded-hal-async/src/i2c.rs

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
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::blocking::Operation;
21+
pub use embedded_hal::i2c::{
22+
AddressMode, Error, ErrorKind, ErrorType, NoAcknowledgeSource, SevenBitAddress, TenBitAddress,
23+
};
24+
25+
/// Async i2c
26+
pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
27+
/// Future returned by the `read` method.
28+
type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
29+
where
30+
Self: 'a;
31+
32+
/// Reads enough bytes from slave with `address` to fill `buffer`
33+
///
34+
/// # I2C Events (contract)
35+
///
36+
/// ``` text
37+
/// Master: ST SAD+R MAK MAK ... NMAK SP
38+
/// Slave: SAK B0 B1 ... BN
39+
/// ```
40+
///
41+
/// Where
42+
///
43+
/// - `ST` = start condition
44+
/// - `SAD+R` = slave address followed by bit 1 to indicate reading
45+
/// - `SAK` = slave acknowledge
46+
/// - `Bi` = ith byte of data
47+
/// - `MAK` = master acknowledge
48+
/// - `NMAK` = master no acknowledge
49+
/// - `SP` = stop condition
50+
fn read<'a>(&'a mut self, address: A, read: &'a mut [u8]) -> Self::ReadFuture<'a>;
51+
52+
/// Future returned by the `write` method.
53+
type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
54+
where
55+
Self: 'a;
56+
57+
/// Writes bytes to slave with address `address`
58+
///
59+
/// # I2C Events (contract)
60+
///
61+
/// ``` text
62+
/// Master: ST SAD+W B0 B1 ... BN SP
63+
/// Slave: SAK SAK SAK ... SAK
64+
/// ```
65+
///
66+
/// Where
67+
///
68+
/// - `ST` = start condition
69+
/// - `SAD+W` = slave address followed by bit 0 to indicate writing
70+
/// - `SAK` = slave acknowledge
71+
/// - `Bi` = ith byte of data
72+
/// - `SP` = stop condition
73+
fn write<'a>(&'a mut self, address: A, write: &'a [u8]) -> Self::WriteFuture<'a>;
74+
75+
/// Future returned by the `write_read` method.
76+
type WriteReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
77+
where
78+
Self: 'a;
79+
80+
/// Writes bytes to slave with address `address` and then reads enough bytes to fill `read` *in a
81+
/// single transaction*.
82+
///
83+
/// # I2C Events (contract)
84+
///
85+
/// ``` text
86+
/// Master: ST SAD+W O0 O1 ... OM SR SAD+R MAK MAK ... NMAK SP
87+
/// Slave: SAK SAK SAK ... SAK SAK I0 I1 ... IN
88+
/// ```
89+
///
90+
/// Where
91+
///
92+
/// - `ST` = start condition
93+
/// - `SAD+W` = slave address followed by bit 0 to indicate writing
94+
/// - `SAK` = slave acknowledge
95+
/// - `Oi` = ith outgoing byte of data
96+
/// - `SR` = repeated start condition
97+
/// - `SAD+R` = slave address followed by bit 1 to indicate reading
98+
/// - `Ii` = ith incoming byte of data
99+
/// - `MAK` = master acknowledge
100+
/// - `NMAK` = master no acknowledge
101+
/// - `SP` = stop condition
102+
fn write_read<'a>(
103+
&'a mut self,
104+
address: A,
105+
write: &'a [u8],
106+
read: &'a mut [u8],
107+
) -> Self::WriteReadFuture<'a>;
108+
109+
/// Future returned by the `transaction` method.
110+
type TransactionFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
111+
where
112+
Self: 'a;
113+
114+
/// Execute the provided operations on the I2C bus as a single transaction.
115+
///
116+
/// Transaction contract:
117+
/// - Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate.
118+
/// - Data from adjacent operations of the same type are sent after each other without an SP or SR.
119+
/// - Between adjacent operations of a different type an SR and SAD+R/W is sent.
120+
/// - After executing the last operation an SP is sent automatically.
121+
/// - If the last operation is a `Read` the master does not send an acknowledge for the last byte.
122+
///
123+
/// - `ST` = start condition
124+
/// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
125+
/// - `SR` = repeated start condition
126+
/// - `SP` = stop condition
127+
fn transaction<'a>(
128+
&'a mut self,
129+
address: A,
130+
operations: &mut [Operation<'a>],
131+
) -> Self::TransactionFuture<'a>;
132+
}
133+
134+
impl<A: AddressMode, T: I2c<A>> I2c<A> for &mut T {
135+
type ReadFuture<'a>
136+
where
137+
Self: 'a,
138+
= T::ReadFuture<'a>;
139+
140+
fn read<'a>(&'a mut self, address: A, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
141+
T::read(self, address, buffer)
142+
}
143+
144+
type WriteFuture<'a>
145+
where
146+
Self: 'a,
147+
= T::WriteFuture<'a>;
148+
149+
fn write<'a>(&'a mut self, address: A, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
150+
T::write(self, address, bytes)
151+
}
152+
153+
type WriteReadFuture<'a>
154+
where
155+
Self: 'a,
156+
= T::WriteReadFuture<'a>;
157+
158+
fn write_read<'a>(
159+
&'a mut self,
160+
address: A,
161+
bytes: &'a [u8],
162+
buffer: &'a mut [u8],
163+
) -> Self::WriteReadFuture<'a> {
164+
T::write_read(self, address, bytes, buffer)
165+
}
166+
167+
type TransactionFuture<'a>
168+
where
169+
Self: 'a,
170+
= T::TransactionFuture<'a>;
171+
172+
fn transaction<'a>(
173+
&'a mut self,
174+
address: A,
175+
operations: &mut [Operation<'a>],
176+
) -> Self::TransactionFuture<'a> {
177+
T::transaction(self, address, operations)
178+
}
179+
}

embedded-hal-async/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
#![feature(generic_associated_types)]
1313

1414
pub mod delay;
15+
pub mod i2c;

0 commit comments

Comments
 (0)