ADXL363 Sensor SPI2 Devicetree NRF9160DK :Only spi nodes accepted in /soc/peripheral@40000000/spi@a000/

Hi,

I am using nrf Connected SDK v2.6.2 on windows 10. I try to create a blank application project for the device ADXL363 on SPI2 bus on the nRF9160DK board.

I basically followed the sample here: https://github.com/aaron-mohtar-co/Lemon-IoT-LTE-nRF9160/tree/main/Examples/spi_sensor 

The error message shown as below:

Main.c

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(adxl363_driver, CONFIG_LOG_DEFAULT_LEVEL);

/* Get ADXL363 SPI device */

const struct device *adxl_dev = DEVICE_DT_GET_ANY(adi_adxl363);

/* SPI Configuration */
struct spi_config spi_cfg = {
    .frequency = 5000000,  // 5 MHz SPI clock
    .operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA,
    .slave = 0,
};

/* Read ADXL363 Device ID */
void adxl363_read_device_id(void) {
    uint8_t tx_data[2] = {0x0B, 0x00};  // Read command for Device ID
    uint8_t rx_data[2] = {0};

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

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

    int ret = spi_transceive(adxl_dev, &spi_cfg, &tx, &rx);
    if (ret == 0) {
        LOG_INF("ADXL363 Device ID: 0x%02X", rx_data[1]);
        if (rx_data[1] == 0xAD) {
            LOG_INF("ADXL363 Connection Verified!");
        } else {
            LOG_ERR("Invalid Device ID! Expected 0xAD but got 0x%02X. Check Wiring!", rx_data[1]);
        }
    } else {
        LOG_ERR("SPI Communication Failed!");
    }
}

void main(void) {
    LOG_INF("Initializing ADXL363...");

    if (!device_is_ready(adxl_dev)) {
        LOG_ERR("ADXL363 device not ready! Check DeviceTree and wiring.");
        return;
    }

    LOG_INF("ADXL363 device found. Reading Device ID...");
    adxl363_read_device_id();
}

Devicetree

nrf9160dk_nrf9160_ns.overlay

&pinctrl {
    spi2_default: spi2_default {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 0, 16)>,
                    <NRF_PSEL(SPIM_MISO, 0, 18)>,
                    <NRF_PSEL(SPIM_MOSI, 0, 17)>;
        };
    };

    spi2_sleep: spi2_sleep {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 0, 16)>,
                    <NRF_PSEL(SPIM_MISO, 0, 18)>,
                    <NRF_PSEL(SPIM_MOSI, 0, 17)>;
        };
    };
};

&spi2 {
    compatible = "nordic,nrf-spim";
    status = "okay";

    /* Define CS Pin */
    cs-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;

    /* Define Pin Control */
    pinctrl-0 = <&spi2_default>;
    pinctrl-1 = <&spi2_sleep>;
    pinctrl-names = "default", "sleep";

    /* ADXL363 Sensor */
    adxl363: adxl363@0 {
        compatible = "adi,adxl363"; // Use the correct driver binding
        reg = <0>;  // Chip Select 0
        spi-max-frequency = <5000000>;  // 5MHz SPI communication speed
        label = "ADXL363";

        int1-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;  // INT1 -> P0.19
    };
};

The blank application has no \dts directory. So, I created the binding file....

\dts\bindings\sensor\adi,adxl363.yaml

description: Analog Devices ADXL363 3-Axis Accelerometer

compatible: "adi,adxl363"

include: spi-device.yaml

properties:
  reg:
    type: int
    required: true
    description: "Chip Select (CS) number"

  spi-max-frequency:
    type: int
    required: true
    description: "Maximum SPI frequency in Hz"

  int1-gpios:
    type: phandle-array
    required: false
    description: "GPIO connected to the INT1 pin"

  int2-gpios:
    type: phandle-array
    required: false
    description: "GPIO connected to the INT2 pin"

How can I define the ADXL363 devicetree via SPI2 properly?

  • Hello,

    How can I define the ADXL363 devicetree via SPI2 properly?

    I'm not really sure what you mean by this question. It looks to me like the ADXL363 driver is not implemented in the nordic SDK. So it seems you would need to implement a custom driver for this, and include it in your build.

  • Hello,

    implemented the ADXL363 driver as.......

    ADXL363.c

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/spi.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/drivers/sensor.h>
    #include "adxl363.h"
    
    LOG_MODULE_REGISTER(adxl363, CONFIG_SENSOR_LOG_LEVEL);
    
    /* ADXL363 Register Addresses */
    #define ADXL363_REG_DEVID_AD     0x00  // Device ID register
    #define ADXL363_EXPECTED_ID      0xAD  // Expected Device ID
    #define ADXL363_CMD_READ         0x0B  // Read command
    
    /* Device Data Structure */
    struct adxl363_data {
        struct spi_config spi_cfg;
        const struct device *spi_dev;
    };
    
    /* Function to Read a Register */
    static int adxl363_read_register(const struct device *dev, uint8_t reg, uint8_t *value) {
        struct adxl363_data *data = dev->data;
        uint8_t tx_buf[2] = {ADXL363_CMD_READ, reg};
        uint8_t rx_buf[2] = {0};
    
        struct spi_buf tx = {.buf = tx_buf, .len = sizeof(tx_buf)};
        struct spi_buf_set tx_set = {.buffers = &tx, .count = 1};
    
        struct spi_buf rx = {.buf = rx_buf, .len = sizeof(rx_buf)};
        struct spi_buf_set rx_set = {.buffers = &rx, .count = 1};
    
        int ret = spi_transceive(data->spi_dev, &data->spi_cfg, &tx_set, &rx_set);
        if (ret < 0) {
            LOG_ERR("Failed to read ADXL363 register 0x%02X", reg);
            return ret;
        }
    
        *value = rx_buf[1];
        return 0;
    }
    
    /* Sensor Driver API Structure */
    static const struct sensor_driver_api adxl363_driver_api = {
        .sample_fetch = NULL,  // Implement fetch function if needed
    };
    
    /* Device Initialization Function */
    static int adxl363_init(const struct device *dev) {
        struct adxl363_data *data = dev->data;
        LOG_INF("Initializing ADXL363 Sensor...");
    
        if (!device_is_ready(data->spi_dev)) {
            LOG_ERR("SPI device not ready");
            return -ENODEV;
        }
    
        return 0;
    }
    
    /* Define Device Data */
    static struct adxl363_data adxl363_driver_data = {
        .spi_cfg = {
            .frequency = 5000000,
            .operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA,
            .slave = 0,
        },
    };
    
    /* Register the Device */
    DEVICE_DT_DEFINE(DT_NODELABEL(adxl363), adxl363_init, NULL, &adxl363_driver_data, NULL,
                     POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &adxl363_driver_api);

    ADXL363.h

    #ifndef ZEPHYR_DRIVERS_SENSOR_ADXL363_H_
    #define ZEPHYR_DRIVERS_SENSOR_ADXL363_H_
    
    #include <zephyr/device.h>
    #include <zephyr/drivers/spi.h>
    
    /* Structure to hold ADXL363 sensor data */
    struct adxl363_data {
        struct spi_config spi_cfg;
        const struct device *spi_dev;
    };
    
    #endif /* ZEPHYR_DRIVERS_SENSOR_ADXL363_H_ */

     

    Updated nrf9160dk_nrf9160_ns.overlay

    &spi2 {
        compatible = "nordic,nrf-spim";
        status = "okay";
    
        /* Define Pin Control */
        pinctrl-0 = <&spi2_default>;
        pinctrl-1 = <&spi2_sleep>;
        pinctrl-names = "default", "sleep";
    
        /* Define CS Pin */
        cs-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
    
        /* ADXL363 Sensor */
        adxl363: adxl363@0 {
            compatible = "adi,adxl363"; // Use the correct driver binding
            reg = <0>;  // Chip Select 0
            spi-max-frequency = <5000000>;  // 5MHz SPI communication speed
            //int1-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;  // INT1 -> P0.19
        };
    };
    
    &pinctrl {
        spi2_default: spi2_default {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 0, 16)>,
                        <NRF_PSEL(SPIM_MOSI, 0, 17)>,
                        <NRF_PSEL(SPIM_MISO, 0, 18)>;
            };
        };
    
        spi2_sleep: spi2_sleep {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 0, 16)>,  
                        <NRF_PSEL(SPIM_MOSI, 0, 17)>,
                        <NRF_PSEL(SPIM_MISO, 0, 18)>;
                low-power-enable;
            };
        };
    };

    Updated Main.c

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/spi.h>
    #include <zephyr/logging/log.h>
    
    LOG_MODULE_REGISTER(adxl363_test, CONFIG_LOG_DEFAULT_LEVEL);
    
    /* Get the ADXL363 device from DeviceTree */
    const struct device *adxl_dev = DEVICE_DT_GET(DT_NODELABEL(adxl363));
    //const struct device *adxl_dev = DEVICE_DT_GET_ANY(adi_adxl363);
    
    /* ADXL363 Register Addresses */
    #define ADXL363_REG_DEVID_AD     0x00  // Device ID register
    #define ADXL363_EXPECTED_ID      0xAD  // Expected Device ID
    #define ADXL363_CMD_READ         0x0B  // Read command
    
    /* Read a Register from ADXL363 */
    static int adxl363_read_register(const struct device *dev, uint8_t reg, uint8_t *value) {
        uint8_t tx_buf[2] = {ADXL363_CMD_READ, reg};  // Send Read Command + Register Address
        uint8_t rx_buf[2] = {0};  // Buffer to store the response
    
        struct spi_buf tx = {.buf = tx_buf, .len = sizeof(tx_buf)};
        struct spi_buf_set tx_set = {.buffers = &tx, .count = 1};
    
        struct spi_buf rx = {.buf = rx_buf, .len = sizeof(rx_buf)};
        struct spi_buf_set rx_set = {.buffers = &rx, .count = 1};
    
        int ret = spi_transceive(dev, NULL, &tx_set, &rx_set);
        if (ret < 0) {
            LOG_ERR("Failed to read ADXL363 register 0x%02X", reg);
            return ret;
        }
    
        *value = rx_buf[1];  // The received data is in rx_buf[1]
        return 0;
    }
    
    /* Verify ADXL363 by Checking Device ID */
    static void adxl363_verify_device(void) {
        if (!device_is_ready(adxl_dev)) {
            LOG_ERR("ADXL363 device not ready! Check DeviceTree and wiring.");
            return;
        }
    
        uint8_t device_id;
        if (adxl363_read_register(adxl_dev, ADXL363_REG_DEVID_AD, &device_id) == 0) {
            if (device_id == ADXL363_EXPECTED_ID) {
                LOG_INF("ADXL363 Device ID Verified: 0x%02X", device_id);
            } else {
                LOG_ERR("Invalid ADXL363 Device ID! Expected 0xAD, but got 0x%02X", device_id);
            }
        } else {
            LOG_ERR("SPI Communication Failed!");
        }
    }
    
    /* Main Test Function */
    void main(void) {
        LOG_INF("Initializing ADXL363 Test...");
    
        adxl363_verify_device();
    }

    adi,adxl363.yaml and location no changed!

     

    However, I still cannot make it fully compiled with the ERROR MESSAGE:

    C:/ncs/v2.6.2/zephyr/cmake/modules/dts.cmake:268 (message):", "source": "cmake", "startLineNumber": 268, "startColumn": 1

    It looks like the compiler cannot find the adi,adxl363.yaml file? or Any syntax gone wrong in nrf9160dk_nrf9160_ns.overlay?! 

  • The following essential files....

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.20.0)
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    
    project(adx1363_v2_6)
    
    zephyr_library()
    zephyr_library_sources(drivers/sensor/adxl363.c)
    
    target_sources(app PRIVATE src/main.c)
    set(DTC_EXTRA_CPPFLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/dts/bindings/sensor/")

    prj.conf

    CONFIG_SPI=y
    CONFIG_SENSOR=y
    CONFIG_GPIO=y
    CONFIG_LOG=y
    CONFIG_LOG_DEFAULT_LEVEL=4

Related