1
1
//! Blocking I2C API
2
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`.
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
6
//!
7
7
//! Through this marker types it is possible to implement each address mode for
8
8
//! the traits independently in `embedded-hal` implementations and device drivers
14
14
//! is not supported by the hardware.
15
15
//!
16
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.
17
+ //! [ `SevenBitAddress`] has been set as default mode and thus can be omitted if desired.
18
18
//!
19
- //! ## Examples
19
+ //! # Bus sharing
20
20
//!
21
- //! ### `embedded-hal` implementation for an MCU
22
- //! Here is an example of an embedded-hal implementation of the `Write` trait
23
- //! for both modes:
24
- //! ```
25
- //! # use embedded_hal::i2c::{ErrorKind, ErrorType, SevenBitAddress, TenBitAddress, I2c, Operation};
26
- //! /// I2C0 hardware peripheral which supports both 7-bit and 10-bit addressing.
27
- //! pub struct I2c0;
21
+ //! I2C allows sharing a single bus between many I2C devices. The SDA and SCL lines are
22
+ //! wired in parallel to all devices. When starting a transfer an "address" is sent
23
+ //! so that the addressed device can respond and all the others can ignore the transfer.
28
24
//!
29
- //! # impl ErrorType for I2c0 { type Error = ErrorKind; }
30
- //! impl I2c<SevenBitAddress> for I2c0
31
- //! {
32
- //! fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
33
- //! // ...
34
- //! # Ok(())
35
- //! }
36
- //! fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
37
- //! // ...
38
- //! # Ok(())
39
- //! }
40
- //! fn write_iter<B: IntoIterator<Item = u8>>(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error> {
41
- //! // ...
42
- //! # Ok(())
43
- //! }
44
- //! fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
45
- //! // ...
46
- //! # Ok(())
47
- //! }
48
- //! fn write_iter_read<B: IntoIterator<Item = u8>>(&mut self, addr: u8, bytes: B, buffer: &mut [u8]) -> Result<(), Self::Error> {
49
- //! // ...
50
- //! # Ok(())
51
- //! }
52
- //! fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> {
53
- //! // ...
54
- //! # Ok(())
55
- //! }
56
- //! fn transaction_iter<'a, O: IntoIterator<Item = Operation<'a>>>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> {
57
- //! // ...
58
- //! # Ok(())
59
- //! }
60
- //! }
25
+ #![ doc = include_str ! ( "i2c-shared-bus.svg" ) ]
61
26
//!
62
- //! impl I2c<TenBitAddress> for I2c0
63
- //! {
64
- //! fn read(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Self::Error> {
65
- //! // ...
66
- //! # Ok(())
67
- //! }
68
- //! fn write(&mut self, addr: u16, bytes: &[u8]) -> Result<(), Self::Error> {
69
- //! // ...
70
- //! # Ok(())
71
- //! }
72
- //! fn write_iter<B: IntoIterator<Item = u8>>(&mut self, addr: u16, bytes: B) -> Result<(), Self::Error> {
73
- //! // ...
74
- //! # Ok(())
75
- //! }
76
- //! fn write_read(&mut self, addr: u16, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
77
- //! // ...
78
- //! # Ok(())
79
- //! }
80
- //! fn write_iter_read<B: IntoIterator<Item = u8>>(&mut self, addr: u16, bytes: B, buffer: &mut [u8]) -> Result<(), Self::Error> {
81
- //! // ...
82
- //! # Ok(())
83
- //! }
84
- //! fn transaction<'a>(&mut self, address: u16, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> {
85
- //! // ...
86
- //! # Ok(())
87
- //! }
88
- //! fn transaction_iter<'a, O: IntoIterator<Item = Operation<'a>>>(&mut self, address: u16, operations: O) -> Result<(), Self::Error> {
89
- //! // ...
90
- //! # Ok(())
91
- //! }
92
- //! }
93
- //! ```
27
+ //! This bus sharing is common when having multiple I2C devices in the same board, since it uses fewer MCU
28
+ //! pins (`2` instead of `2*n`), and fewer MCU I2C peripherals (`1` instead of `n`).
94
29
//!
95
- //! ### Device driver compatible only with 7-bit addresses
30
+ //! This API supports bus sharing natively. Types implementing [`I2c`] are allowed
31
+ //! to represent either exclusive or shared access to an I2C bus. HALs typically
32
+ //! provide exclusive access implementations. Drivers shouldn't care which
33
+ //! kind they receive, they just do transactions on it and let the
34
+ //! underlying implementation share or not.
35
+ //!
36
+ //! The [`embedded-hal-bus`](https://docs.rs/embedded-hal-bus) crate provides several
37
+ //! implementations for sharing I2C buses. You can use them to take an exclusive instance
38
+ //! you've received from a HAL and "split" it into mulitple shared ones, to instantiate
39
+ //! several drivers on the same bus.
40
+ //!
41
+ //! # For driver authors
42
+ //!
43
+ //! Drivers can select the adequate address length with `I2c<SevenBitAddress>` or `I2c<TenBitAddress>` depending
44
+ //! on the target device. If it can use either, the driver can
45
+ //! be generic over the address kind as well, though this is rare.
46
+ //!
47
+ //! Drivers should take the `I2c` instance as an argument to `new()`, and store it in their
48
+ //! struct. They **should not** take `&mut I2c`, the trait has a blanket impl for all `&mut T`
49
+ //! so taking just `I2c` ensures the user can still pass a `&mut`, but is not forced to.
50
+ //!
51
+ //! Drivers **should not** try to enable bus sharing by taking `&mut I2c` at every method.
52
+ //! This is much less ergonomic than owning the `I2c`, which still allows the user to pass an
53
+ //! implementation that does sharing behind the scenes
54
+ //! (from [`embedded-hal-bus`](https://docs.rs/embedded-hal-bus), or others).
55
+ //!
56
+ //! ## Device driver compatible only with 7-bit addresses
96
57
//!
97
58
//! For demonstration purposes the address mode parameter has been omitted in this example.
98
59
//!
99
60
//! ```
100
- //! # use embedded_hal::i2c::{I2c, Error};
101
- //! const ADDR: u8 = 0x15;
61
+ //! use embedded_hal::i2c::{I2c, Error};
62
+ //!
63
+ //! const ADDR: u8 = 0x15;
102
64
//! # const TEMP_REGISTER: u8 = 0x1;
103
65
//! pub struct TemperatureSensorDriver<I2C> {
104
66
//! i2c: I2C,
105
67
//! }
106
68
//!
107
- //! impl<I2C, E: Error> TemperatureSensorDriver<I2C>
108
- //! where
109
- //! I2C: I2c<Error = E>,
110
- //! {
111
- //! pub fn read_temperature(&mut self) -> Result<u8, E> {
69
+ //! impl<I2C: I2c> TemperatureSensorDriver<I2C> {
70
+ //! pub fn new(i2c: I2C) -> Self {
71
+ //! Self { i2c }
72
+ //! }
73
+ //!
74
+ //! pub fn read_temperature(&mut self) -> Result<u8, I2C::Error> {
112
75
//! let mut temp = [0];
113
- //! self.i2c
114
- //! .write_read(ADDR, &[TEMP_REGISTER], &mut temp)
115
- //! .and(Ok(temp[0]))
76
+ //! self.i2c.write_read(ADDR, &[TEMP_REGISTER], &mut temp)?;
77
+ //! Ok(temp[0])
116
78
//! }
117
79
//! }
118
80
//! ```
119
81
//!
120
- //! ### Device driver compatible only with 10-bit addresses
82
+ //! ## Device driver compatible only with 10-bit addresses
121
83
//!
122
84
//! ```
123
- //! # use embedded_hal::i2c::{Error, TenBitAddress, I2c};
124
- //! const ADDR: u16 = 0x158;
85
+ //! use embedded_hal::i2c::{Error, TenBitAddress, I2c};
86
+ //!
87
+ //! const ADDR: u16 = 0x158;
125
88
//! # const TEMP_REGISTER: u8 = 0x1;
126
89
//! pub struct TemperatureSensorDriver<I2C> {
127
90
//! i2c: I2C,
128
91
//! }
129
92
//!
130
- //! impl<I2C, E: Error> TemperatureSensorDriver<I2C>
131
- //! where
132
- //! I2C: I2c<TenBitAddress, Error = E>,
133
- //! {
134
- //! pub fn read_temperature(&mut self) -> Result<u8, E> {
93
+ //! impl<I2C: I2c<TenBitAddress>> TemperatureSensorDriver<I2C> {
94
+ //! pub fn new(i2c: I2C) -> Self {
95
+ //! Self { i2c }
96
+ //! }
97
+ //!
98
+ //! pub fn read_temperature(&mut self) -> Result<u8, I2C::Error> {
135
99
//! let mut temp = [0];
136
- //! self.i2c
137
- //! .write_read(ADDR, &[TEMP_REGISTER], &mut temp)
138
- //! .and(Ok(temp[0]))
100
+ //! self.i2c.write_read(ADDR, &[TEMP_REGISTER], &mut temp)?;
101
+ //! Ok(temp[0])
102
+ //! }
103
+ //! }
104
+ //! ```
105
+ //!
106
+ //! # For HAL authors
107
+ //!
108
+ //! HALs **should not** include bus sharing mechanisms. They should expose a single type representing
109
+ //! exclusive ownership over the bus, and let the user use [`embedded-hal-bus`](https://docs.rs/embedded-hal-bus)
110
+ //! if they want to share it. (One exception is if the underlying platform already
111
+ //! supports sharing, such as Linux or some RTOSs.)
112
+ //!
113
+ //! Here is an example of an embedded-hal implementation of the `I2C` trait
114
+ //! for both addressing modes. All trait methods have have default implementations in terms of `transaction`.
115
+ //! As such, that is the only method that requires implementation in the HAL.
116
+ //!
117
+ //! ```
118
+ //! use embedded_hal::i2c::{self, SevenBitAddress, TenBitAddress, I2c, Operation};
119
+ //!
120
+ //! /// I2C0 hardware peripheral which supports both 7-bit and 10-bit addressing.
121
+ //! pub struct I2c0;
122
+ //!
123
+ //! #[derive(Debug, Copy, Clone, Eq, PartialEq)]
124
+ //! pub enum Error {
125
+ //! // ...
126
+ //! }
127
+ //!
128
+ //! impl i2c::Error for Error {
129
+ //! fn kind(&self) -> i2c::ErrorKind {
130
+ //! match *self {
131
+ //! // ...
132
+ //! }
133
+ //! }
134
+ //! }
135
+ //!
136
+ //! impl i2c::ErrorType for I2c0 {
137
+ //! type Error = Error;
138
+ //! }
139
+ //!
140
+ //! impl I2c<SevenBitAddress> for I2c0 {
141
+ //! fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
142
+ //! // ...
143
+ //! # Ok(())
144
+ //! }
145
+ //! }
146
+ //!
147
+ //! impl I2c<TenBitAddress> for I2c0 {
148
+ //! fn transaction(&mut self, address: u16, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
149
+ //! // ...
150
+ //! # Ok(())
139
151
//! }
140
152
//! }
141
153
//! ```
@@ -256,7 +268,7 @@ impl AddressMode for SevenBitAddress {}
256
268
257
269
impl AddressMode for TenBitAddress { }
258
270
259
- /// Transactional I2C operation.
271
+ /// I2C operation.
260
272
///
261
273
/// Several operations can be combined as part of a transaction.
262
274
#[ derive( Debug , PartialEq , Eq ) ]
@@ -269,7 +281,7 @@ pub enum Operation<'a> {
269
281
270
282
/// Blocking I2C
271
283
pub trait I2c < A : AddressMode = SevenBitAddress > : ErrorType {
272
- /// Reads enough bytes from slave with `address` to fill `buffer `
284
+ /// Reads enough bytes from slave with `address` to fill `read `
273
285
///
274
286
/// # I2C Events (contract)
275
287
///
@@ -287,7 +299,9 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
287
299
/// - `MAK` = master acknowledge
288
300
/// - `NMAK` = master no acknowledge
289
301
/// - `SP` = stop condition
290
- fn read ( & mut self , address : A , buffer : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > ;
302
+ fn read ( & mut self , address : A , read : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
303
+ self . transaction ( address, & mut [ Operation :: Read ( read) ] )
304
+ }
291
305
292
306
/// Writes bytes to slave with address `address`
293
307
///
@@ -305,18 +319,11 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
305
319
/// - `SAK` = slave acknowledge
306
320
/// - `Bi` = ith byte of data
307
321
/// - `SP` = stop condition
308
- fn write ( & mut self , address : A , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > ;
309
-
310
- /// Writes bytes to slave with address `address`
311
- ///
312
- /// # I2C Events (contract)
313
- ///
314
- /// Same as the `write` method
315
- fn write_iter < B > ( & mut self , address : A , bytes : B ) -> Result < ( ) , Self :: Error >
316
- where
317
- B : IntoIterator < Item = u8 > ;
322
+ fn write ( & mut self , address : A , write : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
323
+ self . transaction ( address, & mut [ Operation :: Write ( write) ] )
324
+ }
318
325
319
- /// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer ` *in a
326
+ /// Writes bytes to slave with address `address` and then reads enough bytes to fill `read ` *in a
320
327
/// single transaction*
321
328
///
322
329
/// # I2C Events (contract)
@@ -338,27 +345,12 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
338
345
/// - `MAK` = master acknowledge
339
346
/// - `NMAK` = master no acknowledge
340
347
/// - `SP` = stop condition
341
- fn write_read (
342
- & mut self ,
343
- address : A ,
344
- bytes : & [ u8 ] ,
345
- buffer : & mut [ u8 ] ,
346
- ) -> Result < ( ) , Self :: Error > ;
347
-
348
- /// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
349
- /// single transaction*
350
- ///
351
- /// # I2C Events (contract)
352
- ///
353
- /// Same as the `write_read` method
354
- fn write_iter_read < B > (
355
- & mut self ,
356
- address : A ,
357
- bytes : B ,
358
- buffer : & mut [ u8 ] ,
359
- ) -> Result < ( ) , Self :: Error >
360
- where
361
- B : IntoIterator < Item = u8 > ;
348
+ fn write_read ( & mut self , address : A , write : & [ u8 ] , read : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
349
+ self . transaction (
350
+ address,
351
+ & mut [ Operation :: Write ( write) , Operation :: Read ( read) ] ,
352
+ )
353
+ }
362
354
363
355
/// Execute the provided operations on the I2C bus.
364
356
///
@@ -373,79 +365,31 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
373
365
/// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
374
366
/// - `SR` = repeated start condition
375
367
/// - `SP` = stop condition
376
- fn transaction < ' a > (
368
+ fn transaction (
377
369
& mut self ,
378
370
address : A ,
379
- operations : & mut [ Operation < ' a > ] ,
371
+ operations : & mut [ Operation < ' _ > ] ,
380
372
) -> Result < ( ) , Self :: Error > ;
381
-
382
- /// Execute the provided operations on the I2C bus (iterator version).
383
- ///
384
- /// Transaction contract:
385
- /// - Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate.
386
- /// - Data from adjacent operations of the same type are sent after each other without an SP or SR.
387
- /// - Between adjacent operations of a different type an SR and SAD+R/W is sent.
388
- /// - After executing the last operation an SP is sent automatically.
389
- /// - If the last operation is a `Read` the master does not send an acknowledge for the last byte.
390
- ///
391
- /// - `ST` = start condition
392
- /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
393
- /// - `SR` = repeated start condition
394
- /// - `SP` = stop condition
395
- fn transaction_iter < ' a , O > ( & mut self , address : A , operations : O ) -> Result < ( ) , Self :: Error >
396
- where
397
- O : IntoIterator < Item = Operation < ' a > > ;
398
373
}
399
374
400
375
impl < A : AddressMode , T : I2c < A > > I2c < A > for & mut T {
401
- fn read ( & mut self , address : A , buffer : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
402
- T :: read ( self , address, buffer)
403
- }
404
-
405
- fn write ( & mut self , address : A , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
406
- T :: write ( self , address, bytes)
407
- }
408
-
409
- fn write_iter < B > ( & mut self , address : A , bytes : B ) -> Result < ( ) , Self :: Error >
410
- where
411
- B : IntoIterator < Item = u8 > ,
412
- {
413
- T :: write_iter ( self , address, bytes)
376
+ fn read ( & mut self , address : A , read : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
377
+ T :: read ( self , address, read)
414
378
}
415
379
416
- fn write_read (
417
- & mut self ,
418
- address : A ,
419
- bytes : & [ u8 ] ,
420
- buffer : & mut [ u8 ] ,
421
- ) -> Result < ( ) , Self :: Error > {
422
- T :: write_read ( self , address, bytes, buffer)
380
+ fn write ( & mut self , address : A , write : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
381
+ T :: write ( self , address, write)
423
382
}
424
383
425
- fn write_iter_read < B > (
426
- & mut self ,
427
- address : A ,
428
- bytes : B ,
429
- buffer : & mut [ u8 ] ,
430
- ) -> Result < ( ) , Self :: Error >
431
- where
432
- B : IntoIterator < Item = u8 > ,
433
- {
434
- T :: write_iter_read ( self , address, bytes, buffer)
384
+ fn write_read ( & mut self , address : A , write : & [ u8 ] , read : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
385
+ T :: write_read ( self , address, write, read)
435
386
}
436
387
437
- fn transaction < ' a > (
388
+ fn transaction (
438
389
& mut self ,
439
390
address : A ,
440
- operations : & mut [ Operation < ' a > ] ,
391
+ operations : & mut [ Operation < ' _ > ] ,
441
392
) -> Result < ( ) , Self :: Error > {
442
393
T :: transaction ( self , address, operations)
443
394
}
444
-
445
- fn transaction_iter < ' a , O > ( & mut self , address : A , operations : O ) -> Result < ( ) , Self :: Error >
446
- where
447
- O : IntoIterator < Item = Operation < ' a > > ,
448
- {
449
- T :: transaction_iter ( self , address, operations)
450
- }
451
395
}
0 commit comments