-
Notifications
You must be signed in to change notification settings - Fork 494
Description
This is a continuation of this issue:
Intermittent i2c errors, byte count incorrect and missing bytes in onReceive interrupt handler
#979
I noticed that the changes to Wire.cpp introduced to make improvements to the above issue (I2C slave receiving data) seem to have broken the ability of a Pico in I2C slave mode to respond to I2C requests.
The changes made have improved the error rate for receiving data, which according to my tests dropped down to around 0.027% at 1MHz I2C clock, however the I2C "Repeated Start Condition" now does not seem to work properly.
I have tested Wire.cpp from the last commit before the recent changes (June) and this issue does not exist, just the original data reception issue.
I have only recently noticed this when I created a new test harness which sends data both ways between 2 Pico's, previously the slave Pico was only receiving data, not responding to any I2C requests.
The new test harness projects have been added to the original test harness repo:
https://github.com/chrisckc/TestHarness-I2C/tree/master/I2C_receiver-new
https://github.com/chrisckc/TestHarness-I2C/tree/master/I2c_sender-new
These are based on sending a 255 byte buffer of sequential bytes back and forth between the 2 Pico's
The issue responding to I2C requests is due to this section of the onIRQ() function inside Wire.cpp:
// RESTART_DET
if (irqstat & (1 << 12)) {
if (_onReceiveCallback && _buffLen) {
_onReceiveCallback(_buffLen);
}
_i2c->hw->clr_restart_det;
}
To fix the issue, the above section needs to be changed to this to allow the "Repeated Start Condition" to be handled correctly, as in the original code. The "Repeated Start Condition" is used by the master when making I2C requests to prevent other devices from grabbing the bus between the transfer of the read command from the master to the slave and its response to the master.
// RESTART_DET
if (irqstat & (1 << 12)) {
if (_onReceiveCallback && _buffLen) {
_onReceiveCallback(_buffLen);
}
_buffLen = 0;
_buffOff = 0;
_slaveStartDet = false;
_i2c->hw->clr_restart_det;
}