[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;
}

Parents
  • Hi 

    Could you enable logging and build your application with optimized for debug and post the log?

    Could you also show me your overlay?

    Regards

    Runar

  • I solved the issue with nRF SPI master/slave example.

    But I faced another issue.

     I am using a sensor with its WHO AM I register value is 0x47.

    However, I keep receiving data from it 0x4C.

    To verify that the sensor unit has no issue, I tested with STM32.

    Please check it below oscilloscope waveform and decode value.

    [STM32]: sensor response with correct value

    [nRF52-DK]: sensor response with wrong value

    So we can conclude that the sensor has no problem. I used the same jumber cables and same oscilloscope setup.

    Here's the device tree and C code

    icm42670p: &spi2 {
    	compatible = "nordic,nrf-spi";
    	// compatible = "nordic,nrf-spim";
    	status = "okay";
    	pinctrl-0 = <&spi1_default>;
    	pinctrl-names = "default";
    	cs-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
    	overrun-character = <1>;
    	reg_icm42670p: reg_icm42670p@0 {
    		reg = <0>;
    	};
    
    	max-frequency = <DT_FREQ_M(8)>;
    };

    /**
     * The first bit of the first byte contains the Read/Write bit and indicates the Read (1) operation
     * The first bit of the first byte contains the Read/Write bit and indicates the Write (0) operation.
     */
    int spi_read_register(const struct device *spi_dev, const struct spi_config *spi_cfg, uint8_t address, uint8_t *data, size_t len)
    {
        uint8_t tx_buf = REG_SPI_READ_BIT | address; // Set read bit
        printk("tx_buf: %x\n", tx_buf);
    
        struct spi_buf tx_bufs = {
            .buf = &tx_buf,
            .len = 1,
        };
    
        struct spi_buf_set tx = {
            .buffers = &tx_bufs,
            .count = 1
        };
        
        // size determined by tx buffer size
        struct spi_buf rx_buf[2] = {
            {
                .buf = NULL,
                // .len = 1,
                .len = sizeof(tx_buf),
            },
            {
                .buf = data,
                .len = len,
            }};
    
        const struct spi_buf_set rx = {
            .buffers = rx_buf,
            // .count = ARRAY_SIZE(rx_buf),
            .count = 2,
            .count = 2,
        };
    
        int ret = spi_transceive(spi_dev, spi_cfg, &tx, &rx);
        if (ret == 0)
        {
            printk("Read from address: 0x%x, received data: 0x%x\n", address, *data);
        }
        else
        {
            printk("SPI transceive error: %d\n", ret);
        }
    
        return ret;
    }

Reply
  • I solved the issue with nRF SPI master/slave example.

    But I faced another issue.

     I am using a sensor with its WHO AM I register value is 0x47.

    However, I keep receiving data from it 0x4C.

    To verify that the sensor unit has no issue, I tested with STM32.

    Please check it below oscilloscope waveform and decode value.

    [STM32]: sensor response with correct value

    [nRF52-DK]: sensor response with wrong value

    So we can conclude that the sensor has no problem. I used the same jumber cables and same oscilloscope setup.

    Here's the device tree and C code

    icm42670p: &spi2 {
    	compatible = "nordic,nrf-spi";
    	// compatible = "nordic,nrf-spim";
    	status = "okay";
    	pinctrl-0 = <&spi1_default>;
    	pinctrl-names = "default";
    	cs-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
    	overrun-character = <1>;
    	reg_icm42670p: reg_icm42670p@0 {
    		reg = <0>;
    	};
    
    	max-frequency = <DT_FREQ_M(8)>;
    };

    /**
     * The first bit of the first byte contains the Read/Write bit and indicates the Read (1) operation
     * The first bit of the first byte contains the Read/Write bit and indicates the Write (0) operation.
     */
    int spi_read_register(const struct device *spi_dev, const struct spi_config *spi_cfg, uint8_t address, uint8_t *data, size_t len)
    {
        uint8_t tx_buf = REG_SPI_READ_BIT | address; // Set read bit
        printk("tx_buf: %x\n", tx_buf);
    
        struct spi_buf tx_bufs = {
            .buf = &tx_buf,
            .len = 1,
        };
    
        struct spi_buf_set tx = {
            .buffers = &tx_bufs,
            .count = 1
        };
        
        // size determined by tx buffer size
        struct spi_buf rx_buf[2] = {
            {
                .buf = NULL,
                // .len = 1,
                .len = sizeof(tx_buf),
            },
            {
                .buf = data,
                .len = len,
            }};
    
        const struct spi_buf_set rx = {
            .buffers = rx_buf,
            // .count = ARRAY_SIZE(rx_buf),
            .count = 2,
            .count = 2,
        };
    
        int ret = spi_transceive(spi_dev, spi_cfg, &tx, &rx);
        if (ret == 0)
        {
            printk("Read from address: 0x%x, received data: 0x%x\n", address, *data);
        }
        else
        {
            printk("SPI transceive error: %d\n", ret);
        }
    
        return ret;
    }

Children
Related