Skip to content

Commit 099f3a4

Browse files
committed
I2C bus reset with info to user
I2C slave might stil have something to send when ESP826 starts I2C, thus keeping the bus stuck. Happens e.g. when power failure/reset during transmission. Thanks to work of drmpf there is a solution. Implemented as separate method so as not to interfere with existing. Usage: Wire.begin(); if (Wire.status() != I2C_OK) Serial.writeln("Something wrong with I2C bus that cannot be recovered. Perform power cycle or search for other masters on bus.";
1 parent 5313c56 commit 099f3a4

File tree

4 files changed

+27
-0
lines changed

4 files changed

+27
-0
lines changed

cores/esp8266/core_esp8266_si2c.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,18 @@ unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned i
197197
}
198198
return 0;
199199
}
200+
201+
uint8_t twi_status(){
202+
if (SCL_READ()==0) return I2C_SCL_HELD_LOW; //SCL held low by another device, no procedure available to recover
203+
int clockCount = 20;
204+
205+
while (SDA_READ()==0 && clockCount>0){ //if SDA low, read the bits slaves have to sent to a max
206+
twi_read_bit();
207+
if (SCL_READ()==0) return I2C_SCL_HELD_LOW_AFTER_READ; //I2C bus error. SCL held low beyond slave clock stretch time
208+
}
209+
210+
if (SDA_READ()==0) return I2C_SDA_HELD_LOW; //I2C bus error. SDA line held low by slave/another_master after n bits.
211+
212+
if(!twi_write_start()) return I2C_SDA_HELD_LOW_AFTER_INIT; //line busy. SDA again held low by another device. 2nd master?
213+
else return I2C_OK; //all ok
214+
}

cores/esp8266/twi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,19 @@
2626
extern "C" {
2727
#endif
2828

29+
#define I2C_OK 0
30+
#define I2C_SCL_HELD_LOW 1
31+
#define I2C_SCL_HELD_LOW_AFTER_READ 2
32+
#define I2C_SDA_HELD_LOW 3
33+
#define I2C_SDA_HELD_LOW_AFTER_INIT 4
34+
2935
void twi_init(unsigned char sda, unsigned char scl);
3036
void twi_stop(void);
3137
void twi_setClock(unsigned int freq);
3238
void twi_setClockStretchLimit(uint32_t limit);
3339
uint8_t twi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop);
3440
uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop);
41+
uint8_t twi_status();
3542

3643
#ifdef __cplusplus
3744
}

libraries/Wire/Wire.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ void TwoWire::begin(uint8_t address){
7777
begin();
7878
}
7979

80+
uint8_t TwoWire::status(){
81+
return twi_status();
82+
}
83+
8084
void TwoWire::begin(int address){
8185
begin((uint8_t)address);
8286
}

libraries/Wire/Wire.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class TwoWire : public Stream
6262
uint8_t endTransmission(void);
6363
uint8_t endTransmission(uint8_t);
6464
size_t requestFrom(uint8_t address, size_t size, bool sendStop);
65+
uint8_t status();
6566

6667
uint8_t requestFrom(uint8_t, uint8_t);
6768
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);

0 commit comments

Comments
 (0)