diff --git a/cpu/esp8266/periph/i2c.c b/cpu/esp8266/periph/i2c.c index bdcff8212446e2631df3eda8daff70ec2e9c2704..d490d420543b0b7d9cb4018478548c1c94bb582f 100644 --- a/cpu/esp8266/periph/i2c.c +++ b/cpu/esp8266/periph/i2c.c @@ -53,8 +53,8 @@ extern uint8_t system_get_cpu_freq(void); extern bool system_update_cpu_freq(uint8_t freq); -/* max clock stretching counter */ -#define I2C_CLOCK_STRETCH 400 +/* max clock stretching counter (ca. 10 ms) */ +#define I2C_CLOCK_STRETCH 40000 typedef struct { @@ -128,9 +128,9 @@ static int _i2c_read_bit (_i2c_bus_t* bus, bool* bit); static int _i2c_write_byte (_i2c_bus_t* bus, uint8_t byte); static int _i2c_read_byte (_i2c_bus_t* bus, uint8_t* byte, bool ack); static int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func); +static void _i2c_abort (_i2c_bus_t* bus, const char* func); /* implementation of i2c interface */ - void i2c_init(i2c_t dev) { if (I2C_NUMOF != sizeof(_i2c_bus)/sizeof(_i2c_bus_t)) { @@ -217,12 +217,16 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, /* send address bytes wit read flag */ if ((res = _i2c_write_byte (bus, addr1)) != 0 || (res = _i2c_write_byte (bus, addr2)) != 0) { + /* abort transfer */ + _i2c_abort (bus, __func__); return res; } } else { /* send address byte with read flag */ if ((res = _i2c_write_byte (bus, (addr << 1 | I2C_READ))) != 0) { + /* abort transfer */ + _i2c_abort (bus, __func__); return res; } } @@ -231,7 +235,9 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, /* receive bytes if send address was successful */ for (unsigned int i = 0; i < len; i++) { if ((res = _i2c_read_byte (bus, &(((uint8_t*)data)[i]), i < len-1)) != 0) { - break; + /* abort transfer */ + _i2c_abort (bus, __func__); + return res; } } @@ -272,12 +278,16 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_ /* send address bytes without read flag */ if ((res = _i2c_write_byte (bus, addr1)) != 0 || (res = _i2c_write_byte (bus, addr2)) != 0) { + /* abort transfer */ + _i2c_abort (bus, __func__); return res; } } else { /* send address byte without read flag */ if ((res = _i2c_write_byte (bus, addr << 1)) != 0) { + /* abort transfer */ + _i2c_abort (bus, __func__); return res; } } @@ -286,7 +296,9 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_ /* send bytes if send address was successful */ for (unsigned int i = 0; i < len; i++) { if ((res = _i2c_write_byte (bus, ((uint8_t*)data)[i])) != 0) { - break; + /* abort transfer */ + _i2c_abort (bus, __func__); + return res; } } @@ -372,6 +384,18 @@ static inline void _i2c_clear_sda(_i2c_bus_t* bus) GPIO.OUT_CLEAR = bus->sda_bit; } +static void _i2c_abort(_i2c_bus_t* bus, const char* func) +{ + DEBUG("%s: dev=%u\n", func, bus->dev); + + /* reset SCL and SDA to passive HIGH (floating and pulled-up) */ + _i2c_set_sda (bus); + _i2c_set_scl (bus); + + /* reset repeated start indicator */ + bus->started = false; +} + static /* IRAM */ int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func) { DEBUG("%s: arbitration lost dev=%u\n", func, bus->dev); @@ -471,7 +495,7 @@ static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus) res = -ETIMEDOUT; } - /* wait t_SU;STO - hold time (repeated) START condition, */ + /* wait t_SU;STO - hold time STOP condition, */ /* min. in us: 4.0 (SM), 0.6 (FM), 0.26 (FPM), 0.16 (HSM); no max. */ _i2c_delay (bus); @@ -484,6 +508,8 @@ static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus) /* wait t_BUF - bus free time between a STOP and a START condition */ /* min. in us: 4.7 (SM), 1.3 (FM), 0.5 (FPM), 0.16 (HSM); no max. */ _i2c_delay (bus); + /* one additional delay */ + _i2c_delay (bus); /* if SDA is low, arbitration is lost and someone else is driving the bus */ if (_i2c_read_sda (bus) == 0) {