[SPI] not device ready

Hi there,

SPI device is not ready.

What's wrong?

NCS version: v2.6.1

&spi1 {
    compatible = "nordic,nrf-spi";
    status = "okay";
    pinctrl-0 = <&spi1_default>;
    pinctrl-names = "default";
    max-frequency = <DT_FREQ_M(24)>;
    cs-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
    
    icm42670p: icm42670p@0 {
        compatible = "invensense,icm42670";
        reg = <0>;
        spi-max-frequency = <DT_FREQ_M(24)>;
        accel-hz = <1600>;
        accel-fs = <16>;
        gyro-hz = <1600>;
        gyro-fs = <2000>;
    };
};


&pinctrl {
	uart0_default: uart0_default {
		group1 {
			psels = <NRF_PSEL(UART_TX, 0, 6)>, <NRF_PSEL(UART_RX, 0, 8)>;
		};
	};

	i2c0_default: i2c0_default {

		group1 {
			psels = <NRF_PSEL(TWIM_SCL, 0, 17)>, <NRF_PSEL(TWIM_SDA, 0, 18)>;
			nordic,invert;
			bias-pull-up;
		};
	};

	spi1_default: spi1_default {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 14)>,
					<NRF_PSEL(SPIM_MOSI, 0, 13)>,
					<NRF_PSEL(SPIM_MISO, 0, 12)>;
		};
	};
};

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/spi.h>

// #include <zephyr/drivers/gpio.h>
// #include <zephyr/logging/log.h>
// #include <zephyr/device.h>
// #include <zephyr/drivers/uart/cdc_acm.h>
// #include <zephyr/drivers/uart.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/settings/settings.h>

#include "lib/bluetooth_manager/bluetooth_manager.h"
#include "lib/gpio/gpio.h"
#include "lib/magneto/magneto.h"

#define ICM42670P_NODE DT_NODELABEL(icm42670p)
const struct device *icm42670p_spec = DEVICE_DT_GET(ICM42670P_NODE);

struct spi_config spi_cfg = {
    .frequency = DT_PROP(ICM42670P_NODE, spi_max_frequency),
    .operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA,
    .slave = DT_REG_ADDR(ICM42670P_NODE),
    .cs = NULL,
};

#define ICM42670P_WHO_AM_I_REG 0x75

void read_icm42670p_who_am_i(void)
{
    uint8_t tx_buffer[2] = {ICM42670P_WHO_AM_I_REG | 0x80, 0x00}; // 0x80 to set the read bit
    uint8_t rx_buffer[2] = {0};

    struct spi_buf tx_buf = {
        .buf = tx_buffer,
        .len = sizeof(tx_buffer),
    };
    struct spi_buf rx_buf = {
        .buf = rx_buffer,
        .len = sizeof(rx_buffer),
    };
    struct spi_buf_set tx = {
        .buffers = &tx_buf,
        .count = 1,
    };
    struct spi_buf_set rx = {
        .buffers = &rx_buf,
        .count = 1,
    };

    int ret = spi_transceive(icm42670p_spec, &spi_cfg, &tx, &rx);
    if (ret < 0)
    {
        printk("SPI transaction failed: %d\n", ret);
    }
    else
    {
        printk("ICM42670P WHO_AM_I: 0x%02x\n", rx_buffer[1]);
    }
}

int main(void) {
    int err;

    // Initialize the Bluetooth Subsystem
    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return 0;
    }

    printk("Bluetooth initialized\n");

    if (IS_ENABLED(CONFIG_SETTINGS)) {
        settings_load();
    }

    // Start advertising
    err = start_bluetooth_advertise();
    if (err) {
        printk("Advertising failed to start (err %d)\n", err);
        return 0;
    }

    printk("Advertising successfully started\n");

    // Check if the ICM42670P device is ready
    if (!device_is_ready(icm42670p_spec)) {
        printk("ICM42670P device not ready\n");
        return 0;
    }

    // Read WHO_AM_I register
    read_icm42670p_who_am_i();

    return 0;
}

  • I followed your instruction to use zephyr official driver for icm-42688.

    Setting up the soft-reset and clear reset flag done successfully.

    Especially reading the reset flag is done through MISO pin and it's done properly.

    Hmm. Very interesting. I hope I am making a silly mistake but I can't figure it out. Please help Upside down

    #include <zephyr/types.h>
    #include <zephyr/drivers/gpio.h>0
    #include <zephyr/drivers/spi.h>
    #include <zephyr/sys/util.h>
    #include <zephyr/drivers/sensor.h> // sensor driver
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS 1000
    #define ICM42688P_SPI_NODE DT_NODELABEL(icm42688)
    #define ICM42670P_SPI_CS_DT_SPEC SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_icm42688))
    
    int main(void)
    {
    	printk("sensor: Hello.\n");
    
    	const struct device *spi_dev = DEVICE_DT_GET(ICM42688P_SPI_NODE);
    	const struct gpio_dt_spec spim_cs_gpio = ICM42670P_SPI_CS_DT_SPEC;
    	if (!device_is_ready(spi_dev))
    	{
    		printk("sensor: device not ready.\n");
    		return 0;
    	}
    	else
    	{
    		printk("sensor: device ready.\n");
    	}
    
    	// while (true)
    	// {
    
    	// 	k_sleep(K_MSEC(1000));
    	// }
    
    	return 0;
    }

  • Thank you. What is the gpio voltage you are running? I just noticed that it was lower then the STM you compared it to. 

    Regards

    Runar

  • As you mentioned, GPIO HIGH level Voltage of SPI Pins are
    nRF52-DK: 3.15V
    STM F301RB: 3.59V

    Hmm interesting. Do you think this can cause the issue?

  • Hi

    I had another look at our application. Instead of running with 2x buffers, could you try the implementation we did on SPI lesson on devacademy

    For some reason it looks like you are getting a "1" on the MOSI line after sending the register address 

    Regards

    Runar

Related