-
Couldn't load subscription status.
- Fork 1.3k
Description
If an nRF I2C (TWIM) peripheral is connected to pullups that are not pulled up, and then connected to an unpowered device, the peripheral can be initialized, but then operations on the bus may hang.
First noted on Arduino Nano 33 BLE. It has an on-board accelerometer. The I2C pullups and the device are both powered from other pins, so they can be shut off when not in use. If the pullups and the device are unpowered, we can still create a busio.I2C(), because it passes the tests that try to detect whether pullups are connected, but then trying to read from the device will hang CircuitPython.
This can be simulated on a Feather nRF52840 by putting a 10K resistor between SCL and SDA and then connecting an unpowered device (I used an LIS3DH) to SCL and SDA. EDIT in 2024: I could not get that to work, but a simpler way is to start using a powered LIS3DH device and then disconnect the power.
Trying to readfrom_into() hangs the code in a busy-wait loop:
while (!nrf_twim_event_check(p_twim, evt_to_wait))
Some possible solutions are:
- Improve how to check for proper pullups: maybe try using internal pullups and pulldowns. This doesn't solve the problem of losing pullup power later, for instance.
- Add a timeout of some kind to
nrf_twim_event_check(), directly, or as a background task.
What might be a good timeout (several seconds??), and should it be specifiable in the I2C constructor?
We are using the synchronous TWIM driver, but going to the async driver would not help, I think, because the IRQ handler is not going to get called. So we still need to implement a timeout mechanism. The current Arduino BSP for nRF52 uses the async driver, but it still busy waits and I think it may have the same problem.
Need to decide how much effort to expend to fix this vs. just documenting it.
Tagging @ladyada who discovered this issue.