Description
When a reset occurs during a I2C transmission of a slave to the ESP8266 the SDA might hang.
This situation is known and described e.g. in the AN10216 publication on page17 / slide 42 .
[Uploading AN10216.pdf…] In my case it's the DS1307 realtime clock providing the error situation.
The described procedure in AN10216 (clocking 8 times for remaining incoming bits, then sending a NACK and a STOP) makes the slave release the SDA line.
I have done this by a simple program (see underneath) but a subsequent inline restart of Wire with various variants (with/without STOP, with/without pins) didn't help me so far. On an oscilloscope both lines remained high.
After this code:
- A restart of the program bij reset line is successful
- An ESP.reset(), ESP.restart() or system_restart()
are not successful.
So a software reset left the SDA and CLK lines high but the communication on the I2C didn't start.
To complement the above: the I2C communication works fine, as well as the called I2C_scan. It is only after a reset that SDA might hang low and that I can't recover fully from an SDA line stuck low by software. I get the line high again but cannot get I2C working again without pulling the reset line low.
Hence I would appreciate any hint in getting this resolved inline.
Maybe the recovery could also be added to the library?
Thanks in advance for any support.
Code entered when hanging I2C is found:
Serial.println("Starting I2C bus recovery");
delay(2000);
//try i2c bus recovery at 100kHz = 5uS high, 5uS low
pinMode(SDAPIN, OUTPUT);//keeping SDA high during recovery
digitalWrite(SDAPIN, HIGH);
pinMode(CLKPIN, OUTPUT);
for (int i = 0; i < 10; i++) { //9nth cycle acts as NACK
digitalWrite(CLKPIN, HIGH);
delayMicroseconds(5);
digitalWrite(CLKPIN, LOW);
delayMicroseconds(5);
}
//a STOP signal (SDA from low to high while CLK is high)
digitalWrite(SDAPIN, LOW);
delayMicroseconds(5);
digitalWrite(CLKPIN, HIGH);
delayMicroseconds(2);
digitalWrite(SDAPIN, HIGH);
delayMicroseconds(2);
//bus status is now : FREE
Serial.println("bus recovery done, starting scan in 2 secs");
//return to power up mode
pinMode(SDAPIN, INPUT);
pinMode(CLKPIN, INPUT);
delay(2000);
//pins + begin advised in https://github.com/esp8266/Arduino/issues/452
Wire.pins(SDAPIN, CLKPIN); //this changes default values for sda and clock as well
Wire.begin(SDAPIN, CLKPIN);
//only pins: no signal on clk and sda
//only begin: no signal on clk, no signal on sda
//no further processing in case of error
while(true)
{
i2c_scan();
}
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.