Skip to content

Commit 6a576da

Browse files
authored
Made I2C more resilient by handling more error conditions (#95)
Signed-off-by: Daniel Egger <daniel@eggers-club.de>
1 parent 8195927 commit 6a576da

File tree

1 file changed

+37
-14
lines changed

1 file changed

+37
-14
lines changed

src/i2c.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ i2c_pins! {
149149
pub enum Error {
150150
OVERRUN,
151151
NACK,
152+
BUS,
152153
}
153154

154155
macro_rules! i2c {
@@ -257,8 +258,22 @@ where
257258
(self.i2c, self.pins)
258259
}
259260

260-
fn check_and_clear_error_flags(&self, isr: &crate::pac::i2c1::isr::R) -> Result<(), Error> {
261-
// If we received a NACK, then this is an error
261+
fn check_and_clear_error_flags(&self, isr: &crate::stm32::i2c1::isr::R) -> Result<(), Error> {
262+
// If we have a set overrun flag, clear it and return an OVERRUN error
263+
if isr.ovr().bit_is_set() {
264+
self.i2c.icr.write(|w| w.ovrcf().set_bit());
265+
return Err(Error::OVERRUN);
266+
}
267+
268+
// If we have a set arbitration error or bus error flag, clear it and return an BUS error
269+
if isr.arlo().bit_is_set() | isr.berr().bit_is_set() {
270+
self.i2c
271+
.icr
272+
.write(|w| w.arlocf().set_bit().berrcf().set_bit());
273+
return Err(Error::BUS);
274+
}
275+
276+
// If we received a NACK, then signal as a NACK error
262277
if isr.nackf().bit_is_set() {
263278
self.i2c
264279
.icr
@@ -271,11 +286,13 @@ where
271286

272287
fn send_byte(&self, byte: u8) -> Result<(), Error> {
273288
// Wait until we're ready for sending
274-
while {
289+
loop {
275290
let isr = self.i2c.isr.read();
276291
self.check_and_clear_error_flags(&isr)?;
277-
isr.txis().bit_is_clear()
278-
} {}
292+
if isr.txis().bit_is_set() {
293+
break;
294+
}
295+
}
279296

280297
// Push out a byte of data
281298
self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) });
@@ -285,11 +302,13 @@ where
285302
}
286303

287304
fn recv_byte(&self) -> Result<u8, Error> {
288-
while {
305+
loop {
289306
let isr = self.i2c.isr.read();
290307
self.check_and_clear_error_flags(&isr)?;
291-
isr.rxne().bit_is_clear()
292-
} {}
308+
if isr.rxne().bit_is_set() {
309+
break;
310+
}
311+
}
293312

294313
let value = self.i2c.rxdr.read().bits() as u8;
295314
Ok(value)
@@ -319,23 +338,27 @@ where
319338
self.i2c.cr2.modify(|_, w| w.start().set_bit());
320339

321340
// Wait until the transmit buffer is empty and there hasn't been any error condition
322-
while {
341+
loop {
323342
let isr = self.i2c.isr.read();
324343
self.check_and_clear_error_flags(&isr)?;
325-
isr.txis().bit_is_clear() && isr.tc().bit_is_clear()
326-
} {}
344+
if isr.txis().bit_is_set() || isr.tc().bit_is_set() {
345+
break;
346+
}
347+
}
327348

328349
// Send out all individual bytes
329350
for c in bytes {
330351
self.send_byte(*c)?;
331352
}
332353

333354
// Wait until data was sent
334-
while {
355+
loop {
335356
let isr = self.i2c.isr.read();
336357
self.check_and_clear_error_flags(&isr)?;
337-
isr.tc().bit_is_clear()
338-
} {}
358+
if isr.tc().bit_is_set() {
359+
break;
360+
}
361+
}
339362

340363
// Set up current address for reading
341364
self.i2c.cr2.modify(|_, w| {

0 commit comments

Comments
 (0)