Skip to content

Commit cd583d1

Browse files
committed
Prevent starting a new I2C transaction before previous stop finishes.
When a stop condition is generated by the I2C DMA callback, the code does not wait for the finish of the stop condition. If while the stop condition is being generated and a new I2C transaction attempts to start, the new transaction will be inadvertently terminated by the previous stop condition. Since ISRs should finish as quickly as possible, the ISRs should not spin-wait until the stop condition finishes. Instead, the spin-wait should be placed before starting a new transaction. The patch also removes incorrect comments that falsely indicate that the code will spin-wait until the stop condition finishes.
1 parent 5337975 commit cd583d1

File tree

2 files changed

+8
-13
lines changed

2 files changed

+8
-13
lines changed

src/i2c.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ 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
289+
while self.i2c.cr1.read().stop().bit_is_set() {}
290+
288291
// Send a START condition
289292
self.i2c.cr1.modify(|_, w| w.start().set_bit());
290293

@@ -327,6 +330,9 @@ impl<I2C: Instance> I2c<I2C> {
327330

328331
/// Sends START and Address for reading
329332
fn prepare_read(&self, addr: u8) -> Result<(), Error> {
333+
// Wait until a previous STOP condition finishes
334+
while self.i2c.cr1.read().stop().bit_is_set() {}
335+
330336
// Send a START condition and set ACK bit
331337
self.i2c
332338
.cr1
@@ -443,9 +449,6 @@ impl<I2C: Instance> I2c<I2C> {
443449
// Receive last byte
444450
*last = self.recv_byte()?;
445451

446-
// Wait for the STOP to be sent.
447-
while self.i2c.cr1.read().stop().bit_is_set() {}
448-
449452
// Fallthrough is success
450453
Ok(())
451454
} else {
@@ -465,9 +468,6 @@ impl<I2C: Instance> I2c<I2C> {
465468
// Send a STOP condition
466469
self.i2c.cr1.modify(|_, w| w.stop().set_bit());
467470

468-
// Wait for STOP condition to transmit.
469-
while self.i2c.cr1.read().stop().bit_is_set() {}
470-
471471
// Fallthrough is success
472472
Ok(())
473473
}
@@ -482,9 +482,6 @@ impl<I2C: Instance> I2c<I2C> {
482482
// Send a STOP condition
483483
self.i2c.cr1.modify(|_, w| w.stop().set_bit());
484484

485-
// Wait for STOP condition to transmit.
486-
while self.i2c.cr1.read().stop().bit_is_set() {}
487-
488485
// Fallthrough is success
489486
Ok(())
490487
}

src/i2c/dma.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,6 @@ where
628628
// Wait for BTF
629629
while self.hal_i2c.i2c.sr1.read().btf().bit_is_clear() {}
630630

631-
// Generate stop and wait for it
632631
self.send_stop();
633632
}
634633
}
@@ -668,7 +667,7 @@ where
668667

669668
// Clear ACK
670669
self.hal_i2c.i2c.cr1.modify(|_, w| w.ack().clear_bit());
671-
// Generate stop and wait for it
670+
672671
self.send_stop();
673672
}
674673
}
@@ -730,7 +729,6 @@ where
730729

731730
self.rx.rx_transfer.as_mut().unwrap().start(|_| {});
732731
} else {
733-
// Generate stop and wait for it
734732
self.send_stop();
735733
}
736734
}
@@ -756,7 +754,7 @@ where
756754

757755
// Clear ACK
758756
self.hal_i2c.i2c.cr1.modify(|_, w| w.ack().clear_bit());
759-
// Generate stop and wait for it
757+
760758
self.send_stop();
761759
}
762760
}

0 commit comments

Comments
 (0)