Skip to content

Commit 4922321

Browse files
authoredMay 29, 2019
Merge pull request RIOT-OS#11585 from fedepell/i2c_reg_endianess_2
periph/i2c: handle i2c register write/read helper function correctly in big endian
2 parents 1216c5f + 6171247 commit 4922321

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed
 

‎cpu/efm32/periph/i2c.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "cpu.h"
2424
#include "mutex.h"
25+
#include "byteorder.h"
2526

2627
#include "periph_conf.h"
2728
#include "periph/i2c.h"
@@ -183,16 +184,23 @@ int i2c_read_bytes(i2c_t dev, uint16_t address, void *data, size_t length, uint8
183184
int i2c_read_regs(i2c_t dev, uint16_t address, uint16_t reg,
184185
void *data, size_t length, uint8_t flags)
185186
{
187+
uint16_t reg_end = reg;
188+
186189
if (flags & (I2C_NOSTART | I2C_NOSTOP)) {
187190
return -EOPNOTSUPP;
188191
}
189192

193+
/* Handle endianess of register if 16 bit */
194+
if (flags & I2C_REG16) {
195+
reg_end = htons(reg); /* Make sure register is in big-endian on I2C bus */
196+
}
197+
190198
/* prepare transfer */
191199
I2C_TransferSeq_TypeDef transfer;
192200

193201
transfer.addr = (address << 1);
194202
transfer.flags = I2C_FLAG_WRITE_READ | ((flags & I2C_ADDR10) ? I2C_FLAG_10BIT_ADDR : 0);
195-
transfer.buf[0].data = (uint8_t *) &reg;
203+
transfer.buf[0].data = (uint8_t *) &reg_end;
196204
transfer.buf[0].len = (flags & I2C_REG16) ? 2 : 1;
197205
transfer.buf[1].data = (uint8_t *) data;
198206
transfer.buf[1].len = length;
@@ -222,16 +230,23 @@ int i2c_write_bytes(i2c_t dev, uint16_t address, const void *data, size_t length
222230
int i2c_write_regs(i2c_t dev, uint16_t address, uint16_t reg,
223231
const void *data, size_t length, uint8_t flags)
224232
{
233+
uint16_t reg_end = reg;
234+
225235
if (flags & (I2C_NOSTART | I2C_NOSTOP)) {
226236
return -EOPNOTSUPP;
227237
}
228238

239+
/* Handle endianess of register if 16 bit */
240+
if (flags & I2C_REG16) {
241+
reg_end = htons(reg); /* Make sure register is in big-endian on I2C bus */
242+
}
243+
229244
/* prepare transfer */
230245
I2C_TransferSeq_TypeDef transfer;
231246

232247
transfer.addr = (address << 1);
233248
transfer.flags = I2C_FLAG_WRITE_WRITE | ((flags & I2C_ADDR10) ? I2C_FLAG_10BIT_ADDR : 0);
234-
transfer.buf[0].data = (uint8_t *) &reg;
249+
transfer.buf[0].data = (uint8_t *) &reg_end;
235250
transfer.buf[0].len = (flags & I2C_REG16) ? 2 : 1;
236251
transfer.buf[1].data = (uint8_t *) data;
237252
transfer.buf[1].len = length;

‎drivers/include/periph/i2c.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ typedef enum {
195195
#ifndef HAVE_I2C_FLAGS_T
196196
typedef enum {
197197
I2C_ADDR10 = 0x01, /**< use 10-bit device addressing */
198-
I2C_REG16 = 0x02, /**< use 16-bit register addressing */
198+
I2C_REG16 = 0x02, /**< use 16-bit register addressing, big-endian */
199199
I2C_NOSTOP = 0x04, /**< do not issue a STOP condition after transfer */
200200
I2C_NOSTART = 0x08, /**< skip START sequence, ignores address field */
201201
} i2c_flags_t;

‎drivers/periph_common/i2c.c

+19-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "board.h"
2323
#include "cpu.h"
2424
#include "periph/i2c.h"
25+
#include "byteorder.h"
2526

2627
#ifdef I2C_NUMOF
2728

@@ -37,11 +38,19 @@ int i2c_read_reg(i2c_t dev, uint16_t addr, uint16_t reg,
3738
int i2c_read_regs(i2c_t dev, uint16_t addr, uint16_t reg,
3839
void *data, size_t len, uint8_t flags)
3940
{
41+
uint16_t reg_end = reg;
42+
4043
if (flags & (I2C_NOSTOP | I2C_NOSTART)) {
4144
return -EOPNOTSUPP;
4245
}
46+
47+
/* Handle endianess of register if 16 bit */
48+
if (flags & I2C_REG16) {
49+
reg_end = htons(reg); /* Make sure register is in big-endian on I2C bus */
50+
}
51+
4352
/* First set ADDR and register with no stop */
44-
int ret = i2c_write_bytes(dev, addr, &reg, (flags & I2C_REG16) ? 2 : 1,
53+
int ret = i2c_write_bytes(dev, addr, &reg_end, (flags & I2C_REG16) ? 2 : 1,
4554
flags | I2C_NOSTOP);
4655
if (ret < 0) {
4756
return ret;
@@ -73,11 +82,19 @@ int i2c_write_reg(i2c_t dev, uint16_t addr, uint16_t reg,
7382
int i2c_write_regs(i2c_t dev, uint16_t addr, uint16_t reg,
7483
const void *data, size_t len, uint8_t flags)
7584
{
85+
uint16_t reg_end = reg;
86+
7687
if (flags & (I2C_NOSTOP | I2C_NOSTART)) {
7788
return -EOPNOTSUPP;
7889
}
90+
91+
/* Handle endianess of register if 16 bit */
92+
if (flags & I2C_REG16) {
93+
reg_end = htons(reg); /* Make sure register is in big-endian on I2C bus */
94+
}
95+
7996
/* First set ADDR and register with no stop */
80-
int ret = i2c_write_bytes(dev, addr, &reg, (flags & I2C_REG16) ? 2 : 1,
97+
int ret = i2c_write_bytes(dev, addr, &reg_end, (flags & I2C_REG16) ? 2 : 1,
8198
flags | I2C_NOSTOP);
8299
if (ret < 0) {
83100
return ret;

0 commit comments

Comments
 (0)