aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-08-26 14:24:49 +0200
committerDario Nieuwenhuis <[email protected]>2022-09-27 22:08:49 +0200
commitbe68d8ebb773fcf6d0cb94f3bc580d6661f6779b (patch)
tree24e863b91aa615598979ded49655deb562b79bd8
parent603513e76e0cf727808033540598c6c7dd597133 (diff)
Add further i2c error types
-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 875c129c0..1c446f389 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -114,7 +114,7 @@ pub unsafe fn init() {
114 reset::unreset_wait(peris); 114 reset::unreset_wait(peris);
115} 115}
116 116
117pub(crate) fn clk_sys_freq() -> u32 { 117pub(crate) fn _clk_sys_freq() -> u32 {
118 125_000_000 118 125_000_000
119} 119}
120 120
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index b368c49cf..20616cd62 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -5,12 +5,25 @@ use pac::i2c;
5 5
6use crate::{pac, peripherals, Peripheral}; 6use crate::{pac, peripherals, Peripheral};
7 7
8/// I2C error abort reason
9#[derive(Debug)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub enum AbortReason {
12 /// A bus operation was not acknowledged, e.g. due to the addressed device
13 /// not being available on the bus or the device not being ready to process
14 /// requests at the moment
15 NoAcknowledge,
16 /// The arbitration was lost, e.g. electrical problems with the clock signal
17 ArbitrationLoss,
18 Other(u32),
19}
20
8/// I2C error 21/// I2C error
9#[derive(Debug)] 22#[derive(Debug)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))] 23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub enum Error { 24pub enum Error {
12 /// I2C abort with error 25 /// I2C abort with error
13 Abort(u32), 26 Abort(AbortReason),
14 /// User passed in a read buffer that was 0 length 27 /// User passed in a read buffer that was 0 length
15 InvalidReadBufferLength, 28 InvalidReadBufferLength,
16 /// User passed in a write buffer that was 0 length 29 /// User passed in a write buffer that was 0 length
@@ -29,9 +42,7 @@ pub struct Config {
29 42
30impl Default for Config { 43impl Default for Config {
31 fn default() -> Self { 44 fn default() -> Self {
32 Self { 45 Self { frequency: 100_000 }
33 frequency: 100_000,
34 }
35 } 46 }
36} 47}
37 48
@@ -164,18 +175,30 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
164 Ok(()) 175 Ok(())
165 } 176 }
166 177
167 fn read_and_clear_abort_reason(&mut self) -> Option<u32> { 178 fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> {
168 let p = T::regs(); 179 let p = T::regs();
169 unsafe { 180 unsafe {
170 let abort_reason = p.ic_tx_abrt_source().read().0; 181 let abort_reason = p.ic_tx_abrt_source().read();
171 if abort_reason != 0 { 182 if abort_reason.0 != 0 {
172 // Note clearing the abort flag also clears the reason, and this 183 // Note clearing the abort flag also clears the reason, and this
173 // instance of flag is clear-on-read! Note also the 184 // instance of flag is clear-on-read! Note also the
174 // IC_CLR_TX_ABRT register always reads as 0. 185 // IC_CLR_TX_ABRT register always reads as 0.
175 p.ic_clr_tx_abrt().read(); 186 p.ic_clr_tx_abrt().read();
176 Some(abort_reason) 187
188 let reason = if abort_reason.abrt_7b_addr_noack()
189 | abort_reason.abrt_10addr1_noack()
190 | abort_reason.abrt_10addr2_noack()
191 {
192 AbortReason::NoAcknowledge
193 } else if abort_reason.arb_lost() {
194 AbortReason::ArbitrationLoss
195 } else {
196 AbortReason::Other(abort_reason.0)
197 };
198
199 Err(Error::Abort(reason))
177 } else { 200 } else {
178 None 201 Ok(())
179 } 202 }
180 } 203 }
181 } 204 }
@@ -204,9 +227,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
204 }); 227 });
205 228
206 while p.ic_rxflr().read().rxflr() == 0 { 229 while p.ic_rxflr().read().rxflr() == 0 {
207 if let Some(abort_reason) = self.read_and_clear_abort_reason() { 230 self.read_and_clear_abort_reason()?;
208 return Err(Error::Abort(abort_reason));
209 }
210 } 231 }
211 232
212 *byte = p.ic_data_cmd().read().dat(); 233 *byte = p.ic_data_cmd().read().dat();
@@ -241,7 +262,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
241 262
242 let abort_reason = self.read_and_clear_abort_reason(); 263 let abort_reason = self.read_and_clear_abort_reason();
243 264
244 if abort_reason.is_some() || (send_stop && last) { 265 if abort_reason.is_err() || (send_stop && last) {
245 // If the transaction was aborted or if it completed 266 // If the transaction was aborted or if it completed
246 // successfully wait until the STOP condition has occured. 267 // successfully wait until the STOP condition has occured.
247 268
@@ -254,9 +275,7 @@ impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
254 // condition. Note also the hardware clears RX FIFO as well as 275 // condition. Note also the hardware clears RX FIFO as well as
255 // TX on abort, ecause we set hwparam 276 // TX on abort, ecause we set hwparam
256 // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0. 277 // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0.
257 if let Some(abort_reason) = abort_reason { 278 abort_reason?;
258 return Err(Error::Abort(abort_reason));
259 }
260 } 279 }
261 } 280 }
262 Ok(()) 281 Ok(())
@@ -360,15 +379,15 @@ mod eh1 {
360 impl embedded_hal_1::i2c::Error for Error { 379 impl embedded_hal_1::i2c::Error for Error {
361 fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { 380 fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
362 match *self { 381 match *self {
363 _ => embedded_hal_1::i2c::ErrorKind::Bus, 382 Self::Abort(AbortReason::ArbitrationLoss) => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss,
364 // Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss, 383 Self::Abort(AbortReason::NoAcknowledge) => {
365 // Self::Nack => { 384 embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address)
366 // embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Unknown) 385 }
367 // } 386 Self::Abort(AbortReason::Other(_)) => embedded_hal_1::i2c::ErrorKind::Other,
368 // Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other, 387 Self::InvalidReadBufferLength => embedded_hal_1::i2c::ErrorKind::Other,
369 // Self::Crc => embedded_hal_1::i2c::ErrorKind::Other, 388 Self::InvalidWriteBufferLength => embedded_hal_1::i2c::ErrorKind::Other,
370 // Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun, 389 Self::AddressOutOfRange(_) => embedded_hal_1::i2c::ErrorKind::Other,
371 // Self::ZeroLengthTransfer => embedded_hal_1::i2c::ErrorKind::Other, 390 Self::AddressReserved(_) => embedded_hal_1::i2c::ErrorKind::Other,
372 } 391 }
373 } 392 }
374 } 393 }