BMI270 Accelerometer device is ready when debugging but not when just flashing on a custom board

I am using a custom board with a nrf5340 chip on it with vs code and sdk/toolchain of 2.9.1 and the bmi270 sample. I am getting and issue with my bmi270 accelerometer when I run, but it succeeds when I step through to debug. Here is the log when it fails:

00> [00:00:00.734,924] <err> voltage: setup: -134
00> *** Booting nRF Connect SDK v2.9.1-60d0d6c8d42d ***
00> *** Using Zephyr OS v3.7.99-ca954a6216c9 ***
00> [00:00:00.735,748] <dbg> app: main: Starting BMI270 sensor example, test number 0
00> [00:00:00.735,778] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
00> [00:00:00.735,778] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
00> [00:00:00.735,809] <err> app: Device bmi270@68 is not ready

and here it is when it succeeds during debug:

00> [00:00:00.730,316] <err> voltage: setup: -134
00> [00:00:25.385,620] <dbg> bmi270: write_config_file: writing config file max_fifo
00> *** Booting nRF Connect SDK v2.9.1-60d0d6c8d42d ***
00> *** Using Zephyr OS v3.7.99-ca954a6216c9 ***
00> [00:00:59.785,156] <dbg> app: main: Starting BMI270 sensor example, test number 0
00> [00:01:01.364,959] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
00> [00:01:01.364,959] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
00> [00:01:26.873,657] <dbg> app: main: Device 0xf674 name is bmi270@68
00> [00:01:26.895,629] <dbg> app: main: AX: 0.000000; AY: 0.000000; AZ: 0.000000; GX: 0.000000; GY: 0.000000; GZ: 0.000000;
00> [00:01:26.906,188] <dbg> app: main: AX: 0.000000; AY: 0.000000; AZ: 0.000000; GX: 0.000000; GY: 0.000000; GZ: 0.000000;
00> [00:01:26.916,717] <dbg> app: main: AX: 0.000000; AY: 0.000000; AZ: 0.000000; GX: 0.000000; GY: 0.000000; GZ: 0.000000;
00> 0m

Prj.conf has been edited:

CONFIG_STDOUT_CONSOLE=y
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_LOG=y

CONFIG_BMI270=y
CONFIG_BMI270_TRIGGER_GLOBAL_THREAD=y

CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_UART_CONSOLE=n
CONFIG_LOG_INFO_COLOR_GREEN=y
CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_LOG_BACKEND_RTT_MODE_BLOCK=y
CONFIG_LOG_BUFFER_SIZE=4096
CONFIG_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE=128
CONFIG_LOG_BLOCK_IN_THREAD=y

CONFIG_SENSOR_LOG_LEVEL_DBG=y
CONFIG_I2C_LOG_LEVEL_DBG=y

Code id adapted somewhat as well (need to change the VREGH):

/*
 * Copyright (c) 2021 Bosch Sensortec GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

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

#include "voltage_manager.h"


LOG_MODULE_REGISTER(app, LOG_LEVEL_DBG);

int test_num = 0;

int main(void)
{
	LOG_DBG("Starting BMI270 sensor example, test number %d", test_num);
	change_gpio_voltage(UICR_VREGHVOUT_VREGHVOUT_3V0);

	const struct device *const dev = DEVICE_DT_GET_ONE(bosch_bmi270);
	struct sensor_value acc[3], gyr[3];
	struct sensor_value full_scale, sampling_freq, oversampling;


	if (!device_is_ready(dev)) {
		LOG_ERR("Device %s is not ready", dev->name);
		return 0;
	}

	LOG_DBG("Device %p name is %s", dev, dev->name);

	/* Setting scale in G, due to loss of precision if the SI unit m/s^2
	 * is used
	 */
	full_scale.val1 = 2;            /* G */
	full_scale.val2 = 0;
	sampling_freq.val1 = 100;       /* Hz. Performance mode */
	sampling_freq.val2 = 0;
	oversampling.val1 = 1;          /* Normal mode */
	oversampling.val2 = 0;

	sensor_attr_set(dev, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_FULL_SCALE,
			&full_scale);
	sensor_attr_set(dev, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_OVERSAMPLING,
			&oversampling);
	/* Set sampling frequency last as this also sets the appropriate
	 * power mode. If already sampling, change to 0.0Hz before changing
	 * other attributes
	 */
	sensor_attr_set(dev, SENSOR_CHAN_ACCEL_XYZ,
			SENSOR_ATTR_SAMPLING_FREQUENCY,
			&sampling_freq);


	/* Setting scale in degrees/s to match the sensor scale */
	full_scale.val1 = 500;          /* dps */
	full_scale.val2 = 0;
	sampling_freq.val1 = 100;       /* Hz. Performance mode */
	sampling_freq.val2 = 0;
	oversampling.val1 = 1;          /* Normal mode */
	oversampling.val2 = 0;

	sensor_attr_set(dev, SENSOR_CHAN_GYRO_XYZ, SENSOR_ATTR_FULL_SCALE,
			&full_scale);
	sensor_attr_set(dev, SENSOR_CHAN_GYRO_XYZ, SENSOR_ATTR_OVERSAMPLING,
			&oversampling);
	/* Set sampling frequency last as this also sets the appropriate
	 * power mode. If already sampling, change sampling frequency to
	 * 0.0Hz before changing other attributes
	 */
	sensor_attr_set(dev, SENSOR_CHAN_GYRO_XYZ,
			SENSOR_ATTR_SAMPLING_FREQUENCY,
			&sampling_freq);

	while (1) {
		/* 10ms period, 100Hz Sampling frequency */
		k_sleep(K_MSEC(10));

		sensor_sample_fetch(dev);

		sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ, acc);
		sensor_channel_get(dev, SENSOR_CHAN_GYRO_XYZ, gyr);

		LOG_DBG("AX: %d.%06d; AY: %d.%06d; AZ: %d.%06d; "
		       "GX: %d.%06d; GY: %d.%06d; GZ: %d.%06d;",
		       acc[0].val1, acc[0].val2,
		       acc[1].val1, acc[1].val2,
		       acc[2].val1, acc[2].val2,
		       gyr[0].val1, gyr[0].val2,
		       gyr[1].val1, gyr[1].val2,
		       gyr[2].val1, gyr[2].val2);
	}
	return 0;
}

it's strange it works when I'm stepping through it in debug but not when I build and flash it

  • because somehow debugger is changing the timings of the initialization inserting delays which happen to luckily working in the right way to stretch out time between rail goes to 3v and the driver probing the chip.

  • Ok. All of that is way over my head. It seems like there should be a way to control the timing of initialization. I guess checking with the code you provided will prove if the theory you have is correct or not. It seems like changing the VREGH every time is a little extreme, but I can test it out.

    There is no UICR_VREGHVOUT_VREGHVOUT_0V0

    These are the options:

    /* Bits 2..0 : VREGH regulator output voltage. */
    #define UICR_VREGHVOUT_VREGHVOUT_Pos (0UL) /*!< Position of VREGHVOUT field. */
    #define UICR_VREGHVOUT_VREGHVOUT_Msk (0x7UL << UICR_VREGHVOUT_VREGHVOUT_Pos) /*!< Bit mask of VREGHVOUT field. */
    #define UICR_VREGHVOUT_VREGHVOUT_1V8 (0x0UL) /*!< 1.8 V */
    #define UICR_VREGHVOUT_VREGHVOUT_2V1 (0x1UL) /*!< 2.1 V */
    #define UICR_VREGHVOUT_VREGHVOUT_2V4 (0x2UL) /*!< 2.4 V */
    #define UICR_VREGHVOUT_VREGHVOUT_2V7 (0x3UL) /*!< 2.7 V */
    #define UICR_VREGHVOUT_VREGHVOUT_3V0 (0x4UL) /*!< 3.0 V */
    #define UICR_VREGHVOUT_VREGHVOUT_3V3 (0x5UL) /*!< 3.3 V */
    #define UICR_VREGHVOUT_VREGHVOUT_DEFAULT (0x7UL) /*!< Default voltage: 1.8 V */

  • That didn't work. Seems to keep restarting over and over again when trying to switch between 1V8 and 3V0.

    I've tried with all kinds of variations of wait time between the vregh call  (which does nothing the 2nd time btw, so it should not be a problem) and the accelerometer initialization, even so much as 1 minute.

Related