2626//! Here is an example of an embedded-hal implementation of the `Write` trait
2727//! for both modes:
2828//! ```
29- //! # use embedded_hal::i2c::{SevenBitAddress, TenBitAddress, blocking::Write};
29+ //! # use embedded_hal::i2c::{ErrorKind, SevenBitAddress, TenBitAddress, blocking::Write};
3030//! /// I2C0 hardware peripheral which supports both 7-bit and 10-bit addressing.
3131//! pub struct I2c0;
3232//!
3333//! impl Write<SevenBitAddress> for I2c0
3434//! {
35- //! # type Error = () ;
35+ //! # type Error = ErrorKind ;
3636//! #
3737//! fn write(&mut self, addr: u8, output: &[u8]) -> Result<(), Self::Error> {
3838//! // ...
4242//!
4343//! impl Write<TenBitAddress> for I2c0
4444//! {
45- //! # type Error = () ;
45+ //! # type Error = ErrorKind ;
4646//! #
4747//! fn write(&mut self, addr: u16, output: &[u8]) -> Result<(), Self::Error> {
4848//! // ...
5656//! For demonstration purposes the address mode parameter has been omitted in this example.
5757//!
5858//! ```
59- //! # use embedded_hal::i2c::blocking::WriteRead;
59+ //! # use embedded_hal::i2c::{ blocking::WriteRead, Error} ;
6060//! const ADDR: u8 = 0x15;
6161//! # const TEMP_REGISTER: u8 = 0x1;
6262//! pub struct TemperatureSensorDriver<I2C> {
6363//! i2c: I2C,
6464//! }
6565//!
66- //! impl<I2C, E: core::fmt::Debug > TemperatureSensorDriver<I2C>
66+ //! impl<I2C, E: Error > TemperatureSensorDriver<I2C>
6767//! where
6868//! I2C: WriteRead<Error = E>,
6969//! {
7979//! ### Device driver compatible only with 10-bit addresses
8080//!
8181//! ```
82- //! # use embedded_hal::i2c::{TenBitAddress, blocking::WriteRead};
82+ //! # use embedded_hal::i2c::{Error, TenBitAddress, blocking::WriteRead};
8383//! const ADDR: u16 = 0x158;
8484//! # const TEMP_REGISTER: u8 = 0x1;
8585//! pub struct TemperatureSensorDriver<I2C> {
8686//! i2c: I2C,
8787//! }
8888//!
89- //! impl<I2C, E: core::fmt::Debug > TemperatureSensorDriver<I2C>
89+ //! impl<I2C, E: Error > TemperatureSensorDriver<I2C>
9090//! where
9191//! I2C: WriteRead<TenBitAddress, Error = E>,
9292//! {
101101
102102use crate :: private;
103103
104+ /// I2C error
105+ pub trait Error : core:: fmt:: Debug {
106+ /// Convert error to a generic I2C error kind
107+ ///
108+ /// By using this method, I2C errors freely defined by HAL implementations
109+ /// can be converted to a set of generic I2C errors upon which generic
110+ /// code can act.
111+ fn kind ( & self ) -> ErrorKind ;
112+ }
113+
114+ /// I2C error kind
115+ ///
116+ /// This represents a common set of I2C operation errors. HAL implementations are
117+ /// free to define more specific or additional error types. However, by providing
118+ /// a mapping to these common I2C errors, generic code can still react to them.
119+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , Ord , PartialOrd , Hash ) ]
120+ #[ non_exhaustive]
121+ pub enum ErrorKind {
122+ /// Bus error occurred. e.g. A START or a STOP condition is detected and is not located after a multiple of 9 SCL clock pulses.
123+ Bus ,
124+ /// The arbitration was lost, e.g. electrical problems with the clock signal
125+ ArbitrationLoss ,
126+ /// The device did not acknowledge its address. The device may be missing.
127+ NoAcknowledgeAddress ,
128+ /// The device did not acknowled the data. It may not be ready to process requests at the moment.
129+ NoAcknowledgeData ,
130+ /// The peripheral receive buffer was overrun
131+ Overrun ,
132+ /// A different error occurred. The original error may contain more information.
133+ Other ,
134+ }
135+
136+ impl Error for ErrorKind {
137+ fn kind ( & self ) -> ErrorKind {
138+ * self
139+ }
140+ }
141+
142+ impl core:: fmt:: Display for ErrorKind {
143+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
144+ match self {
145+ Self :: Bus => write ! ( f, "Bus error occurred" ) ,
146+ Self :: ArbitrationLoss => write ! ( f, "The arbitration was lost" ) ,
147+ Self :: NoAcknowledgeAddress => write ! ( f, "The device did not acknowledge its address" ) ,
148+ Self :: NoAcknowledgeData => write ! ( f, "The device did not acknowledge the data" ) ,
149+ Self :: Overrun => write ! ( f, "The peripheral receive buffer was overrun" ) ,
150+ Self :: Other => write ! (
151+ f,
152+ "A different error occurred. The original error may contain more information"
153+ ) ,
154+ }
155+ }
156+ }
157+
104158/// Address mode (7-bit / 10-bit)
105159///
106160/// Note: This trait is sealed and should not be implemented outside of this crate.
@@ -119,12 +173,12 @@ impl AddressMode for TenBitAddress {}
119173/// Blocking I2C traits
120174pub mod blocking {
121175
122- use super :: { AddressMode , SevenBitAddress } ;
176+ use super :: { AddressMode , Error , SevenBitAddress } ;
123177
124178 /// Blocking read
125179 pub trait Read < A : AddressMode = SevenBitAddress > {
126180 /// Error type
127- type Error : core :: fmt :: Debug ;
181+ type Error : Error ;
128182
129183 /// Reads enough bytes from slave with `address` to fill `buffer`
130184 ///
@@ -158,7 +212,7 @@ pub mod blocking {
158212 /// Blocking write
159213 pub trait Write < A : AddressMode = SevenBitAddress > {
160214 /// Error type
161- type Error : core :: fmt :: Debug ;
215+ type Error : Error ;
162216
163217 /// Writes bytes to slave with address `address`
164218 ///
@@ -190,7 +244,7 @@ pub mod blocking {
190244 /// Blocking write (iterator version)
191245 pub trait WriteIter < A : AddressMode = SevenBitAddress > {
192246 /// Error type
193- type Error : core :: fmt :: Debug ;
247+ type Error : Error ;
194248
195249 /// Writes bytes to slave with address `address`
196250 ///
@@ -216,7 +270,7 @@ pub mod blocking {
216270 /// Blocking write + read
217271 pub trait WriteRead < A : AddressMode = SevenBitAddress > {
218272 /// Error type
219- type Error : core :: fmt :: Debug ;
273+ type Error : Error ;
220274
221275 /// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
222276 /// single transaction*
@@ -264,7 +318,7 @@ pub mod blocking {
264318 /// Blocking write (iterator version) + read
265319 pub trait WriteIterRead < A : AddressMode = SevenBitAddress > {
266320 /// Error type
267- type Error : core :: fmt :: Debug ;
321+ type Error : Error ;
268322
269323 /// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
270324 /// single transaction*
@@ -314,7 +368,7 @@ pub mod blocking {
314368 /// This allows combining operations within an I2C transaction.
315369 pub trait Transactional < A : AddressMode = SevenBitAddress > {
316370 /// Error type
317- type Error : core :: fmt :: Debug ;
371+ type Error : Error ;
318372
319373 /// Execute the provided operations on the I2C bus.
320374 ///
@@ -353,7 +407,7 @@ pub mod blocking {
353407 /// This allows combining operation within an I2C transaction.
354408 pub trait TransactionalIter < A : AddressMode = SevenBitAddress > {
355409 /// Error type
356- type Error : core :: fmt :: Debug ;
410+ type Error : Error ;
357411
358412 /// Execute the provided operations on the I2C bus (iterator version).
359413 ///
0 commit comments