Skip to content

Commit 219245e

Browse files
deshipudpgeorge
authored andcommitted
extmod/machine_i2c: Add support for the addrsize parameter in mem xfers.
The memory read/write I2C functions now take an optional keyword-only parameter that specifies the number of bits in the memory address. Only mem-addrs that are a multiple of 8-bits are supported (otherwise the behaviour is undefined). Due to the integer type used for the address, for values larger than 32 bits, only 32 bits of address will be sent, and the rest will be padded with 0s. Right now no exception is raised when that happens. For values smaller than 8, no address is sent. Also no exception then. Tested with a VL6180 sensor, which has 16-bit register addresses. Due to code refactoring, this patch reduces stmhal and esp8266 builds by about 50 bytes.
1 parent 7165fbd commit 219245e

2 files changed

Lines changed: 63 additions & 74 deletions

File tree

docs/library/machine.I2C.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,7 @@ methods are convenience functions to communicate with such devices.
170170

171171
Read `nbytes` from the slave specified by `addr` starting from the memory
172172
address specified by `memaddr`.
173-
The argument `addrsize` specifies the address size in bits (on ESP8266
174-
this argument is not recognised and the address size is always 8 bits).
173+
The argument `addrsize` specifies the address size in bits.
175174
Returns a `bytes` object with the data read.
176175

177176
.. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8)

extmod/machine_i2c.c

Lines changed: 62 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -128,24 +128,6 @@ STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
128128
return !ret;
129129
}
130130

131-
STATIC void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
132-
mp_hal_i2c_start(self);
133-
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
134-
goto er;
135-
}
136-
while (len--) {
137-
if (!mp_hal_i2c_write_byte(self, *data++)) {
138-
goto er;
139-
}
140-
}
141-
mp_hal_i2c_stop(self);
142-
return;
143-
144-
er:
145-
mp_hal_i2c_stop(self);
146-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
147-
}
148-
149131
STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) {
150132
mp_hal_i2c_delay(self);
151133
mp_hal_i2c_scl_low(self);
@@ -172,33 +154,27 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack)
172154
return 1; // success
173155
}
174156

175-
STATIC void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
176-
mp_hal_i2c_start(self);
177-
if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
178-
goto er;
157+
// addr is the device address, memaddr is a memory address sent big-endian
158+
STATIC int mp_hal_i2c_write_addresses(machine_i2c_obj_t *self, uint8_t addr,
159+
uint32_t memaddr, uint8_t addrsize) {
160+
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
161+
return 0; // error
179162
}
180-
while (len--) {
181-
if (!mp_hal_i2c_read_byte(self, data++, len == 0)) {
182-
goto er;
163+
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
164+
if (!mp_hal_i2c_write_byte(self, memaddr >> i)) {
165+
return 0; // error
183166
}
184167
}
185-
mp_hal_i2c_stop(self);
186-
return;
187-
188-
er:
189-
mp_hal_i2c_stop(self);
190-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
168+
return 1; // success
191169
}
192170

193-
STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, const uint8_t *src, size_t len) {
171+
STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr,
172+
uint32_t memaddr, uint8_t addrsize, const uint8_t *src, size_t len) {
194173
// start the I2C transaction
195174
mp_hal_i2c_start(self);
196175

197176
// write the slave address and the memory address within the slave
198-
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
199-
goto er;
200-
}
201-
if (!mp_hal_i2c_write_byte(self, memaddr)) {
177+
if (!mp_hal_i2c_write_addresses(self, addr, memaddr, addrsize)) {
202178
goto er;
203179
}
204180

@@ -218,27 +194,45 @@ STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t
218194
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
219195
}
220196

221-
STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, uint8_t *dest, size_t len) {
197+
STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr,
198+
uint32_t memaddr, uint8_t addrsize, uint8_t *dest, size_t len) {
222199
// start the I2C transaction
223200
mp_hal_i2c_start(self);
224201

225-
// write the slave address and the memory address within the slave
226-
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
227-
goto er;
202+
if (addrsize) {
203+
// write the slave address and the memory address within the slave
204+
if (!mp_hal_i2c_write_addresses(self, addr, memaddr, addrsize)) {
205+
goto er;
206+
}
207+
208+
// i2c_read will do a repeated start, and then read the I2C memory
209+
mp_hal_i2c_start(self);
228210
}
229-
if (!mp_hal_i2c_write_byte(self, memaddr)) {
211+
212+
if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
230213
goto er;
231214
}
232-
233-
// i2c_read will do a repeated start, and then read the I2C memory
234-
mp_hal_i2c_read(self, addr, dest, len);
215+
while (len--) {
216+
if (!mp_hal_i2c_read_byte(self, dest++, len == 0)) {
217+
goto er;
218+
}
219+
}
220+
mp_hal_i2c_stop(self);
235221
return;
236222

237223
er:
238224
mp_hal_i2c_stop(self);
239225
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
240226
}
241227

228+
STATIC void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, const uint8_t *src, size_t len) {
229+
mp_hal_i2c_write_mem(self, addr, 0, 0, src, len);
230+
}
231+
232+
STATIC void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *dest, size_t len) {
233+
mp_hal_i2c_read_mem(self, addr, 0, 0, dest, len);
234+
}
235+
242236
/******************************************************************************/
243237
// MicroPython bindings for I2C
244238

@@ -367,68 +361,64 @@ STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t
367361
}
368362
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto);
369363

364+
STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
365+
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
366+
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
367+
{ MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
368+
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
369+
};
370+
370371
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
371372
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
372-
static const mp_arg_t allowed_args[] = {
373-
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
374-
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
375-
{ MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
376-
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
377-
};
378373
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
379-
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
380-
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
374+
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
375+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
376+
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
381377

382378
// create the buffer to store data into
383379
vstr_t vstr;
384-
vstr_init_len(&vstr, args[ARG_n].u_int);
380+
vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
385381

386382
// do the transfer
387-
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, (uint8_t*)vstr.buf, vstr.len);
383+
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
384+
args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
388385
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
389386
}
390387
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
391388

389+
392390
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
393391
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
394-
static const mp_arg_t allowed_args[] = {
395-
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
396-
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
397-
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
398-
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
399-
};
400392
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
401-
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
402-
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
393+
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
394+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
395+
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
403396

404397
// get the buffer to store data into
405398
mp_buffer_info_t bufinfo;
406399
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
407400

408401
// do the transfer
409-
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
402+
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
403+
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
410404
return mp_const_none;
411405
}
412406
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
413407

414408
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
415409
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
416-
static const mp_arg_t allowed_args[] = {
417-
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
418-
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
419-
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
420-
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
421-
};
422410
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
423-
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
424-
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
411+
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
412+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
413+
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
425414

426415
// get the buffer to write the data from
427416
mp_buffer_info_t bufinfo;
428417
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
429418

430419
// do the transfer
431-
mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
420+
mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
421+
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
432422
return mp_const_none;
433423
}
434424
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);

0 commit comments

Comments
 (0)