diff --git a/cpu/nrf5x_common/periph/i2c_nrf52_nrf9160.c b/cpu/nrf5x_common/periph/i2c_nrf52_nrf9160.c index 8f420deba3..288de26074 100644 --- a/cpu/nrf5x_common/periph/i2c_nrf52_nrf9160.c +++ b/cpu/nrf5x_common/periph/i2c_nrf52_nrf9160.c @@ -92,6 +92,14 @@ static inline NRF_TWIM_Type *bus(i2c_t dev) return i2c_config[dev].dev; } +/** + * @brief Like i2c_write_bytes, but with the constraint (created by the + * hardware) that data is in RAM + */ +static int direct_i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, + size_t len, + uint8_t flags); + /** * Block until the interrupt described by inten_success_flag or * TWIM_INTEN_ERROR_Msk fires. @@ -262,7 +270,7 @@ int i2c_write_regs(i2c_t dev, uint16_t addr, uint16_t reg, } memcpy(&tx_buf[reg_addr_len], data, len); - int ret = i2c_write_bytes(dev, addr, tx_buf, reg_addr_len + len, flags); + int ret = direct_i2c_write_bytes(dev, addr, tx_buf, reg_addr_len + len, flags); /* Release tx_buf */ mutex_unlock(&buffer_lock); @@ -331,6 +339,31 @@ int i2c_read_regs(i2c_t dev, uint16_t addr, uint16_t reg, int i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_t len, uint8_t flags) +{ + if ((unsigned int)data >= CPU_RAM_BASE && (unsigned int)data < CPU_RAM_BASE + CPU_RAM_SIZE) { + return direct_i2c_write_bytes(dev, addr, data, len, flags); + } + + /* These are critical for the memcpy; direct_i2c_write_bytes makes some + * more */ + assert((len > 0) && (len < 256)); + + /* Lock tx_buf */ + mutex_lock(&buffer_lock); + + memcpy(tx_buf, data, len); + + int result = direct_i2c_write_bytes(dev, addr, tx_buf, len, flags); + + /* Release tx_buf */ + mutex_unlock(&buffer_lock); + + return result; +} + +int direct_i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, + size_t len, + uint8_t flags) { assert((dev < I2C_NUMOF) && data && (len > 0) && (len < 256));