Skip to content

I2C NACK error nesting #316

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
implement these `Error` traits, which implies providing a conversion to a common
set of error kinds. Generic drivers using these interfaces can then convert the errors
to this common set to act upon them.
- The `NoAcknowledgeAddress` and `NoAcknowledgeData` variants of the I2C `Error`
trait have been merged into `NoAcknowledge` with a `NoAcknowledgeSource` field
to differentiate between the two events. An additional `Unknown` variant is
provided in `NoAcknowledgeSource` for devices that can't differentiate between
the two events.

### Removed
- Removed `DelayMs` in favor of `DelayUs` with `u32` as type for clarity.
Expand Down
41 changes: 34 additions & 7 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,38 @@ pub trait Error: core::fmt::Debug {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[non_exhaustive]
pub enum ErrorKind {
/// 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.
/// 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.
Bus,
/// The arbitration was lost, e.g. electrical problems with the clock signal
ArbitrationLoss,
/// The device did not acknowledge its address. The device may be missing.
NoAcknowledgeAddress,
/// The device did not acknowled the data. It may not be ready to process requests at the moment.
NoAcknowledgeData,
/// A bus operation was not acknowledged, e.g. due to the addressed device not
/// being available on the bus or the device not being ready to process requests
/// at the moment
NoAcknowledge(NoAcknowledgeSource),
/// The peripheral receive buffer was overrun
Overrun,
/// A different error occurred. The original error may contain more information.
Other,
}

/// I2C no acknowledge error source
///
/// In cases where it is possible, a device should indicate if a no acknowledge
/// response was received to an address versus a no acknowledge to a data byte.
/// Where it is not possible to differentiate, `Unknown` should be indicated.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum NoAcknowledgeSource {
/// The device did not acknowledge its address. The device may be missing.
Address,
/// The device did not acknowledge the data. It may not be ready to process
/// requests at the moment.
Data,
/// Either the device did not acknowledge its address or the data, but it is
/// unknown which.
Unknown,
}

impl Error for ErrorKind {
fn kind(&self) -> ErrorKind {
*self
Expand All @@ -144,8 +162,7 @@ impl core::fmt::Display for ErrorKind {
match self {
Self::Bus => write!(f, "Bus error occurred"),
Self::ArbitrationLoss => write!(f, "The arbitration was lost"),
Self::NoAcknowledgeAddress => write!(f, "The device did not acknowledge its address"),
Self::NoAcknowledgeData => write!(f, "The device did not acknowledge the data"),
Self::NoAcknowledge(s) => s.fmt(f),
Self::Overrun => write!(f, "The peripheral receive buffer was overrun"),
Self::Other => write!(
f,
Expand All @@ -155,6 +172,16 @@ impl core::fmt::Display for ErrorKind {
}
}

impl core::fmt::Display for NoAcknowledgeSource {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Address => write!(f, "The device did not acknowledge its address"),
Self::Data => write!(f, "The device did not acknowledge the data"),
Self::Unknown => write!(f, "The device did not acknowledge its address or the data"),
}
}
}

/// Address mode (7-bit / 10-bit)
///
/// Note: This trait is sealed and should not be implemented outside of this crate.
Expand Down