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?

Parents
  • 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

Reply
  • 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

Children
No Data
Related