zephyr/doc/build/dts/troubleshooting.rst

168 lines
5.4 KiB
ReStructuredText

.. _dt-trouble:
Troubleshooting devicetree
##########################
Here are some tips for fixing misbehaving devicetree related code.
See :ref:`dt-howtos` for other "HOWTO" style information.
Try again with a pristine build directory
*****************************************
.. important:: Try this first, before doing anything else.
See :ref:`west-building-pristine` for examples, or just delete the build
directory completely and retry.
This is general advice which is especially applicable to debugging devicetree
issues, because the outputs are created during the CMake configuration phase,
and are not always regenerated when one of their inputs changes.
Make sure <devicetree.h> is included
************************************
Unlike Kconfig symbols, the :file:`devicetree.h` header must be included
explicitly.
Many Zephyr header files rely on information from devicetree, so including some
other API may transitively include :file:`devicetree.h`, but that's not
guaranteed.
.. _dt-use-the-right-names:
Make sure you're using the right names
**************************************
Remember that:
- In C/C++, devicetree names must be lowercased and special characters must be
converted to underscores. Zephyr's generated devicetree header has DTS names
converted in this way into the C tokens used by the preprocessor-based
``<devicetree.h>`` API.
- In overlays, use devicetree node and property names the same way they
would appear in any DTS file. Zephyr overlays are just DTS fragments.
For example, if you're trying to **get** the ``clock-frequency`` property of a
node with path ``/soc/i2c@12340000`` in a C/C++ file:
.. code-block:: c
/*
* 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)
/* ^ ^ */
And if you're trying to **set** that property in a devicetree overlay:
.. code-block:: none
/*
* 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>;
};
Look at the preprocessor output
*******************************
To save preprocessor output when using GCC-based toolchains, add
``-save-temps=obj`` to the ``EXTRA_CFLAGS`` CMake variable. For example, to
build :ref:`hello_world` with west with this option set, use:
.. code-block:: sh
west build -b BOARD samples/hello_world -- -DEXTRA_CFLAGS=-save-temps=obj
This will create a preprocessor output file named :file:`foo.c.i` in the build
directory for each source file :file:`foo.c`.
You can then search for the file in the build directory to see what your
devicetree macros expanded to. For example, on macOS and Linux, using ``find``
to find :file:`main.c.i`:
.. code-block:: sh
$ find build -name main.c.i
build/CMakeFiles/app.dir/src/main.c.i
It's usually easiest to run a style formatter on the results before opening
them. For example, to use ``clang-format`` to reformat the file in place:
.. code-block:: sh
clang-format -i build/CMakeFiles/app.dir/src/main.c.i
You can then open the file in your favorite editor to view the final C results
after preprocessing.
Validate properties
*******************
If you're getting a compile error reading a node property, check your node
identifier and property. For example, if you get a build error on a line that
looks like this:
.. code-block:: c
int baud_rate = DT_PROP(DT_NODELABEL(my_serial), current_speed);
Try checking the node by adding this to the file and recompiling:
.. code-block:: c
#if !DT_NODE_EXISTS(DT_NODELABEL(my_serial))
#error "whoops"
#endif
If you see the "whoops" error message when you rebuild, the node identifier
isn't referring to a valid node. :ref:`get-devicetree-outputs` and debug from
there.
Some hints for what to check next if you don't see the "whoops" error message:
- did you :ref:`dt-use-the-right-names`?
- does the :ref:`property exist <dt-checking-property-exists>`?
- does the node have a :ref:`matching binding <dt-bindings>`?
- does the binding define the property?
.. _missing-dt-binding:
Check for missing bindings
**************************
See :ref:`dt-bindings` for information about bindings, and
:ref:`devicetree_binding_index` for information on bindings built into Zephyr.
If the build fails to :ref:`dts-find-binding` for a node, then either the
node's ``compatible`` property is not defined, or its value has no matching
binding. If the property is set, check for typos in its name. In a devicetree
source file, ``compatible`` should look like ``"vnd,some-device"`` --
:ref:`dt-use-the-right-names`.
If your binding file is not under :file:`zephyr/dts`, you may need to set
:ref:`DTS_ROOT <dts_root>`; see :ref:`dt-where-bindings-are-located`.
Errors with DT_INST_() APIs
***************************
If you're using an API like :c:func:`DT_INST_PROP`, you must define
``DT_DRV_COMPAT`` to the lowercase-and-underscores version of the compatible
you are interested in. See :ref:`dt-create-devices-inst`.