Skip to content

nrf: Fix I2C regression introduced by nrfx v3 update.#19220

Open
andrewleech wants to merge 1 commit into
micropython:masterfrom
andrewleech:nrf-i2c-fix
Open

nrf: Fix I2C regression introduced by nrfx v3 update.#19220
andrewleech wants to merge 1 commit into
micropython:masterfrom
andrewleech:nrf-i2c-fix

Conversation

@andrewleech
Copy link
Copy Markdown
Contributor

@andrewleech andrewleech commented May 14, 2026

Summary

Fixes a regression introduced in #19125 where I2C stopped working on nRF52840 when SPI is also enabled (issue #19214).

The root cause is an IRQ handler symbol conflict in nrfx v3: both nrfx_prs_box_0_irq_handler (PRS dispatcher) and nrfx_twim_0_irq_handler map to the same final symbol SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler via the nrfx irq alias headers. With LTO enabled, the PRS dispatcher wins and the TWIM event handler is never called, so I2C transfers stall indefinitely waiting for a xfer_done flag that never gets set.

The fix is to use nrfx blocking mode (NULL event handler) where nrfy_twim_tx_start polls the STOPPED/SUSPENDED peripheral register directly without relying on the NVIC interrupt. This is appropriate for MicroPython's synchronous machine.I2C API.

Also fixes the NOSTOP flag: the old code passed (flags & MP_MACHINE_I2C_FLAG_STOP) == 0 as the xfer flags argument, which evaluates to 0 or 1. The value 1 is NRFX_TWIM_FLAG_TX_POSTINC in nrfx v3, not the no-stop flag. Now uses NRFX_TWIM_FLAG_TX_NO_STOP explicitly.

Testing

Tested that the nRF52840 port builds. Hardware testing not done - the regression is reported by users in #19214.

Generative AI

I used generative AI tools when creating this PR, but a human has checked the code and is responsible for the code and the description above.

In nrfx v3, when both SPIM0 and TWIM0 are enabled (PRS_BOX_0_ENABLED),
nrfx_prs.c and nrfx_twim.c emit the same IRQ handler symbol via macro
aliasing in nrfx_irqs_nrf52840.h. LTO resolves this to the PRS dispatcher,
which never reaches twi_event_handler, causing I2C to stall indefinitely.

Fix by switching to blocking mode (NULL handler), where nrfy_twim_tx_start
polls the STOPPED/SUSPENDED event internally without IRQ dependency.

Also fix the NOSTOP flag: the old code passed (flags & FLAG_STOP) == 0,
evaluating to 0 or 1. In nrfx v3 TWIM, flag 1 is NRFX_TWIM_FLAG_TX_POSTINC
(buffer post-increment), not no-stop. The correct flag is
NRFX_TWIM_FLAG_TX_NO_STOP (1 << 5).

Fixes: micropython#19214

Signed-off-by: Andrew Leech <andrew@alelec.net>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
@ricksorensen
Copy link
Copy Markdown
Contributor

I can confirm I2C works with this update on my XIAO nrf52840 with expansion board. Both I2C(1) - the intermal IMU bus and I2C(0) work.
I have not yet checked with SPI.

@robert-hh
Copy link
Copy Markdown
Contributor

robert-hh commented May 15, 2026

Tested with a Arduino Nano 33 BLE. I2C works. No SPI connected or enabled, besides the internal Flash of the UBLOX module. But I do not see if and where the supplied value for timeout is applied.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants