Skip to content

Commit 9c1d941

Browse files
committed
Fix PIO I2C race condition
1 parent 84e8d48 commit 9c1d941

File tree

2 files changed

+9
-0
lines changed

2 files changed

+9
-0
lines changed

pio/i2c/i2c.pio

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ do_nack:
4848

4949
do_byte:
5050
set x, 7 ; Loop 8 times
51+
mov isr, null ; Set ISR and input shift counter to zero. This
52+
; helps fix a race condition when autopush is
53+
; disabled and re-enabled, which can leave the
54+
; counter in an inconsistent state.
5155
bitloop:
5256
out pindirs, 1 [7] ; Serialise write data (all-ones if reading)
5357
nop side 1 [2] ; SCL rising edge

pio/i2c/pio_i2c.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ void pio_i2c_resume_after_error(PIO pio, uint sm) {
2222
pio_interrupt_clear(pio, sm);
2323
}
2424

25+
// Disable autopush of read I2C bytes, which is useful when only writing to
26+
// the I2C bus and we don't want to bother with cleaning the RX FIFO. But be
27+
// careful because this isn't synchronized to the state machine program and in
28+
// a race condition can leave its input shift counter in an unexpected state,
29+
// shifting any subsequently read bytes by an unexpected number of bits.
2530
void pio_i2c_rx_enable(PIO pio, uint sm, bool en) {
2631
if (en)
2732
hw_set_bits(&pio->sm[sm].shiftctrl, PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS);

0 commit comments

Comments
 (0)