summaryrefslogtreecommitdiff
path: root/embassy-rp
diff options
context:
space:
mode:
authorMathias <mk@blackbird.online>2022-08-26 14:24:49 +0200
committerDario Nieuwenhuis <dirbaio@dirbaio.net>2022-09-27 22:08:49 +0200
commitbe68d8ebb773fcf6d0cb94f3bc580d6661f6779b (patch)
tree24e863b91aa615598979ded49655deb562b79bd8 /embassy-rp
parent603513e76e0cf727808033540598c6c7dd597133 (diff)
downloadembassy-be68d8ebb773fcf6d0cb94f3bc580d6661f6779b.zip
Add further i2c error types
Diffstat (limited to 'embassy-rp')
-rw-r--r--embassy-rp/src/clocks.rs2
-rw-r--r--embassy-rp/src/i2c.rs69
2 files changed, 45 insertions, 26 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index 875c129c..1c446f38 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -114,7 +114,7 @@ pub unsafe fn init() {
reset::unreset_wait(peris);
}
-pub(crate) fn clk_sys_freq() -> u32 {
+pub(crate) fn _clk_sys_freq() -> u32 {
125_000_000
}
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index b368c49c..20616cd6 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -5,12 +5,25 @@ use pac::i2c;
use crate::{pac, peripherals, Peripheral};
+/// I2C error abort reason
+#[derive(Debug)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum AbortReason {
+ /// 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,
+ /// The arbitration was lost, e.g. electrical problems with the clock signal
+ ArbitrationLoss,
+ Other(u32),
+}
+
/// I2C error
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
/// I2C abort with error
- Abort(u32),
+ Abort(AbortReason),
/// User passed in a read buffer that was 0 length
InvalidReadBufferLength,
/// User passed in a write buffer that was 0 length
@@ -29,9 +42,7 @@ pub struct Config {
impl Default for Config {
fn default() -> Self {
- Self {
- frequency: 100_000,
- }
+ Self { frequency: 100_000 }
}
}
@@ -164,18 +175,30 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
Ok(())
}
- fn read_and_clear_abort_reason(&mut self) -> Option<u32> {
+ fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> {
let p = T::regs();
unsafe {
- let abort_reason = p.ic_tx_abrt_source().read().0;
- if abort_reason != 0 {
+ let abort_reason = p.ic_tx_abrt_source().read();
+ if abort_reason.0 != 0 {
// Note clearing the abort flag also clears the reason, and this
// instance of flag is clear-on-read! Note also the
// IC_CLR_TX_ABRT register always reads as 0.
p.ic_clr_tx_abrt().read();
- Some(abort_reason)
+
+ let reason = if abort_reason.abrt_7b_addr_noack()
+ | abort_reason.abrt_10addr1_noack()
+ | abort_reason.abrt_10addr2_noack()
+ {
+ AbortReason::NoAcknowledge
+ } else if abort_reason.arb_lost() {
+ AbortReason::ArbitrationLoss
+ } else {
+ AbortReason::Other(abort_reason.0)
+ };
+
+ Err(Error::Abort(reason))
} else {
- None
+ Ok(())
}
}
}
@@ -204,9 +227,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
});
while p.ic_rxflr().read().rxflr() == 0 {
- if let Some(abort_reason) = self.read_and_clear_abort_reason() {
- return Err(Error::Abort(abort_reason));
- }
+ self.read_and_clear_abort_reason()?;
}
*byte = p.ic_data_cmd().read().dat();
@@ -241,7 +262,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
let abort_reason = self.read_and_clear_abort_reason();
- if abort_reason.is_some() || (send_stop && last) {
+ if abort_reason.is_err() || (send_stop && last) {
// If the transaction was aborted or if it completed
// successfully wait until the STOP condition has occured.
@@ -254,9 +275,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
// condition. Note also the hardware clears RX FIFO as well as
// TX on abort, ecause we set hwparam
// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0.
- if let Some(abort_reason) = abort_reason {
- return Err(Error::Abort(abort_reason));
- }
+ abort_reason?;
}
}
Ok(())
@@ -360,15 +379,15 @@ mod eh1 {
impl embedded_hal_1::i2c::Error for Error {
fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
match *self {
- _ => embedded_hal_1::i2c::ErrorKind::Bus,
- // Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss,
- // Self::Nack => {
- // embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Unknown)
- // }
- // Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other,
- // Self::Crc => embedded_hal_1::i2c::ErrorKind::Other,
- // Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun,
- // Self::ZeroLengthTransfer => embedded_hal_1::i2c::ErrorKind::Other,
+ Self::Abort(AbortReason::ArbitrationLoss) => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss,
+ Self::Abort(AbortReason::NoAcknowledge) => {
+ embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address)
+ }
+ Self::Abort(AbortReason::Other(_)) => embedded_hal_1::i2c::ErrorKind::Other,
+ Self::InvalidReadBufferLength => embedded_hal_1::i2c::ErrorKind::Other,
+ Self::InvalidWriteBufferLength => embedded_hal_1::i2c::ErrorKind::Other,
+ Self::AddressOutOfRange(_) => embedded_hal_1::i2c::ErrorKind::Other,
+ Self::AddressReserved(_) => embedded_hal_1::i2c::ErrorKind::Other,
}
}
}