Dear community,
we're having trouble connecting our thingy91x to the BMI270 via the nRF5340 using SPI. We've tried many similar cases without success.
Here's our setup: Visual Studio Code (1.105) with nRF Connect SDK and Toolchain (V3.1.1)
The app.overlay:
&spi3 {
status = "okay";
bmi270@2 {
status = "okay";
};
};
the prj.conf:
# USB CDC ACM Configuration CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_PRODUCT="Thingy91x BMI270 Test" CONFIG_USB_CDC_ACM=y # Serial settings CONFIG_SERIAL=y # Interface Configuration CONFIG_GPIO=y CONFIG_SPI=y #CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=8 #CONFIG_SPI_ASYNC=n # Sensor Configuration CONFIG_SENSOR=y CONFIG_BMI270=y #CONFIG_BMI270_TRIGGER_NONE=y # Console configuration CONFIG_CONSOLE=y # Logging Configuration CONFIG_LOG=y CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_STDOUT_CONSOLE=y CONFIG_RTT_CONSOLE=y CONFIG_USE_SEGGER_RTT=y CONFIG_LOG_BACKEND_RTT=y
The main.c file was generated from the original bmi270 sample using the thingy91x/nrf5340/cpuapp template.
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/drivers/uart/cdc_acm.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#define SLEEP_TIME_MS 500
/* USB CDC ACM device */
#define USB_DEVICE_NAME CONFIG_USB_DEVICE_PRODUCT
static const struct device *usb_dev;
static char data[128];
/* Helper function for formatted output to USB CDC ACM */
static void cdc_printf(const char *format, ...) {
va_list args;
va_start(args, format);
vsnprintf(data, sizeof(data), format, args);
va_end(args);
for (int i = 0; i < strlen(data); i++) {
uart_poll_out(usb_dev, data[i]);
}
}
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
int main(void)
{
// Initialize and blink LED 3 times
int ret;
if (!gpio_is_ready_dt(&led)) {
return 0;
}
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
int i = 7;
while (i > 0) {
ret = gpio_pin_toggle_dt(&led);
if (ret < 0) {
return 0;
}
k_msleep(SLEEP_TIME_MS);
i--;
}
////////////////////
/* Enable USB CDC */
ret = usb_enable(NULL);
if (ret != 0) {
return 0;
}
/* Wait for USB CDC to be ready */
k_sleep(K_MSEC(1000));
/* Get USB CDC ACM device */
usb_dev = DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart);
if (!device_is_ready(usb_dev)) {
return 0;
}
/* Write initial test message */
cdc_printf("\r\nUSB CDC ACM device ready.\r\n");
/////////////////////////////////////////
// Setup and read data from BMI270 sensor
cdc_printf("\r\nChecking BMI270 device tree status...\r\n");
cdc_printf("accelerometer_hp node exists: %d\r\n", DT_NODE_EXISTS(DT_NODELABEL(accelerometer_hp)));
cdc_printf("accelerometer_hp node status: %d\r\n", DT_NODE_HAS_STATUS(DT_NODELABEL(accelerometer_hp), okay));
cdc_printf("spi3 node exists: %d\r\n", DT_NODE_EXISTS(DT_NODELABEL(spi3)));
cdc_printf("spi3 node status: %d\r\n", DT_NODE_HAS_STATUS(DT_NODELABEL(spi3), okay));
// Get SPI device first
const struct device *const spi = DEVICE_DT_GET(DT_NODELABEL(spi3));
if (!device_is_ready(spi)) {
cdc_printf("SPI3 is not ready!\r\n");
return 0;
}
cdc_printf("SPI3 is ready\r\n");
// Now try to get BMI270
const struct device *const dev_bmi = DEVICE_DT_GET(DT_NODELABEL(accelerometer_hp));
if (dev_bmi == NULL) {
cdc_printf("Could not get BMI270 device!\r\n");
return 0;
}
cdc_printf("Got BMI270 device: %s\r\n", dev_bmi->name);
struct sensor_value acc[3], gyr[3], val;
struct sensor_value full_scale, sampling_freq, oversampling;
if (!device_is_ready(dev_bmi)) {
int ret;
cdc_printf("BMI270 is not ready, starting basic initialization...\r\n");
// Power-up time - wait 2ms after power-up
k_sleep(K_MSEC(2));
cdc_printf("Power-up delay complete\r\n");
// Step 1: Dummy read to switch from I²C to SPI
struct sensor_value chip_id = {0};
ret = sensor_attr_get(dev_bmi, SENSOR_CHAN_ALL,
SENSOR_ATTR_CONFIGURATION, &chip_id);
cdc_printf("Dummy read: err=%d, ID=0x%02x\r\n",
ret, (uint8_t)chip_id.val1);
// Step 2: Try to read Chip ID (should be 0x24)
ret = sensor_attr_get(dev_bmi, SENSOR_CHAN_ALL,
SENSOR_ATTR_CONFIGURATION, &chip_id);
cdc_printf("Chip ID read: err=%d, ID=0x%02x (should be 0x24)\r\n",
ret, (uint8_t)chip_id.val1);
return 0;
}
cdc_printf("BMI270 is ready and initialized!\r\n");
The following Flash command was used with a jlink probe:
nrfutil device program --firmware .\merged.hex --traits jlink --x-family nrf53 --core Application
The Output is:
Checking BMI270 device tree status...
accelerometer_hp node exists: 1
accelerometer_hp node status: 1
spi3 node exists: 1
spi3 node status: 1
SPI3 is ready
Got BMI270 device: bmi270@2
BMI270 is not ready, starting basic initialization...
Power-up delay complete
Dummy read: err=-88, ID=0x00
Chip ID read: err=-88, ID=0x00 (should be 0x24)
We also tried a raw SPI transceive: timeout.
Any help getting the bmi270 working is greatly appreciated! :-)