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
  • Hello,

    I have tried your sample on nRF52840dk (with modified C code and the device tree) for both NCS v2.1.1 and NCS v3.1.1. My system is windows.

    Overlay file name: nrf52840dk_nrf52840.overlay

    Build command: west build -p -b nrf52840dk/nrf5284

    The application built and flashed ok.

    I got same output for both version

    In your application, you choose i2c1, so the SDA and SCL pin should show the output on the pin P 0.30 and P0.21 according to nRF52840 board file.

    Can you please share which pins you are using for seeing SDA and SCL output on logic analyser?

  • Hi, I am measuring the signals on P0.30 and P0.31.

    If you don't have an rv3028 RTC connected to these pins, it's normal that it would fail in both cases. If you have another I2C peripheral handy, you can change the address in the device tree overlay (and perhaps slightly adapt the main.c to read some other registers) and try with your own peripheral.

Reply Children
Related