diff --git a/drivers/include/periph/i2c.h b/drivers/include/periph/i2c.h index 939884bc60..3cc3b58573 100644 --- a/drivers/include/periph/i2c.h +++ b/drivers/include/periph/i2c.h @@ -195,7 +195,7 @@ typedef enum { #ifndef HAVE_I2C_FLAGS_T typedef enum { I2C_ADDR10 = 0x01, /**< use 10-bit device addressing */ - I2C_REG16 = 0x02, /**< use 16-bit register addressing */ + I2C_REG16 = 0x02, /**< use 16-bit register addressing, big-endian */ I2C_NOSTOP = 0x04, /**< do not issue a STOP condition after transfer */ I2C_NOSTART = 0x08, /**< skip START sequence, ignores address field */ } i2c_flags_t; diff --git a/drivers/periph_common/i2c.c b/drivers/periph_common/i2c.c index f6e3ad0b00..a24fd4560c 100644 --- a/drivers/periph_common/i2c.c +++ b/drivers/periph_common/i2c.c @@ -22,6 +22,7 @@ #include "board.h" #include "cpu.h" #include "periph/i2c.h" +#include "byteorder.h" #ifdef I2C_NUMOF @@ -37,11 +38,19 @@ int i2c_read_reg(i2c_t dev, uint16_t addr, uint16_t reg, int i2c_read_regs(i2c_t dev, uint16_t addr, uint16_t reg, void *data, size_t len, uint8_t flags) { + uint16_t reg_end = reg; + if (flags & (I2C_NOSTOP | I2C_NOSTART)) { return -EOPNOTSUPP; } + + /* Handle endianess of register if 16 bit */ + if (flags & I2C_REG16) { + reg_end = htons(reg); /* Make sure register is in big-endian on I2C bus */ + } + /* First set ADDR and register with no stop */ - int ret = i2c_write_bytes(dev, addr, ®, (flags & I2C_REG16) ? 2 : 1, + int ret = i2c_write_bytes(dev, addr, ®_end, (flags & I2C_REG16) ? 2 : 1, flags | I2C_NOSTOP); if (ret < 0) { return ret; @@ -73,11 +82,19 @@ int i2c_write_reg(i2c_t dev, uint16_t addr, uint16_t reg, int i2c_write_regs(i2c_t dev, uint16_t addr, uint16_t reg, const void *data, size_t len, uint8_t flags) { + uint16_t reg_end = reg; + if (flags & (I2C_NOSTOP | I2C_NOSTART)) { return -EOPNOTSUPP; } + + /* Handle endianess of register if 16 bit */ + if (flags & I2C_REG16) { + reg_end = htons(reg); /* Make sure register is in big-endian on I2C bus */ + } + /* First set ADDR and register with no stop */ - int ret = i2c_write_bytes(dev, addr, ®, (flags & I2C_REG16) ? 2 : 1, + int ret = i2c_write_bytes(dev, addr, ®_end, (flags & I2C_REG16) ? 2 : 1, flags | I2C_NOSTOP); if (ret < 0) { return ret;