When using the nRF Connect SDK, a common issue to encounter are devicetree errors.
The devicetree is a hierarchical data structure used to describe hardware, such as a development kit, SoC, SiP or module. The devicetree defines everything ranging from the GPIO configurations of the LEDs on a development kit to the memory-mapped locations of peripherals.
It is used in two main ways:
Devicetree was covered in Lesson 2 of the nRF Connect SDK Fundamental course.
Here are some common errors you might face while working with the devicetree.
Unlike Kconfig symbols, the devicetree.h
header file for the devicetree needs to be manually added to your project. Many of the header files rely on information from the devicetree, so it might be included by another API. But this is not always the case.
If you have set up a peripheral incorrectly, it will generate a build error containing error: '__device_dts_ord_,
which indicates that the fault is something related to the devicetree.
The file build/zephyr/include/generated/devicetree_generated.h
can give information regarding which peripheral is causing an error with the devicetree.
The devicetree covers the hardware of a peripheral. In order to enable the driver for the peripheral, the peripheral needs to be enabled in prj.conf
with the correct Kconfig.
For example, if the device uses I2C/TWI, the Kconfig CONFIG_I2C=y
needs to be set.
If the builds fail to find a devicetree binding, then either the node’s compatible
property is not properly defined, or the binding does not exist. Check the Bindings index to see if the device binding exists in Zephyr. If the binding is not listed, you may need to create it yourself.
In overlays, use the devicetree node and property name the same way as they appear in any .dts
file.
Devicetree overlay names must be lowercase, and all special characters need to be converted to underscore.
The following code snippet contains examples for correct and incorrect uses:
* foo.c: lowercase-and-underscores names
*/
/* Don't do this: */
#define MY_CLOCK_FREQ DT_PROP(DT_PATH(soc, i2c@1234000), clock-frequency)
/* ^ ^
* @ should be _ - should be _ */
/* Do this instead: */
#define MY_CLOCK_FREQ DT_PROP(DT_PATH(soc, i2c_1234000), clock_frequency)
C/*
Trying to set property in overlay:
```
/*
* foo.overlay: DTS names with special characters, etc.
*/
/* Don't do this; you'll get devicetree errors. */
&{/soc/i2c_12340000/} {
clock_frequency = <115200>;
};
/* Do this instead. Overlays are just DTS fragments. */
&{/soc/i2c@12340000/} {
clock-frequency = <115200>;
};
DevicetreeIf you get a compile error reading a property node, check and verify that all required properties are set. The required properties can be viewed on the binding list, see Devicetree HOWTOs: Find a devicetree binding.
It is also good practice to write a simple if sentence to verify that the node exists
#if !DT_NODE_EXIST(DT_NODELABEL(NameOfYourNode))
#Error "NameOfYourNode not valid"
#endif
C