From 5233fb3a3d3245bd4c5dfb781e3fcbc8a3fbfd6a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Jun 2022 11:57:57 +1000 Subject: [PATCH] extmod/machine_i2c: Only use WRITE1 option if transfer supports it. When MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 is enabled the port's hardware I2C transfer functions should support the MP_MACHINE_I2C_FLAG_WRITE1 option, but software I2C will not. So add a flag to the I2C protocol struct so each individual protocol can indicate whether it supports this option or not. Fixes issue #8765. Signed-off-by: Damien George --- extmod/machine_i2c.c | 25 ++++++++++++------------- extmod/machine_i2c.h | 3 +++ ports/esp32/machine_i2c.c | 1 + 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 7d0628a2d4..452f07a2eb 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -515,19 +515,20 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize); #if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 - - // Create partial write and read buffers - mp_machine_i2c_buf_t bufs[2] = { - {.len = memaddr_len, .buf = memaddr_buf}, - {.len = len, .buf = buf}, - }; - - // Do write+read I2C transfer + // The I2C transfer function may support the MP_MACHINE_I2C_FLAG_WRITE1 option mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; - return i2c_p->transfer(self, addr, 2, bufs, - MP_MACHINE_I2C_FLAG_WRITE1 | MP_MACHINE_I2C_FLAG_READ | MP_MACHINE_I2C_FLAG_STOP); + if (i2c_p->transfer_supports_write1) { + // Create partial write and read buffers + mp_machine_i2c_buf_t bufs[2] = { + {.len = memaddr_len, .buf = memaddr_buf}, + {.len = len, .buf = buf}, + }; - #else + // Do write+read I2C transfer + return i2c_p->transfer(self, addr, 2, bufs, + MP_MACHINE_I2C_FLAG_WRITE1 | MP_MACHINE_I2C_FLAG_READ | MP_MACHINE_I2C_FLAG_STOP); + } + #endif int ret = mp_machine_i2c_writeto(self, addr, memaddr_buf, memaddr_len, false); if (ret != memaddr_len) { @@ -536,8 +537,6 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a return ret; } return mp_machine_i2c_readfrom(self, addr, buf, len, true); - - #endif } STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) { diff --git a/extmod/machine_i2c.h b/extmod/machine_i2c.h index a211aef527..a3363d4c34 100644 --- a/extmod/machine_i2c.h +++ b/extmod/machine_i2c.h @@ -61,6 +61,9 @@ typedef struct _mp_machine_i2c_buf_t { // - transfer must be non-NULL // - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor typedef struct _mp_machine_i2c_p_t { + #if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 + bool transfer_supports_write1; + #endif void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); int (*start)(mp_obj_base_t *obj); int (*stop)(mp_obj_base_t *obj); diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c index b037202e8d..e25cad0b60 100644 --- a/ports/esp32/machine_i2c.c +++ b/ports/esp32/machine_i2c.c @@ -188,6 +188,7 @@ mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_ } STATIC const mp_machine_i2c_p_t machine_hw_i2c_p = { + .transfer_supports_write1 = true, .transfer = machine_hw_i2c_transfer, };