Skip to content

Commit ceee3f3

Browse files
Merge #208
208: Updating I2C to wait for STOP to be sent before returning r=therealprof a=ryan-summers This PR updates the I2C driver to properly wait for the STOP condition to finish transmitting before returning for i2c write and read. This is necessary to prevent a race condition on the peripheral. If another transaction is started fast enough (before the STOP condition can be sent), it is possible that the I2C state will be mismanaged. This fixes #207 I have tested this on a local hardware setup using a large fan of I2C devices where rapid I2C writes and reads are completed in a loop as part of a self test Co-authored-by: Ryan Summers <[email protected]>
2 parents 6de379d + 894880b commit ceee3f3

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

src/i2c.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,9 @@ where
932932
// Send a STOP condition
933933
self.i2c.cr1.modify(|_, w| w.stop().set_bit());
934934

935+
// Wait for STOP condition to transmit.
936+
while self.i2c.cr1.read().stop().bit_is_set() {}
937+
935938
// Fallthrough is success
936939
Ok(())
937940
}
@@ -965,7 +968,10 @@ where
965968
.write(|w| unsafe { w.bits((u32::from(addr) << 1) + 1) });
966969

967970
// Wait until address was sent
968-
while self.i2c.sr1.read().addr().bit_is_clear() {}
971+
while {
972+
self.check_and_clear_error_flags()?;
973+
self.i2c.sr1.read().addr().bit_is_clear()
974+
} {}
969975

970976
// Clear condition by reading SR2
971977
self.i2c.sr2.read();
@@ -983,6 +989,9 @@ where
983989
// Receive last byte
984990
*last = self.recv_byte()?;
985991

992+
// Wait for the STOP to be sent.
993+
while self.i2c.cr1.read().stop().bit_is_set() {}
994+
986995
// Fallthrough is success
987996
Ok(())
988997
} else {

0 commit comments

Comments
 (0)