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
  • I think I have the same issue on SDK 3.2.1. I'm trying to complete the nRF Connect SDK Fundamentals lesson 6 exercise 1, and it's failing. My logic analyzer shows almost identical to yours. Address and single byte written get ACK, and then it returns with an error code, and lets the bus rise into "inactive" (no stop bit, no restart attempt).

    I tried adding debugging I2C with CONFIG_I2C_LOG_LEVEL_DBG=y which didn't give me answers. I tried disabling the SPI interfaces, I tried both I2C0 and I2C1 with no change. I ensured there are no device tree IO pin conflicts with the I2C pins. I tried i2c_write_read_dt (from the exercise) as well as i2c_write_dt, and both look good on the logic analyzer (including ACK), but both missing the restart/stop. I tried on both an nRF52832 and nRF52840. I even tried skipping the zephyr I2C drivers and configuring the registers directly with nrfx_twim_init, nrfx_twim_enable, and nrfx_twim_xfer.

    After several days of frustration and trying to track it down, I realized it works perfectly well on SDK 3.1.1, so something must have broken at 3.2.0 and/or 3.2.1

    Edit: I also looked at the analog levels of the I2C signals to ensure they are crisp and well within voltage expectations, and even tried multiple sets of pullup resistors from ~910 ohms up to 10k ohms. Changing pullup resistors didn't seem to make any difference in the outcome (still failed the same), although I could see the corresponding changes to the rise time of the signals on the oscilloscope. 10k looks a little weak for my setup, but on SDK 3.1.1 it still works perfectly fine.

  • Hello mt37,

    Can you show me the error log?

    Did you try to add the fix I mentioned in my (compatible = "nordic,nrf-twim";) reply? Also, you need to add bias-pull-up in the device tree file if you use internal pull-up resistor.

  • l6e1 only works if I either add your fix, or if I run an older version of the SDK.

  • Hello,

    That's the fix for now as there is bug in the "nordic,nrf-twi" driver in ncs v3.2.1.

Reply Children
No Data
Related