I2C write-restart-read issue on nRF Connect SDK v3.2.x

Hello,

The following code performs an I2C write-restart-read operation that works correctly on a NRF52840 devkit with ncs v3.1.1, but fails with ncs v3.2.0 and v3.2.1. Note that this code works correctly on stock Zephyr versions v4.2.0 and v4.3.0, so the problem seems to be specific to nRF Connect SDK.

The I2C slave being used is a rs3028 RTC being driven directly (without the Zephyr sensor driver), but I imagine that the problem is independent of the I2C peripheral.

The project is adapted from ncs/v3.1.1/zephyr/samples/drivers/i2c/target_eeprom, where main.c has been replaced by:

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/i2c/target/eeprom.h>

static const struct i2c_dt_spec spec_i2c_clock = I2C_DT_SPEC_GET(DT_NODELABEL(i2cclock));

void write_read_blocking(void* out_data, size_t out_size, void* in_data, size_t in_size) {
    struct i2c_msg msg[2] = {
        {
            .buf = out_data,
            .len = out_size,
            .flags = I2C_MSG_WRITE,
        },
        {
            .buf = in_data,
            .len = in_size,
            .flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP,
        },
    };

    // int retval = i2c_write_read_dt(&spec(), out_data, out_size, in_data, in_size);
    int retval = i2c_transfer_dt(&spec_i2c_clock, msg, 2);
	printk("retval: %d\n", retval);
}

int main(void)
{
	printk("i2c target sample\n");

	if (!i2c_is_ready_dt(&spec_i2c_clock)) {
		printk("I2C device not ready\n");
		return 0;
	}

	k_msleep(1000);

	uint8_t out[] = {0x00, };
	uint8_t in[7];

	write_read_blocking(out, sizeof(out), in, sizeof(in));

	return 0;
}

Both the i2c_write_read_dt and i2c_transfer_dt variants were tried, resulting in the same behavior. Here is the i2c.overlay file:

&spi0 { status = "disabled"; };
&spi1 { status = "disabled"; };
&spi2 { status = "disabled"; };

&i2c0 { status = "disabled"; };

&i2c1 {
	status = "okay";

	i2cclock: i2cclock@68 {
		compatible = "i2c-device";
		label = "I2CCLOCK";
		reg = <0x68>;
	};
};

And the build command:

west build -b nrf52840dk/nrf52840 -- -D DTC_OVERLAY_FILE=i2c.overlay

On ncs v3.1.1, one observes that the 52840 correctly writes the byte 0 to device 0x68, performs an I2C restart, and then reads 7 bytes of calendar data:

On ncs v3.2.1 and v3.2.0, one observes that the 52840 correctly writes the byte 0 to device 0x68, performs an I2C restart, and then terminates with retval=-5 (not clocking the read operation).

I am using nRF-Connect on Ubuntu 24.04.3 LTS, installed using the command-line approach described here:

https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/installation/install_ncs.html

Parents Reply
  • Hi Kazi,

    Thanks, that works! I am now observing the clock reading from the RTC chip, and the error code is 0.

    Why does 'nordic,nrf-twi' work with previous versions of nRF Connect, and with all versions of Zephyr, but not with nRF Connect v3.2.x? Has the TWI driver been changed? Isn't TWI a legacy implementation? Is this a bug that will be fixed?

    Why isn't TWIM the default implementation in the nrf52840dk/nrf52840 board?

    Best,

    David

Children
No Data
Related