Skip to content

Commit b25aae5

Browse files
authored
Merge pull request #743 from ZhiyaoMa98/I2C-fix
Let I2C blocking methods wait until STOP is sent.
2 parents 403fddb + fb08190 commit b25aae5

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

src/i2c.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,12 @@ impl<I2C: Instance> I2c<I2C> {
285285
/// Sends START and Address for writing
286286
#[inline(always)]
287287
fn prepare_write(&self, addr: u8) -> Result<(), Error> {
288-
// Wait until a previous STOP condition finishes
288+
// Wait until a previous STOP condition finishes. When the previous
289+
// STOP was generated inside an ISR (e.g. DMA interrupt handler),
290+
// the ISR returns without waiting for the STOP condition to finish.
291+
// It is possible that the STOP condition is still being generated
292+
// when we reach here, so we wait until it finishes before proceeding
293+
// to start a new transaction.
289294
while self.i2c.cr1.read().stop().bit_is_set() {}
290295

291296
// Send a START condition
@@ -330,7 +335,12 @@ impl<I2C: Instance> I2c<I2C> {
330335

331336
/// Sends START and Address for reading
332337
fn prepare_read(&self, addr: u8) -> Result<(), Error> {
333-
// Wait until a previous STOP condition finishes
338+
// Wait until a previous STOP condition finishes. When the previous
339+
// STOP was generated inside an ISR (e.g. DMA interrupt handler),
340+
// the ISR returns without waiting for the STOP condition to finish.
341+
// It is possible that the STOP condition is still being generated
342+
// when we reach here, so we wait until it finishes before proceeding
343+
// to start a new transaction.
334344
while self.i2c.cr1.read().stop().bit_is_set() {}
335345

336346
// Send a START condition and set ACK bit
@@ -449,6 +459,13 @@ impl<I2C: Instance> I2c<I2C> {
449459
// Receive last byte
450460
*last = self.recv_byte()?;
451461

462+
// Wait for the STOP to be sent. Otherwise, the interface will still be
463+
// busy for a while after this function returns. Immediate following
464+
// operations through the DMA handle might thus encounter `WouldBlock`
465+
// error. Instead, we should make sure that the interface becomes idle
466+
// before returning.
467+
while self.i2c.cr1.read().stop().bit_is_set() {}
468+
452469
// Fallthrough is success
453470
Ok(())
454471
} else {
@@ -468,6 +485,13 @@ impl<I2C: Instance> I2c<I2C> {
468485
// Send a STOP condition
469486
self.i2c.cr1.modify(|_, w| w.stop().set_bit());
470487

488+
// Wait for the STOP to be sent. Otherwise, the interface will still be
489+
// busy for a while after this function returns. Immediate following
490+
// operations through the DMA handle might thus encounter `WouldBlock`
491+
// error. Instead, we should make sure that the interface becomes idle
492+
// before returning.
493+
while self.i2c.cr1.read().stop().bit_is_set() {}
494+
471495
// Fallthrough is success
472496
Ok(())
473497
}
@@ -482,6 +506,13 @@ impl<I2C: Instance> I2c<I2C> {
482506
// Send a STOP condition
483507
self.i2c.cr1.modify(|_, w| w.stop().set_bit());
484508

509+
// Wait for the STOP to be sent. Otherwise, the interface will still be
510+
// busy for a while after this function returns. Immediate following
511+
// operations through the DMA handle might thus encounter `WouldBlock`
512+
// error. Instead, we should make sure that the interface becomes idle
513+
// before returning.
514+
while self.i2c.cr1.read().stop().bit_is_set() {}
515+
485516
// Fallthrough is success
486517
Ok(())
487518
}

0 commit comments

Comments
 (0)