doc: guides: dts improvements

People seem to miss the troubleshooting page a lot, since nobody ever
mentions that they tried its steps and they didn't work. Promote it to
a top level page to make it easier to see. Add cross-references
between the two to keep them well linked together.

Add a couple of extra links to the bindings related HOWTO while we are
here, now that the bindings docs are a bit better off than they were
when this content was originally written.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Martí Bolívar 2021-05-25 14:24:20 -07:00 committed by Kumar Gala
parent 574746e7dc
commit 7e7f4201df
3 changed files with 140 additions and 129 deletions

View file

@ -5,6 +5,8 @@ Devicetree HOWTOs
This page has step-by-step advice for getting things done with devicetree.
.. tip:: See :ref:`dt-trouble` for troubleshooting advice.
.. _get-devicetree-outputs:
Get your devicetree and generated header
@ -153,8 +155,9 @@ creating the device, or the device's initialization function failed.
Find a devicetree binding
*************************
Devicetree binding YAML files document what you can do with the nodes they
describe, so it's critical to be able to find them for the nodes you are using.
:ref:`dt-bindings` are YAML files which declare what you can do with the nodes
they describe, so it's critical to be able to find them for the nodes you are
using.
If you don't have them already, :ref:`get-devicetree-outputs`. To find a node's
binding, open the generated header file, which starts with a list of nodes in a
@ -597,130 +600,3 @@ supporting a devicetree alias to specify the hardware specific portions, as is
done in the :ref:`blinky-sample`. The application can then be configured in
:ref:`BOARD.dts <devicetree-in-out-files>` files or via :ref:`devicetree
overlays <use-dt-overlays>`.
.. _dt-trouble:
Troubleshoot devicetree issues
******************************
Here are some tips for fixing misbehaving devicetree code.
Try again with a pristine build directory
=========================================
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 at CMake configuration time, 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>;
};
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>`?
.. _missing-dt-binding:
Check for missing bindings
==========================
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>`.
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`.

View file

@ -14,4 +14,5 @@ See :ref:`devicetree` for reference material.
bindings.rst
api-usage.rst
howtos.rst
troubleshooting.rst
dt-vs-kconfig.rst

View file

@ -0,0 +1,134 @@
.. _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>;
};
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`.