-
Notifications
You must be signed in to change notification settings - Fork 2k
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
cpu/nrf5x i2c: Set up correct interrupts after NOSTOP transmissions #20282
Conversation
Why not just always wait on all three success IRQs? Or do you suspect spurious IRQs? If the finish would be the same code in the stop case, the nostop+RX, and the nostop+TX case a bit of ROM is likely to be safed. |
I suspect (but didn't test) that the LASTTX would fire a bit before STOPPED and thus we need precision. Unifying last TX and RX sounds viable -- will need to test what's smaller.
|
Hm, this might be introducing a race condition: Researching whether doing LASTTX | LASTRX unconditionally might be viable, I found around https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Ftwim.html figure 5 that "The TWI master will generate a LASTRX event when it is ready to receive the last byte" (i.e., when it is signalled it hasn't been read yet). From more docs reading I think that the correct thing to do is to set a LASTTX -> SUSPEND shortcut when our application requests NOSTOP, and then to unblock the device on SUSPENDED. As I don't expect rogue interrupts, we can once more wait for anything (ERROR | STOPPED | SUSPENDED), and just need to set some shortcut unconditionally. |
After lengthy discussion I summarize that it's a low quality I2C implementation -- discussion on Matrix (linked in the commit) confirms that multiple chained operations of the same kind (read or write) can not be done without sending a ST(art), and while not sending a S(to)P is supported in theory, there is no good interrupt that can be caught after the read has completed. But it'd be of little use anyway as no continued read can be performed. (It might be used in a write-read-write pattern, but that's uncommon). I've thus abandoned the announced SUSPEND route (those shortcuts are not available consistently across the nRF5x devices, and I don't think any more that they'd have done the desired thing in the first place), stuck with the original patch and forbade the race condition by making read requests with I2C_NOSTOP fail with an error. (Before this PR, those would stall the thread, so it's still a compatible change). I've tested this by running the GPIO/I2C tests on the nrf52dk and the RIOT Peripheral Selftest Shield v0.3 (thanks maribu!) with a pinout that'll follow in a separate PR. |
Contribution description
On nrf5x chips (tested on nrf52840), I2C_NOSTOP is not implemented correctly: It sets up the interrupts for the ERROR and STOPPED events, but the STOPPED condition is only reached when the "short" (nRF5x ling for triggering actions after state transitions) LASTTX_STOP causes the STOP condition to be set after the last transmission (eventually winding up in STOPPED). But when setting I2C_NOSTOP, the only interrupt that triggers is LASTTX, and that is not enabled.
Testing procedure
In the periph_i2c test (with DEBUG enabled for full output, but you'll see the hang anyway):
After that, the program hangs; with this patch, it reports
I've tested this with a microbit-v2, which has an accelerometer/magnetometer at address 30.
Issues/PRs references
Found this while implementing Rust embedded-hal 1.0, which is strict about not sending stop conditions, and also allows scatter-gather I2C that is implemented with I2C_NOSTART.