Re-introduce Data and Address, again
This commit is contained in:
parent
28e162fa03
commit
e7278ac2f0
@ -107,10 +107,19 @@ pub enum Error {
|
||||
}
|
||||
|
||||
/// I2C no acknowledge error reason.
|
||||
///
|
||||
/// Consider this as a hint and make sure to always handle all cases.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum AcknowledgeCheckFailedReason {
|
||||
/// 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,
|
||||
@ -119,6 +128,8 @@ pub enum AcknowledgeCheckFailedReason {
|
||||
impl core::fmt::Display for AcknowledgeCheckFailedReason {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
AcknowledgeCheckFailedReason::Address => write!(f, "Address"),
|
||||
AcknowledgeCheckFailedReason::Data => write!(f, "Data"),
|
||||
AcknowledgeCheckFailedReason::Unknown => write!(f, "Unknown"),
|
||||
}
|
||||
}
|
||||
@ -127,6 +138,10 @@ impl core::fmt::Display for AcknowledgeCheckFailedReason {
|
||||
impl From<&AcknowledgeCheckFailedReason> for embedded_hal::i2c::NoAcknowledgeSource {
|
||||
fn from(value: &AcknowledgeCheckFailedReason) -> Self {
|
||||
match value {
|
||||
AcknowledgeCheckFailedReason::Address => {
|
||||
embedded_hal::i2c::NoAcknowledgeSource::Address
|
||||
}
|
||||
AcknowledgeCheckFailedReason::Data => embedded_hal::i2c::NoAcknowledgeSource::Data,
|
||||
AcknowledgeCheckFailedReason::Unknown => {
|
||||
embedded_hal::i2c::NoAcknowledgeSource::Unknown
|
||||
}
|
||||
@ -687,9 +702,9 @@ impl<'a> I2cFuture<'a> {
|
||||
}
|
||||
|
||||
if r.nack().bit_is_set() {
|
||||
return Err(Error::AcknowledgeCheckFailed(
|
||||
AcknowledgeCheckFailedReason::Unknown,
|
||||
));
|
||||
return Err(Error::AcknowledgeCheckFailed(estimate_ack_failed_reason(
|
||||
self.info.register_block(),
|
||||
)));
|
||||
}
|
||||
|
||||
#[cfg(not(esp32))]
|
||||
@ -703,7 +718,7 @@ impl<'a> I2cFuture<'a> {
|
||||
.bit_is_clear()
|
||||
{
|
||||
return Err(Error::AcknowledgeCheckFailed(
|
||||
AcknowledgeCheckFailedReason::Unknown,
|
||||
AcknowledgeCheckFailedReason::Data,
|
||||
));
|
||||
}
|
||||
|
||||
@ -1719,7 +1734,7 @@ impl Driver<'_> {
|
||||
let retval = if interrupts.time_out().bit_is_set() {
|
||||
Err(Error::Timeout)
|
||||
} else if interrupts.nack().bit_is_set() {
|
||||
Err(Error::AcknowledgeCheckFailed(AcknowledgeCheckFailedReason::Unknown))
|
||||
Err(Error::AcknowledgeCheckFailed(estimate_ack_failed_reason(self.register_block())))
|
||||
} else if interrupts.arbitration_lost().bit_is_set() {
|
||||
Err(Error::ArbitrationLost)
|
||||
} else {
|
||||
@ -1730,11 +1745,11 @@ impl Driver<'_> {
|
||||
let retval = if interrupts.time_out().bit_is_set() {
|
||||
Err(Error::Timeout)
|
||||
} else if interrupts.nack().bit_is_set() {
|
||||
Err(Error::AcknowledgeCheckFailed(AcknowledgeCheckFailedReason::Unknown))
|
||||
Err(Error::AcknowledgeCheckFailed(estimate_ack_failed_reason(self.register_block())))
|
||||
} else if interrupts.arbitration_lost().bit_is_set() {
|
||||
Err(Error::ArbitrationLost)
|
||||
} else if interrupts.trans_complete().bit_is_set() && self.register_block().sr().read().resp_rec().bit_is_clear() {
|
||||
Err(Error::AcknowledgeCheckFailed(AcknowledgeCheckFailedReason::Unknown))
|
||||
Err(Error::AcknowledgeCheckFailed(AcknowledgeCheckFailedReason::Data))
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
@ -2318,6 +2333,24 @@ fn write_fifo(register_block: &RegisterBlock, data: u8) {
|
||||
}
|
||||
}
|
||||
|
||||
// Estimate the reason for an acknowledge check failure on a best effort basis.
|
||||
// When in doubt it's better to return `Unknown` than to return a wrong reason.
|
||||
fn estimate_ack_failed_reason(_register_block: &RegisterBlock) -> AcknowledgeCheckFailedReason {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(esp32, esp32s2, esp32c2, esp32c3))] {
|
||||
AcknowledgeCheckFailedReason::Unknown
|
||||
} else {
|
||||
// this is based on observations rather than documented behavior
|
||||
if _register_block.fifo_st().read().txfifo_raddr().bits() <= 1 {
|
||||
return AcknowledgeCheckFailedReason::Address;
|
||||
} else {
|
||||
return AcknowledgeCheckFailedReason::Data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! instance {
|
||||
($inst:ident, $peri:ident, $scl:ident, $sda:ident, $interrupt:ident) => {
|
||||
impl Instance for crate::peripherals::$inst {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user