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

Parents
  • It seems to me that the issue on your custom board the BMI270 driver runs immediately after reset, but the new 3 V rail isn’t stable yet. In a debugger session the halt gives enough time for the LDO to settle, but in a normal boot the sensor probe races ahead and fails.

    Can you try to add some delay about 50msafter change_gpio_voltage and before DEVICE_DT_GET_ONE so that it can give the sensor some time to initialize. It is very possible that the debugger which inserts extra clock cycles to halt the PC for debugging inserts enough delay to let the sensor initialize properly. Please try and let me know if this works.

  • No luck:

    00> [00:00:00.740,661] <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.741,485] <dbg> app: main: Starting BMI270 sensor example, test number 1
    00> [00:00:00.741,516] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.741,516] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.741,516] <dbg> app: main: Waiting 60 seconds for voltage to stabilize
    00> [00:01:00.741,638] <err> app: Device bmi270@68 is not ready

    and:

    00> [00:00:00.742,095] <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.742,919] <dbg> app: main: Starting BMI270 sensor example, test number 1
    00> [00:00:00.742,950] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.742,950] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.742,950] <dbg> app: main: Waiting 120 seconds for voltage to stabilize
    00> [00:02:00.743,072] <err> app: Device bmi270@68 is not ready

    and:

    00> [00:00:00.733,551] <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.734,375] <dbg> app: main: Starting BMI270 sensor example, test number 1
    00> [00:00:00.734,405] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.734,405] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.734,405] <dbg> app: main: Waiting 300 seconds for voltage to stabilize
    00> [00:05:00.734,527] <err> app: Device bmi270@68 is not ready

    change_gpio_voltage only does it the first time if it's not at the right setting. 

    However when I put k_sleep(K_SECONDS(2)); in it works:

    static int bmi270_init(const struct device *dev)
    {
    	int ret;
    	struct bmi270_data *data = dev->data;
    	uint8_t chip_id;
    	uint8_t soft_reset_cmd;
    	uint8_t init_ctrl;
    	uint8_t msg;
    	uint8_t tries;
    	uint8_t adv_pwr_save;
    k_sleep(K_SECONDS(2));
    	ret = bmi270_bus_check(dev);
    	if (ret < 0) {
    		LOG_ERR("Could not initialize bus");
    		return ret;
    	}
    	
    	...
    }

    Obviously, that's not a solution, but I hope it helps determine the problem and solution. Is there any way to delay the init?

    I've even tried this:

    static int set_volttage_early(void)
    {
    	int sleep_time = 2; // seconds
    	LOG_DBG("Setting GPIO voltage early in boot process");
        int rt = change_gpio_voltage(UICR_VREGHVOUT_VREGHVOUT_3V0);
    	LOG_DBG("sleeping for %d seconds", sleep_time);
    	k_sleep(K_SECONDS(sleep_time));
    	return rt;
    }
    
    SYS_INIT(set_volttage_early, POST_KERNEL, 1); 

    But it doesn't work (I put debug statements in the init to show order):

    00> [00:00:00.719,299] <dbg> app: set_volttage_early: Setting GPIO voltage early in boot process
    00> [00:00:00.719,299] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.719,329] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.719,329] <inf> voltage_mgr: Target voltage already set. No action needed.
    00> [00:00:00.719,329] <dbg> app: set_volttage_early: sleeping for 2 seconds
    00> [00:00:02.719,696] <err> voltage: setup: -134
    00> [00:00:02.719,726] <dbg> bmi270: bmi270_init: Initializing BMI270 sensor
    00> *** Booting nRF Connect SDK v2.9.1-60d0d6c8d42d ***
    00> *** Using Zephyr OS v3.7.99-ca954a6216c9 ***
    00> [00:00:02.720,520] <dbg> app: main: Starting BMI270 sensor example, test number 2
    00> [00:00:02.720,550] <dbg> app: main: Waiting 1 seconds for voltage to stabilize
    00> [00:00:03.720,642] <err> app: Device bmi270@68 is not ready

    Seems strange I can delay before the init, but it only works in the init.

Reply
  • No luck:

    00> [00:00:00.740,661] <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.741,485] <dbg> app: main: Starting BMI270 sensor example, test number 1
    00> [00:00:00.741,516] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.741,516] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.741,516] <dbg> app: main: Waiting 60 seconds for voltage to stabilize
    00> [00:01:00.741,638] <err> app: Device bmi270@68 is not ready

    and:

    00> [00:00:00.742,095] <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.742,919] <dbg> app: main: Starting BMI270 sensor example, test number 1
    00> [00:00:00.742,950] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.742,950] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.742,950] <dbg> app: main: Waiting 120 seconds for voltage to stabilize
    00> [00:02:00.743,072] <err> app: Device bmi270@68 is not ready

    and:

    00> [00:00:00.733,551] <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.734,375] <dbg> app: main: Starting BMI270 sensor example, test number 1
    00> [00:00:00.734,405] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.734,405] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.734,405] <dbg> app: main: Waiting 300 seconds for voltage to stabilize
    00> [00:05:00.734,527] <err> app: Device bmi270@68 is not ready

    change_gpio_voltage only does it the first time if it's not at the right setting. 

    However when I put k_sleep(K_SECONDS(2)); in it works:

    static int bmi270_init(const struct device *dev)
    {
    	int ret;
    	struct bmi270_data *data = dev->data;
    	uint8_t chip_id;
    	uint8_t soft_reset_cmd;
    	uint8_t init_ctrl;
    	uint8_t msg;
    	uint8_t tries;
    	uint8_t adv_pwr_save;
    k_sleep(K_SECONDS(2));
    	ret = bmi270_bus_check(dev);
    	if (ret < 0) {
    		LOG_ERR("Could not initialize bus");
    		return ret;
    	}
    	
    	...
    }

    Obviously, that's not a solution, but I hope it helps determine the problem and solution. Is there any way to delay the init?

    I've even tried this:

    static int set_volttage_early(void)
    {
    	int sleep_time = 2; // seconds
    	LOG_DBG("Setting GPIO voltage early in boot process");
        int rt = change_gpio_voltage(UICR_VREGHVOUT_VREGHVOUT_3V0);
    	LOG_DBG("sleeping for %d seconds", sleep_time);
    	k_sleep(K_SECONDS(sleep_time));
    	return rt;
    }
    
    SYS_INIT(set_volttage_early, POST_KERNEL, 1); 

    But it doesn't work (I put debug statements in the init to show order):

    00> [00:00:00.719,299] <dbg> app: set_volttage_early: Setting GPIO voltage early in boot process
    00> [00:00:00.719,299] <inf> voltage_mgr: change_gpio_voltage: REGOUT = 0xfffffffc
    00> [00:00:00.719,329] <inf> voltage_mgr: change_gpio_voltage: target voltage is 4
    00> [00:00:00.719,329] <inf> voltage_mgr: Target voltage already set. No action needed.
    00> [00:00:00.719,329] <dbg> app: set_volttage_early: sleeping for 2 seconds
    00> [00:00:02.719,696] <err> voltage: setup: -134
    00> [00:00:02.719,726] <dbg> bmi270: bmi270_init: Initializing BMI270 sensor
    00> *** Booting nRF Connect SDK v2.9.1-60d0d6c8d42d ***
    00> *** Using Zephyr OS v3.7.99-ca954a6216c9 ***
    00> [00:00:02.720,520] <dbg> app: main: Starting BMI270 sensor example, test number 2
    00> [00:00:02.720,550] <dbg> app: main: Waiting 1 seconds for voltage to stabilize
    00> [00:00:03.720,642] <err> app: Device bmi270@68 is not ready

    Seems strange I can delay before the init, but it only works in the init.

Children
No Data
Related