Skip to content

Commit 4f3ada1

Browse files
Merge #316
316: I2C NACK error nesting r=therealprof a=yodaldevoid This idea was first proposed [here](#296 (comment)), but broken out to keep things moving. This merges `ErrorKind::NoAcknowledgeData` and `ErrorKind::NoAcknowledgeAddress` into one variant with a source field to indicate what the NACK was in response to. Some drivers may not be able to differentiate between NACKs on address or data bytes so they should use `NoAcknowledgeSource::Unknown`. Feel free to bikeshed names and documentation. I used the most obvious names to me, but naming is one of the hardest problems in programming. Co-authored-by: Gabriel Smith <[email protected]>
2 parents 86adcd7 + c5d1799 commit 4f3ada1

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1313
implement these `Error` traits, which implies providing a conversion to a common
1414
set of error kinds. Generic drivers using these interfaces can then convert the errors
1515
to this common set to act upon them.
16+
- The `NoAcknowledgeAddress` and `NoAcknowledgeData` variants of the I2C `Error`
17+
trait have been merged into `NoAcknowledge` with a `NoAcknowledgeSource` field
18+
to differentiate between the two events. An additional `Unknown` variant is
19+
provided in `NoAcknowledgeSource` for devices that can't differentiate between
20+
the two events.
1621

1722
### Removed
1823
- Removed `DelayMs` in favor of `DelayUs` with `u32` as type for clarity.

src/i2c.rs

+34-7
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,38 @@ pub trait Error: core::fmt::Debug {
119119
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
120120
#[non_exhaustive]
121121
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.
122+
/// Bus error occurred. e.g. A START or a STOP condition is detected and is not
123+
/// located after a multiple of 9 SCL clock pulses.
123124
Bus,
124125
/// The arbitration was lost, e.g. electrical problems with the clock signal
125126
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,
127+
/// A bus operation was not acknowledged, e.g. due to the addressed device not
128+
/// being available on the bus or the device not being ready to process requests
129+
/// at the moment
130+
NoAcknowledge(NoAcknowledgeSource),
130131
/// The peripheral receive buffer was overrun
131132
Overrun,
132133
/// A different error occurred. The original error may contain more information.
133134
Other,
134135
}
135136

137+
/// I2C no acknowledge error source
138+
///
139+
/// In cases where it is possible, a device should indicate if a no acknowledge
140+
/// response was received to an address versus a no acknowledge to a data byte.
141+
/// Where it is not possible to differentiate, `Unknown` should be indicated.
142+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
143+
pub enum NoAcknowledgeSource {
144+
/// The device did not acknowledge its address. The device may be missing.
145+
Address,
146+
/// The device did not acknowledge the data. It may not be ready to process
147+
/// requests at the moment.
148+
Data,
149+
/// Either the device did not acknowledge its address or the data, but it is
150+
/// unknown which.
151+
Unknown,
152+
}
153+
136154
impl Error for ErrorKind {
137155
fn kind(&self) -> ErrorKind {
138156
*self
@@ -144,8 +162,7 @@ impl core::fmt::Display for ErrorKind {
144162
match self {
145163
Self::Bus => write!(f, "Bus error occurred"),
146164
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"),
165+
Self::NoAcknowledge(s) => s.fmt(f),
149166
Self::Overrun => write!(f, "The peripheral receive buffer was overrun"),
150167
Self::Other => write!(
151168
f,
@@ -155,6 +172,16 @@ impl core::fmt::Display for ErrorKind {
155172
}
156173
}
157174

175+
impl core::fmt::Display for NoAcknowledgeSource {
176+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177+
match self {
178+
Self::Address => write!(f, "The device did not acknowledge its address"),
179+
Self::Data => write!(f, "The device did not acknowledge the data"),
180+
Self::Unknown => write!(f, "The device did not acknowledge its address or the data"),
181+
}
182+
}
183+
}
184+
158185
/// Address mode (7-bit / 10-bit)
159186
///
160187
/// Note: This trait is sealed and should not be implemented outside of this crate.

0 commit comments

Comments
 (0)