Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix PIO I2C race condition #617

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pio/i2c/i2c.pio
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ do_nack:

do_byte:
set x, 7 ; Loop 8 times
mov isr, null ; Set ISR and input shift counter to zero. This
; helps fix a race condition when autopush is
; disabled and re-enabled, which can leave the
; counter in an inconsistent state.
bitloop:
out pindirs, 1 [7] ; Serialise write data (all-ones if reading)
nop side 1 [2] ; SCL rising edge
Expand Down
5 changes: 5 additions & 0 deletions pio/i2c/pio_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ void pio_i2c_resume_after_error(PIO pio, uint sm) {
pio_interrupt_clear(pio, sm);
}

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