From da27253693a92d44f194ae58a620f08bd8a30b46 Mon Sep 17 00:00:00 2001 From: arturo182 Date: Wed, 4 Jul 2018 20:33:01 +0200 Subject: nrf: Fix I2C transfers with data larger than HW allows --- ports/nrf/common-hal/busio/I2C.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c index c84c763f6..f42189162 100644 --- a/ports/nrf/common-hal/busio/I2C.c +++ b/ports/nrf/common-hal/busio/I2C.c @@ -34,6 +34,7 @@ #include "nrf_gpio.h" #define INST_NO 0 +#define MAX_XFER_SIZE ((1U << NRFX_CONCAT_3(TWIM, INST_NO, _EASYDMA_MAXCNT_SIZE)) - 1) static uint8_t twi_error_to_mp(const nrfx_err_t err) { switch (err) { @@ -152,8 +153,21 @@ uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const u if(len == 0) return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV; + const uint32_t parts = len / MAX_XFER_SIZE; + const uint32_t remainder = len % MAX_XFER_SIZE; + nrfx_err_t err = NRFX_SUCCESS; + nrfx_twim_enable(&self->twim); - const nrfx_err_t err = nrfx_twim_tx(&self->twim, addr, data, len, !stopBit); + + for (uint32_t i = 0; i < parts; ++i) { + err = nrfx_twim_tx(&self->twim, addr, data + i * MAX_XFER_SIZE, MAX_XFER_SIZE, !stopBit); + if (err != NRFX_SUCCESS) + break; + } + + if ((remainder > 0) && (err == NRFX_SUCCESS)) + err = nrfx_twim_tx(&self->twim, addr, data + parts * MAX_XFER_SIZE, remainder, !stopBit); + nrfx_twim_disable(&self->twim); return twi_error_to_mp(err); @@ -163,8 +177,21 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t if(len == 0) return 0; + const uint32_t parts = len / MAX_XFER_SIZE; + const uint32_t remainder = len % MAX_XFER_SIZE; + nrfx_err_t err = NRFX_SUCCESS; + nrfx_twim_enable(&self->twim); - const nrfx_err_t err = nrfx_twim_rx(&self->twim, addr, data, len); + + for (uint32_t i = 0; i < parts; ++i) { + err = nrfx_twim_rx(&self->twim, addr, data + i * MAX_XFER_SIZE, MAX_XFER_SIZE); + if (err != NRFX_SUCCESS) + break; + } + + if ((remainder > 0) && (err == NRFX_SUCCESS)) + err = nrfx_twim_rx(&self->twim, addr, data + parts * MAX_XFER_SIZE, remainder); + nrfx_twim_disable(&self->twim); return twi_error_to_mp(err); -- cgit v1.2.3