Skip to content
Snippets Groups Projects
Unverified Commit df7468a2 authored by Kevin Weiss's avatar Kevin Weiss Committed by GitHub
Browse files

Merge pull request #10017 from gschorcht/esp8266_i2c_fix

cpu/esp8266: periph/i2c fix
parents 22e03180 6307ace1
No related branches found
No related tags found
No related merge requests found
...@@ -53,8 +53,8 @@ ...@@ -53,8 +53,8 @@
extern uint8_t system_get_cpu_freq(void); extern uint8_t system_get_cpu_freq(void);
extern bool system_update_cpu_freq(uint8_t freq); extern bool system_update_cpu_freq(uint8_t freq);
/* max clock stretching counter */ /* max clock stretching counter (ca. 10 ms) */
#define I2C_CLOCK_STRETCH 400 #define I2C_CLOCK_STRETCH 40000
typedef struct typedef struct
{ {
...@@ -128,9 +128,9 @@ static int _i2c_read_bit (_i2c_bus_t* bus, bool* bit); ...@@ -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_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_read_byte (_i2c_bus_t* bus, uint8_t* byte, bool ack);
static int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func); 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 */ /* implementation of i2c interface */
void i2c_init(i2c_t dev) void i2c_init(i2c_t dev)
{ {
if (I2C_NUMOF != sizeof(_i2c_bus)/sizeof(_i2c_bus_t)) { 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, ...@@ -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 */ /* send address bytes wit read flag */
if ((res = _i2c_write_byte (bus, addr1)) != 0 || if ((res = _i2c_write_byte (bus, addr1)) != 0 ||
(res = _i2c_write_byte (bus, addr2)) != 0) { (res = _i2c_write_byte (bus, addr2)) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res; return res;
} }
} }
else { else {
/* send address byte with read flag */ /* send address byte with read flag */
if ((res = _i2c_write_byte (bus, (addr << 1 | I2C_READ))) != 0) { if ((res = _i2c_write_byte (bus, (addr << 1 | I2C_READ))) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res; return res;
} }
} }
...@@ -231,7 +235,9 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, ...@@ -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 */ /* receive bytes if send address was successful */
for (unsigned int i = 0; i < len; i++) { for (unsigned int i = 0; i < len; i++) {
if ((res = _i2c_read_byte (bus, &(((uint8_t*)data)[i]), i < len-1)) != 0) { 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_ ...@@ -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 */ /* send address bytes without read flag */
if ((res = _i2c_write_byte (bus, addr1)) != 0 || if ((res = _i2c_write_byte (bus, addr1)) != 0 ||
(res = _i2c_write_byte (bus, addr2)) != 0) { (res = _i2c_write_byte (bus, addr2)) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res; return res;
} }
} }
else { else {
/* send address byte without read flag */ /* send address byte without read flag */
if ((res = _i2c_write_byte (bus, addr << 1)) != 0) { if ((res = _i2c_write_byte (bus, addr << 1)) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res; return res;
} }
} }
...@@ -286,7 +296,9 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_ ...@@ -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 */ /* send bytes if send address was successful */
for (unsigned int i = 0; i < len; i++) { for (unsigned int i = 0; i < len; i++) {
if ((res = _i2c_write_byte (bus, ((uint8_t*)data)[i])) != 0) { 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) ...@@ -372,6 +384,18 @@ static inline void _i2c_clear_sda(_i2c_bus_t* bus)
GPIO.OUT_CLEAR = bus->sda_bit; 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) static /* IRAM */ int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func)
{ {
DEBUG("%s: arbitration lost dev=%u\n", func, bus->dev); DEBUG("%s: arbitration lost dev=%u\n", func, bus->dev);
...@@ -471,7 +495,7 @@ static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus) ...@@ -471,7 +495,7 @@ static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus)
res = -ETIMEDOUT; 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. */ /* min. in us: 4.0 (SM), 0.6 (FM), 0.26 (FPM), 0.16 (HSM); no max. */
_i2c_delay (bus); _i2c_delay (bus);
...@@ -484,6 +508,8 @@ static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* 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 */ /* 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. */ /* min. in us: 4.7 (SM), 1.3 (FM), 0.5 (FPM), 0.16 (HSM); no max. */
_i2c_delay (bus); _i2c_delay (bus);
/* one additional delay */
_i2c_delay (bus);
/* if SDA is low, arbitration is lost and someone else is driving the bus */ /* if SDA is low, arbitration is lost and someone else is driving the bus */
if (_i2c_read_sda (bus) == 0) { if (_i2c_read_sda (bus) == 0) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment