This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unable to Connect nRF5340DK with BMI270 Over I2C

I am attempting to get the BMI270 sample working on an nRF5340DK, using nRF Connect SDK v1.6.0, but all attempts at device_get_binding("BMI270"), device_get_binding(DT_LABEL(DT_INST(0, bosch_bmi270))), and similar return null.  I am using the following config and overlay files

#prj.conf

CONFIG_UART_CONSOLE=n
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_BMI270=y

/* nrf5340dk_nrf5340_cpuapp.overlay - no shield */

&arduino_i2c {
	status = "okay";

	bmi270@68 {
		compatible = "bosch,bmi270";
		reg = <0x68>;
		label = "BMI270";
	};
};

On the hardware side I'm using a BMI270 breakout connecting SDA to P1.02 and SCL to P1.03.

I have also used a shield that sends SDA to P0.25 and SCL to P0.26, with the following overlay

/* nrf5340dk_nrf5340_cpuapp.overlay - with shield */

&i2c1 {
    sda-pin = <25>;
    scl-pin = <26>;
};

&arduino_i2c {
	status = "okay";

	bmi270@68 {
		compatible = "bosch,bmi270";
		reg = <0x68>;
		label = "BMI270";
	};
};

In all attempted cases

#include <zephyr.h>
#include <device.h>
#include <drivers/sensor.h>
#include <stdio.h>

void main(void)
{
	const struct device *dev;

	dev = device_get_binding("BMI270");

	if (dev == NULL) {
		printf("Could not get %s device\n",
		       DT_LABEL(DT_INST(0, bosch_bmi270)));
		return;
	}
	...
}

gives the output

00> *** Booting Zephyr OS build v2.6.0-rc1-ncs1  ***
00> Could not get BMI270 device

in J-Link RTT Viewer.

Any help would be greatly appreciated.

Parents
  • Hi Jonathan, sorry to hear you're having trouble.

    To try to diagnose, I changed the sample as follows:
     
    gist.github.com/.../7abd6107b22c20470e04e780c58cf119
     
    My goal there is to figure out whether device_get_binding() is returning NULL because
     
    1. the device doesn't exist, or
    2. the device initialization function failed
     
    I built with:
     
    $ west build -b nrf5340dk_nrf5340_cpuapp
     
    If the build fails, it's 1. If the build doesn't fail, I'm guessing it's 2.  The build succeeded, so it's not 1.
     
    To confirm that it's 2., I would have to run the program with a breakpoint on bmi270_init(), to see if it returns nonzero.
     
    I don't have hardware, though -- could you please get the bmi270_init() return value on your nRF5340 setup to see what happened?
     
    If it's returning nonzero, the error number and a stack trace when bmi270_init() returns would help diagnose further.

  • Hi Marti,

    Stepping through bmi270_init(), it looks like the error is being generated at ret = write_config_file(drv_dev), see below.

  • Thanks!

    From your screenshot, you're getting -EIO from the i2c_burst_write() call on line 35, which indicates a real error coming out of i2c_nrfx_twim_transfer() in the I2C driver, i2c_nrfx_twim.c.

    Beyond just looking at the bus, you can build like this to enable more logs:

    west build -b nrf5340dk_nrf5340_cpuapp -- -DCONFIG_LOG=y -DCONFIG_LOG_MODE_IMMEDIATE=y  -DEXTRA_CFLAGS="-DNRFX_TWIM_CONFIG_LOG_ENABLED=1 -DNRFX_TWIM_CONFIG_LOG_LEVEL=4"

    I'm a bit surprised you're getting a different result on nRF52833DK since it's the same driver, but maybe comparing those logs will show where things go wrong on nRF5340.

  • Hi Marti,

    I really appreciate your help. I ran with the extra flags, but I didn't see anything that pointed to an answer in the logs.  I am very enthusiastic about the new features on the nrf5340, but this level of complication just to print IMU data over i2c doesn't bode well for the more complex development to come.  It seems like we need to stick with the nrf52833 for now. Thanks again for trying to help us find an answer though. 

Reply Children
  • Hi again, Jonathan!

    After digging a little and reading through Marti's comments here I finally tracked down the problem. This issue arises because of how the TWI with easyDMA hardware is implemented on the nRF5340. You can read more about it in this GitHub issue.

    In summary burst writes from the nRF5340 generates repeated starts, which are not handled well by some sensors/devices. Seemingly BMI270 is one of these. The fix for this issue is to use the normal i2c_write() function instead of i2c_burst_write(). If you choose to change the driver to work with the nRF5340, please consider doing a PR for the fix for the Zephyr RTOS GitHub repository as well. EDIT: try the method presented in my comment below instead.

    You do not see this issue on the nRF52833 as it by default is using TWI without easyDMA.

    Thank you for your patience and thank you Marti for the help. It was the following comment that helped me pick up the scent:

    marti.bolivar.nordic said:
    From your screenshot, you're getting -EIO from the i2c_burst_write() call on line 35, which indicates a real error coming out of i2c_nrfx_twim_transfer() in the I2C driver, i2c_nrfx_twim.c.

    Best regards,
    Carl Richard

  • Additional note here. Before changing the driver you can try to use the concat-buf-size property of the TWIM peripheral. This was implemented/added to prevent the issues you are seeing.

    Just add the property to your overlay file with a suitable size. Looking at threads describing the same issue as yours the following overlay, with concat-buf-size at 128, seems to work:

    /*
     * Copyright (c) 2021 Bosch Sensortec GmbH
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    &arduino_i2c {
        status = "okay";
        zephyr,concat-buf-size = <128>;
        bmi270@68 {
            compatible = "bosch,bmi270";
            reg = <0x68>;
            label = "BMI270";
        };
    };


    Best regards,
    Carl Richard

  • Hi Carl,

    Thank you, that's very helpful in understanding the cause of the i2c problems.  Unfortunately, adding zephyr, concat-buf-size=<128>; to the overlay didn't help.  I modified bmi270.c so that reg_write() uses i2c_write() instead of i2c_burst_write() as follows:

    static int reg_write(uint8_t reg, const uint8_t *data, uint16_t length,
    		     struct bmi270_data *dev)
    {
    	uint8_t buffer[1+length];
            __ASSERT((1U + length) <= sizeof(buffer),
                              "burst buffer too small");
            buffer[0]=reg;
            memmove(buffer+1,data,length);
            return i2c_write(dev->i2c,buffer,1+length,dev->i2c_addr);
    }

    With this change to the BMI270 driver, I get streaming data on both the 5340dk and the 52833dk.

    As suggested in the struck-through text, I created a pull request here: github.com/.../37190

Related