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.
|
/// 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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum AcknowledgeCheckFailedReason {
|
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
|
/// Either the device did not acknowledge its address or the data, but it is
|
||||||
/// unknown which.
|
/// unknown which.
|
||||||
Unknown,
|
Unknown,
|
||||||
@ -119,6 +128,8 @@ pub enum AcknowledgeCheckFailedReason {
|
|||||||
impl core::fmt::Display for AcknowledgeCheckFailedReason {
|
impl core::fmt::Display for AcknowledgeCheckFailedReason {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
AcknowledgeCheckFailedReason::Address => write!(f, "Address"),
|
||||||
|
AcknowledgeCheckFailedReason::Data => write!(f, "Data"),
|
||||||
AcknowledgeCheckFailedReason::Unknown => write!(f, "Unknown"),
|
AcknowledgeCheckFailedReason::Unknown => write!(f, "Unknown"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,6 +138,10 @@ impl core::fmt::Display for AcknowledgeCheckFailedReason {
|
|||||||
impl From<&AcknowledgeCheckFailedReason> for embedded_hal::i2c::NoAcknowledgeSource {
|
impl From<&AcknowledgeCheckFailedReason> for embedded_hal::i2c::NoAcknowledgeSource {
|
||||||
fn from(value: &AcknowledgeCheckFailedReason) -> Self {
|
fn from(value: &AcknowledgeCheckFailedReason) -> Self {
|
||||||
match value {
|
match value {
|
||||||
|
AcknowledgeCheckFailedReason::Address => {
|
||||||
|
embedded_hal::i2c::NoAcknowledgeSource::Address
|
||||||
|
}
|
||||||
|
AcknowledgeCheckFailedReason::Data => embedded_hal::i2c::NoAcknowledgeSource::Data,
|
||||||
AcknowledgeCheckFailedReason::Unknown => {
|
AcknowledgeCheckFailedReason::Unknown => {
|
||||||
embedded_hal::i2c::NoAcknowledgeSource::Unknown
|
embedded_hal::i2c::NoAcknowledgeSource::Unknown
|
||||||
}
|
}
|
||||||
@ -687,9 +702,9 @@ impl<'a> I2cFuture<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r.nack().bit_is_set() {
|
if r.nack().bit_is_set() {
|
||||||
return Err(Error::AcknowledgeCheckFailed(
|
return Err(Error::AcknowledgeCheckFailed(estimate_ack_failed_reason(
|
||||||
AcknowledgeCheckFailedReason::Unknown,
|
self.info.register_block(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(esp32))]
|
#[cfg(not(esp32))]
|
||||||
@ -703,7 +718,7 @@ impl<'a> I2cFuture<'a> {
|
|||||||
.bit_is_clear()
|
.bit_is_clear()
|
||||||
{
|
{
|
||||||
return Err(Error::AcknowledgeCheckFailed(
|
return Err(Error::AcknowledgeCheckFailed(
|
||||||
AcknowledgeCheckFailedReason::Unknown,
|
AcknowledgeCheckFailedReason::Data,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1719,7 +1734,7 @@ impl Driver<'_> {
|
|||||||
let retval = if interrupts.time_out().bit_is_set() {
|
let retval = if interrupts.time_out().bit_is_set() {
|
||||||
Err(Error::Timeout)
|
Err(Error::Timeout)
|
||||||
} else if interrupts.nack().bit_is_set() {
|
} 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() {
|
} else if interrupts.arbitration_lost().bit_is_set() {
|
||||||
Err(Error::ArbitrationLost)
|
Err(Error::ArbitrationLost)
|
||||||
} else {
|
} else {
|
||||||
@ -1730,11 +1745,11 @@ impl Driver<'_> {
|
|||||||
let retval = if interrupts.time_out().bit_is_set() {
|
let retval = if interrupts.time_out().bit_is_set() {
|
||||||
Err(Error::Timeout)
|
Err(Error::Timeout)
|
||||||
} else if interrupts.nack().bit_is_set() {
|
} 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() {
|
} else if interrupts.arbitration_lost().bit_is_set() {
|
||||||
Err(Error::ArbitrationLost)
|
Err(Error::ArbitrationLost)
|
||||||
} else if interrupts.trans_complete().bit_is_set() && self.register_block().sr().read().resp_rec().bit_is_clear() {
|
} 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 {
|
} else {
|
||||||
Ok(())
|
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 {
|
macro_rules! instance {
|
||||||
($inst:ident, $peri:ident, $scl:ident, $sda:ident, $interrupt:ident) => {
|
($inst:ident, $peri:ident, $scl:ident, $sda:ident, $interrupt:ident) => {
|
||||||
impl Instance for crate::peripherals::$inst {
|
impl Instance for crate::peripherals::$inst {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user