cpu/esp32: fix errno for I2C addr ack error

fixup! cpu/esp32: fix errno for I2C addr ack error
This commit is contained in:
Gunar Schorcht 2019-09-05 10:34:48 +02:00
parent 8c8306e1ca
commit cb8b1b12c1
2 changed files with 61 additions and 16 deletions

View File

@ -288,23 +288,68 @@ int i2c_release(i2c_t dev)
return 0;
}
#define _i2c_return_on_error(dev) \
/*
* This macro checks the result of a read transfer. In case of an error,
* the hardware is reset and returned with a corresponding error code.
*
* @note:
* In a read transfer, an ACK is only expected for the address field. Thus,
* an ACK error can only happen for the address field. Therefore, we always
* return -ENXIO in case of an ACK error.
*/
#define _i2c_return_on_error_read(dev) \
if (_i2c_bus[dev].results & I2C_ARBITRATION_LOST_INT_ENA) { \
LOG_TAG_ERROR("i2c", "arbitration lost dev=%u\n", dev); \
LOG_TAG_DEBUG("i2c", "arbitration lost dev=%u\n", dev); \
_i2c_reset_hw (dev); \
__asm__ volatile ("isync"); \
__asm__ volatile ("isync"); \
return -EAGAIN; \
} \
else if (_i2c_bus[dev].results & I2C_ACK_ERR_INT_ENA) { \
LOG_TAG_ERROR("i2c", "ack error dev=%u\n", dev); \
LOG_TAG_DEBUG("i2c", "ack error dev=%u\n", dev); \
_i2c_reset_hw (dev); \
__asm__ volatile ("isync"); \
return -EIO; \
__asm__ volatile ("isync"); \
return -ENXIO; \
} \
else if (_i2c_bus[dev].results & I2C_TIME_OUT_INT_ENA) { \
LOG_TAG_ERROR("i2c", "bus timeout dev=%u\n", dev); \
LOG_TAG_DEBUG("i2c", "bus timeout dev=%u\n", dev); \
_i2c_reset_hw (dev); \
__asm__ volatile ("isync"); \
__asm__ volatile ("isync"); \
return -ETIMEDOUT; \
}
/*
* This macro checks the result of a write transfer. In case of an error,
* the hardware is reset and returned with a corresponding error code.
*
* @note:
* In a write transfer, an ACK error can happen for the address field
* as well as for data. If the FIFO still contains all data bytes,
* (i.e. _i2c_hw[dev].regs->status_reg.tx_fifo_cnt >= len), the ACK error
* happened in address field and we have to returen -ENXIO. Otherwise, the
* ACK error happened in data field and we have to return -EIO.
*/
#define _i2c_return_on_error_write(dev) \
if (_i2c_bus[dev].results & I2C_ARBITRATION_LOST_INT_ENA) { \
LOG_TAG_DEBUG("i2c", "arbitration lost dev=%u\n", dev); \
_i2c_reset_hw (dev); \
__asm__ volatile ("isync"); \
return -EAGAIN; \
} \
else if (_i2c_bus[dev].results & I2C_ACK_ERR_INT_ENA) { \
LOG_TAG_DEBUG("i2c", "ack error dev=%u\n", dev); \
_i2c_reset_hw (dev); \
__asm__ volatile ("isync"); \
if (_i2c_hw[dev].regs->status_reg.tx_fifo_cnt >= len) { \
return -ENXIO; \
} \
else { \
return -EIO; \
} \
} \
else if (_i2c_bus[dev].results & I2C_TIME_OUT_INT_ENA) { \
LOG_TAG_DEBUG("i2c", "bus timeout dev=%u\n", dev); \
_i2c_reset_hw (dev); \
__asm__ volatile ("isync"); \
return -ETIMEDOUT; \
}
@ -350,7 +395,7 @@ int i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t fla
_i2c_read_cmd (dev, data, I2C_MAX_DATA, false);
_i2c_end_cmd (dev);
_i2c_transfer (dev);
_i2c_return_on_error (dev);
_i2c_return_on_error_read (dev);
/* if transfer was successful, fetch the data from I2C RAM */
for (unsigned i = 0; i < I2C_MAX_DATA; i++) {
@ -380,7 +425,7 @@ int i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t fla
/* finish operation by executing the command pipeline */
_i2c_transfer (dev);
_i2c_return_on_error (dev);
_i2c_return_on_error_read (dev);
/* if transfer was successful, fetch data from I2C RAM */
for (unsigned i = 0; i < len; i++) {
@ -437,7 +482,7 @@ int i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_t len, uint
_i2c_write_cmd (dev, ((uint8_t*)data) + off, I2C_MAX_DATA);
_i2c_end_cmd (dev);
_i2c_transfer (dev);
_i2c_return_on_error (dev);
_i2c_return_on_error_write (dev);
len -= I2C_MAX_DATA;
off += I2C_MAX_DATA;
@ -458,7 +503,7 @@ int i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_t len, uint
/* finish operation by executing the command pipeline */
_i2c_transfer (dev);
_i2c_return_on_error (dev);
_i2c_return_on_error_write (dev);
/* return 0 on success */
return 0;

View File

@ -225,7 +225,7 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len,
(res = _i2c_write_byte (bus, addr2)) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res;
return -ENXIO;
}
}
else {
@ -233,7 +233,7 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len,
if ((res = _i2c_write_byte (bus, (addr << 1 | I2C_READ))) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res;
return -ENXIO;
}
}
}
@ -286,7 +286,7 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_
(res = _i2c_write_byte (bus, addr2)) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res;
return -ENXIO;
}
}
else {
@ -294,7 +294,7 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_
if ((res = _i2c_write_byte (bus, addr << 1)) != 0) {
/* abort transfer */
_i2c_abort (bus, __func__);
return res;
return -ENXIO;
}
}
}