This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI Master chip select in .overlay

Trying to convert a working sample for a BME280 sensor from I2C to SPI

nrfConnect 1.4 on nrf9160-DK

After looking at other SPI examples and noting the syntax I thought the .overlay should be like this

```

&spi3 {
  status = "okay";
  sck-pin = <10>;
  mosi-pin = <11>;
  miso-pin = <12>;
  cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;

  bme280@76 {
    compatible = "bosch,bme280";
    reg = <0x76>;
    spi-max-frequency = <4000000>;
    label = "BME280";
  };
};

&uart3 {
  status = "disabled";
};

```

prj.conf is:

```

CONFIG_SENSOR=y
CONFIG_SPI=y
CONFIG_SPI_3=y
CONFIG_BME280=y
CONFIG_SPI_NRFX=y

CONFIG_MAIN_STACK_SIZE=4096
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=4

```

If I take out the cs-gpios line this compiles but understandably throws a runtime error.

```

[00:00:00.000,030] [0m<dbg> BME280.bme280_init: initializing BME280[0m
[00:00:00.000,030] [0m<dbg> BME280.bme280_spi_init: no chip select set[0m
[00:00:00.000,030] [0m<inf> spi_nrfx_spim: CS control inhibited (no GPIO device)[0m
[00:00:00.000,091] [0m<dbg> BME280.bme280_chip_init: bad chip id 0xff[0m
[00:00:00.000,091] [0m<dbg> BME280.bme280_init: BME280 failed[0m

```

But with that line in place west produces all sorts of errors:

```

nrf9160dk_nrf9160ns.dts.pre.tmp:357.32-361.5: Warning (simple_bus_reg): /soc/cryptocell-sw: missing or empty reg/ranges property

nrf9160dk_nrf9160ns.dts.pre.tmp:56.42-68.3: Warning (unique_unit_address_if_enabled): /soc/peripheral@40000000/flash-controller@39000: duplicate unit-address (also used in node /soc/peripheral@40000000/kmu@39000)

nrf9160dk_nrf9160ns.dts.pre.tmp:305.19-311.3: Warning (unique_unit_address_if_enabled): /soc/peripheral@40000000/clock@5000: duplicate unit-address (also used in node /soc/peripheral@40000000/power@5000)

-- Generated zephyr.dts: .../ncs/zephyr/samples/sensor/bme280spi/build/zephyr/zephyr.dts

-- Generated devicetree_unfixed.h: .../ncs/zephyr/samples/sensor/bme280spi/build/zephyr/include/generated/devicetree_unfixed.h

```

etc.etc.

Is the above .overlay correct for an SPI device?

BTW. the only other use of cs-gpios I found in this SDK was for the spi_flash_at45 sample which, for other reasons, does not seem to compile cleanly.

OK. I moved on a little after looking here https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.4.0/zephyr/guides/dts/howtos.html#set-devicetree-overlays

This shows a different way to specify the chip select.  So my new .overlay compiles OK but still throws the same runtime error

 ```

&spi3 {
  status = "okay";
  sck-pin = <11>;
  mosi-pin = <10>;
  miso-pin = <12>;

  bme280@13 {
    compatible = "bosch,bme280";
    reg = <13>;
    spi-max-frequency = <4000000>;
    label = "BME280";
  };
};

&uart3 {
  status = "disabled";
};

```

Parents
  • Add a file nrf9160d_nrf9160ns.overlay in zephyr\samples\sensor\bme280\boards with the following content:

    &spi3 {
        status = "okay";
        sck-pin = <10>;
        mosi-pin = <11>;
        miso-pin = <12>;
        cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
      
        bme280@0 {
          compatible = "bosch,bme280";
          reg = <0x00>;
          //reg = <0x76>;
          spi-max-frequency = <4000000>;
          label = "BME280";
        };
      };
      
      &uart3 {
        status = "disabled";
      };

    In addition, set zephyr\samples\sensor\bme280\prj.conf to:

    CONFIG_SPI=y
    CONFIG_I2C=n
    CONFIG_SENSOR=y
    CONFIG_BME280=y

    I was able to build the bme280 successfully with these modifications. I have not tested it, since I don't have a BME280 at hand at the moment.


    Some explanations:

    When using SPI, the field bme280@{this field} (and reg = <{this field}>)has a different meaning. In I2C, you initiate communication with a device by sending the address on the line, while in SPI you enable the CS line for the particular device. Then it doesn't make sense to use the address 0x76 or 13 in the dts, instead the field represent the chip select line number. These lines from DTS Guide --> Important properties sums it up nicely:

    If you only add one SPI based sensor inside an spi node, you can use use the value 0, however if you add more devices do it like it's done in nrf/boards/arm/thingy91_nrf9160/thingy91_nrf9160_common.dts.

    The amount of inputs given to cs-gpios in the SPI node has to correspond to the amount of sub-devices.

    Best regards,

    Simon

  • Thx Simon,

    I can also build with the above.

    At runtime I get:

    ```

    prepare to jump to Non-Secure image.
    [00:00:00.000,030] [0m<dbg> BME280.bme280_init: initializing BME280[0m
    [00:00:00.000,122] [0m<dbg> BME280.bme280_chip_init: ID OK[0m
    [00:00:00.001,647] [0m<dbg> BME280.bme280_init: BME280 OK[0m
    *** Booting Zephyr OS build v2.4.0-ncs1 ***
    [00:00:00.001,708] [0m<dbg> os.k_sched_unlock: scheduler unlocked (0x200102b0:0)[0m
    Starting BME280 test with SPI
    No device "BME280" found (); did initialization fail?

    ```

    I have double-checked the connections.

    Source:

    ```

    /*
    * Copyright (c) 2012-2014 Wind River Systems, Inc.
    * SPDX-License-Identifier: Apache-2.0
    * bme280 example converted to SPI
    */

    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/sensor.h>

    #define BME280 DT_INST(0, bosch_bme280)
    //#undef DT_BOSCH_BME280_BUS_I2C
    //#define DT_BOSCH_BME280_BUS_SPI

    #if DT_NODE_HAS_STATUS(BME280, okay)
    #define BME280_LABEL DT_LABEL(BME280)
    #else
    #error Your devicetree has no enabled nodes with compatible "bosch,bme280"
    #define BME280_LABEL "<none>"
    #endif

    void main(void)
    {
    int i;
    printk("Starting BME280 test with SPI \n");

    const struct device *dev = device_get_binding("BME280_LABEL");
    if (dev == NULL) {
    printk("No device \"%s\" found (); did initialization fail?\n", BME280_LABEL);
    return;
    } else {
    printk("Found device \"%s\"\n", BME280_LABEL);
    }

    for (i = 1; i < 2; i++) {
    struct sensor_value temp, press, humidity;

    sensor_sample_fetch(dev);
    sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
    sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);
    sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity);


    printk("Environmental Temperature: %d.%02d Degrees Cent. \n", temp.val1, temp.val2);
    printk("Environmental Pressure: %d.%02d Bar \n", press.val1, press.val2);
    printk("Environmental Humidity: %d.%02d per/cent \n", humidity.val1, humidity.val2);

    }
    }

    ```

    Any comments pls?

  • Try changing device_get_binding("BME280_LABEL") to device_get_binding(BME280_LABEL) (without the quotation marks "").

    You could also just simply do device_get_binding("BME280") (use the label set in the overlay file) directly to make sure it works.


    Additional comments:

    If that doesn't work, it is helpful to look at the file build/zephyr/zephyr.dts to see if the dts output is generated correctly. 

    Sometimes the reason for device_get_binding() failing is because the associated init function has failed. The init function for the bme280 driver you're using is bme280_init()

    Best regards,

    Simon

Reply
  • Try changing device_get_binding("BME280_LABEL") to device_get_binding(BME280_LABEL) (without the quotation marks "").

    You could also just simply do device_get_binding("BME280") (use the label set in the overlay file) directly to make sure it works.


    Additional comments:

    If that doesn't work, it is helpful to look at the file build/zephyr/zephyr.dts to see if the dts output is generated correctly. 

    Sometimes the reason for device_get_binding() failing is because the associated init function has failed. The init function for the bme280 driver you're using is bme280_init()

    Best regards,

    Simon

Children
Related