478 lines
16 KiB
ReStructuredText
478 lines
16 KiB
ReStructuredText
.. _dt-syntax:
|
|
|
|
Syntax and structure
|
|
####################
|
|
|
|
As the name indicates, a devicetree is a tree. The human-readable text format
|
|
for this tree is called DTS (for devicetree source), and is defined in the
|
|
`Devicetree specification`_.
|
|
|
|
.. _Devicetree specification: https://www.devicetree.org/
|
|
|
|
This page's purpose is to introduce devicetree in a more gradual way than the
|
|
specification. However, you may still need to refer to the specification to
|
|
understand some detailed cases.
|
|
|
|
.. contents:: Contents
|
|
:local:
|
|
|
|
Example
|
|
*******
|
|
|
|
Here is an example DTS file:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
/dts-v1/;
|
|
|
|
/ {
|
|
a-node {
|
|
subnode_nodelabel: a-sub-node {
|
|
foo = <3>;
|
|
};
|
|
};
|
|
};
|
|
|
|
The ``/dts-v1/;`` line means the file's contents are in version 1 of the DTS
|
|
syntax, which has replaced a now-obsolete "version 0".
|
|
|
|
Nodes
|
|
*****
|
|
|
|
Like any tree data structure, a devicetree has a hierarchy of *nodes*.
|
|
The above tree has three nodes:
|
|
|
|
#. A root node: ``/``
|
|
#. A node named ``a-node``, which is a child of the root node
|
|
#. A node named ``a-sub-node``, which is a child of ``a-node``
|
|
|
|
.. _dt-node-labels:
|
|
|
|
Nodes can be assigned *node labels*, which are unique shorthands that refer to
|
|
the labeled node. Above, ``a-sub-node`` has the node label
|
|
``subnode_nodelabel``. A node can have zero, one, or multiple node labels. You
|
|
can use node labels to refer to the node elsewhere in the devicetree.
|
|
|
|
Devicetree nodes have *paths* identifying their locations in the tree. Like
|
|
Unix file system paths, devicetree paths are strings separated by slashes
|
|
(``/``), and the root node's path is a single slash: ``/``. Otherwise, each
|
|
node's path is formed by concatenating the node's ancestors' names with the
|
|
node's own name, separated by slashes. For example, the full path to
|
|
``a-sub-node`` is ``/a-node/a-sub-node``.
|
|
|
|
Properties
|
|
**********
|
|
|
|
Devicetree nodes can also have *properties*. Properties are name/value pairs.
|
|
Property values can be any sequence of bytes. In some cases, the values are an
|
|
array of what are called *cells*. A cell is just a 32-bit unsigned integer.
|
|
|
|
Node ``a-sub-node`` has a property named ``foo``, whose value is a cell with
|
|
value 3. The size and type of ``foo``\ 's value are implied by the enclosing
|
|
angle brackets (``<`` and ``>``) in the DTS.
|
|
|
|
See :ref:`dt-writing-property-values` below for more example property values.
|
|
|
|
Devicetrees reflect hardware
|
|
****************************
|
|
|
|
In practice, devicetree nodes usually correspond to some hardware, and the node
|
|
hierarchy reflects the hardware's physical layout. For example, let's consider
|
|
a board with three I2C peripherals connected to an I2C bus controller on an SoC,
|
|
like this:
|
|
|
|
.. figure:: zephyr_dt_i2c_high_level.png
|
|
:alt: representation of a board with three I2C peripherals
|
|
:figclass: align-center
|
|
|
|
Nodes corresponding to the I2C bus controller and each I2C peripheral would be
|
|
present in the devicetree. Reflecting the hardware layout, the
|
|
I2C peripheral nodes would be children of the bus controller node.
|
|
Similar conventions exist for representing other types of hardware.
|
|
|
|
The DTS would look something like this:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
/dts-v1/;
|
|
|
|
/ {
|
|
soc {
|
|
i2c-bus-controller {
|
|
i2c-peripheral-1 {
|
|
};
|
|
i2c-peripheral-2 {
|
|
};
|
|
i2c-peripheral-3 {
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
Properties in practice
|
|
**********************
|
|
|
|
In practice, properties usually describe or configure the hardware the node
|
|
represents. For example, an I2C peripheral's node has a property whose value is
|
|
the peripheral's address on the bus.
|
|
|
|
Here's a tree representing the same example, but with real-world node
|
|
names and properties you might see when working with I2C devices.
|
|
|
|
.. figure:: zephyr_dt_i2c_example.png
|
|
:figclass: align-center
|
|
|
|
I2C devicetree example with real-world names and properties.
|
|
Node names are at the top of each node with a gray background.
|
|
Properties are shown as "name=value" lines.
|
|
|
|
This is the corresponding DTS:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
/dts-v1/;
|
|
|
|
/ {
|
|
soc {
|
|
i2c@40003000 {
|
|
compatible = "nordic,nrf-twim";
|
|
reg = <0x40003000 0x1000>;
|
|
|
|
apds9960@39 {
|
|
compatible = "avago,apds9960";
|
|
reg = <0x39>;
|
|
};
|
|
ti_hdc@43 {
|
|
compatible = "ti,hdc", "ti,hdc1010";
|
|
reg = <0x43>;
|
|
};
|
|
mma8652fc@1d {
|
|
compatible = "nxp,fxos8700", "nxp,mma8652fc";
|
|
reg = <0x1d>;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
.. _dt-unit-address:
|
|
|
|
Unit addresses
|
|
**************
|
|
|
|
In addition to showing more real-world names and properties, the above example
|
|
introduces a new devicetree concept: unit addresses. Unit addresses are the
|
|
parts of node names after an "at" sign (``@``), like ``40003000`` in
|
|
``i2c@40003000``, or ``39`` in ``apds9960@39``. Unit addresses are optional:
|
|
the ``soc`` node does not have one.
|
|
|
|
In devicetree, unit addresses give a node's address in the
|
|
address space of its parent node. Here are some example unit addresses for
|
|
different types of hardware.
|
|
|
|
Memory-mapped peripherals
|
|
The peripheral's register map base address.
|
|
For example, the node named ``i2c@40003000`` represents an I2C controller
|
|
whose register map base address is 0x40003000.
|
|
|
|
I2C peripherals
|
|
The peripheral's address on the I2C bus.
|
|
For example, the child node ``apds9960@39`` of the I2C controller
|
|
in the previous section has I2C address 0x39.
|
|
|
|
SPI peripherals
|
|
An index representing the peripheral's chip select line number.
|
|
(If there is no chip select line, 0 is used.)
|
|
|
|
Memory
|
|
The physical start address.
|
|
For example, a node named ``memory@2000000`` represents RAM starting at
|
|
physical address 0x2000000.
|
|
|
|
Memory-mapped flash
|
|
Like RAM, the physical start address.
|
|
For example, a node named ``flash@8000000`` represents a flash device
|
|
whose physical start address is 0x8000000.
|
|
|
|
Fixed flash partitions
|
|
This applies when the devicetree is used to store a flash partition table.
|
|
The unit address is the partition's start offset within the flash memory.
|
|
For example, take this flash device and its partitions:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
flash@8000000 {
|
|
/* ... */
|
|
partitions {
|
|
partition@0 { /* ... */ };
|
|
partition@20000 { /* ... */ };
|
|
/* ... */
|
|
};
|
|
};
|
|
|
|
The node named ``partition@0`` has offset 0 from the start of its flash
|
|
device, so its base address is 0x8000000. Similarly, the base address of
|
|
the node named ``partition@20000`` is 0x8020000.
|
|
|
|
.. _dt-important-props:
|
|
|
|
Important properties
|
|
********************
|
|
|
|
.. Documentation maintainers: If you add a property to this list,
|
|
make sure it gets linked to from gen_devicetree_rest.py too.
|
|
|
|
The devicetree specification defines several standard properties.
|
|
Some of the most important ones are:
|
|
|
|
compatible
|
|
The name of the hardware device the node represents.
|
|
|
|
The recommended format is ``"vendor,device"``, like ``"avago,apds9960"``,
|
|
or a sequence of these, like ``"ti,hdc", "ti,hdc1010"``. The ``vendor``
|
|
part is an abbreviated name of the vendor. The file
|
|
:zephyr_file:`dts/bindings/vendor-prefixes.txt` contains a list of commonly
|
|
accepted ``vendor`` names. The ``device`` part is usually taken from the
|
|
datasheet.
|
|
|
|
It is also sometimes a value like ``gpio-keys``, ``mmio-sram``, or
|
|
``fixed-clock`` when the hardware's behavior is generic.
|
|
|
|
The build system uses the compatible property to find the right
|
|
:ref:`bindings <dt-bindings>` for the node. Device drivers use
|
|
``devicetree.h`` to find nodes with relevant compatibles, in order to
|
|
determine the available hardware to manage.
|
|
|
|
The ``compatible`` property can have multiple values. Additional values are
|
|
useful when the device is a specific instance of a more general family, to
|
|
allow the system to match from most- to least-specific device drivers.
|
|
|
|
Within Zephyr's bindings syntax, this property has type ``string-array``.
|
|
|
|
reg
|
|
Information used to address the device. The value is specific to the device
|
|
(i.e. is different depending on the compatible property).
|
|
|
|
The ``reg`` property is a sequence of ``(address, length)`` pairs. Each
|
|
pair is called a "register block". Values are conventionally written
|
|
in hex.
|
|
|
|
Here are some common patterns:
|
|
|
|
- Devices accessed via memory-mapped I/O registers (like ``i2c@40003000``):
|
|
``address`` is usually the base address of the I/O register space, and
|
|
``length`` is the number of bytes occupied by the registers.
|
|
- I2C devices (like ``apds9960@39`` and its siblings):
|
|
``address`` is a slave address on the I2C bus. There is no ``length``
|
|
value.
|
|
- SPI devices: ``address`` is a chip select line number; there is no
|
|
``length``.
|
|
|
|
You may notice some similarities between the ``reg`` property and common
|
|
unit addresses described above. This is not a coincidence. The ``reg``
|
|
property can be seen as a more detailed view of the addressable resources
|
|
within a device than its unit address.
|
|
|
|
status
|
|
A string which describes whether the node is enabled.
|
|
|
|
The devicetree specification allows this property to have values
|
|
``"okay"``, ``"disabled"``, ``"reserved"``, ``"fail"``, and ``"fail-sss"``.
|
|
Only the values ``"okay"`` and ``"disabled"`` are currently relevant to
|
|
Zephyr; use of other values currently results in undefined behavior.
|
|
|
|
A node is considered enabled if its status property is either ``"okay"`` or
|
|
not defined (i.e. does not exist in the devicetree source). Nodes with
|
|
status ``"disabled"`` are explicitly disabled. (For backwards
|
|
compatibility, the value ``"ok"`` is treated the same as ``"okay"``, but
|
|
this usage is deprecated.) Devicetree nodes which correspond to physical
|
|
devices must be enabled for the corresponding ``struct device`` in the
|
|
Zephyr driver model to be allocated and initialized.
|
|
|
|
interrupts
|
|
Information about interrupts generated by the device, encoded as an array
|
|
of one or more *interrupt specifiers*. Each interrupt specifier has some
|
|
number of cells. See section 2.4, *Interrupts and Interrupt Mapping*, in the
|
|
`Devicetree Specification release v0.3`_ for more details.
|
|
|
|
Zephyr's devicetree bindings language lets you give a name to each cell in
|
|
an interrupt specifier.
|
|
|
|
.. _Devicetree Specification release v0.3:
|
|
https://www.devicetree.org/specifications/
|
|
|
|
.. highlight:: none
|
|
|
|
.. note::
|
|
|
|
Earlier versions of Zephyr made frequent use of the ``label`` property,
|
|
which is distinct from the standard :ref:`node label <dt-node-labels>`.
|
|
Use of the label *property* in new devicetree bindings, as well as use of
|
|
the :c:macro:`DT_LABEL` macro in new code, are actively discouraged. Label
|
|
properties continue to persist for historical reasons in some existing
|
|
bindings and overlays, but should not be used in new bindings or device
|
|
implementations.
|
|
|
|
.. _dt-writing-property-values:
|
|
|
|
Writing property values
|
|
***********************
|
|
|
|
This section describes how to write property values in DTS format. The property
|
|
types in the table below are described in detail in :ref:`dt-bindings`.
|
|
|
|
Some specifics are skipped in the interest of keeping things simple; if you're
|
|
curious about details, see the devicetree specification.
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
:widths: 1 4 4
|
|
|
|
* - Property type
|
|
- How to write
|
|
- Example
|
|
|
|
* - string
|
|
- Double quoted
|
|
- ``a-string = "hello, world!";``
|
|
|
|
* - int
|
|
- between angle brackets (``<`` and ``>``)
|
|
- ``an-int = <1>;``
|
|
|
|
* - boolean
|
|
- for ``true``, with no value (for ``false``, use ``/delete-property/``)
|
|
- ``my-true-boolean;``
|
|
|
|
* - array
|
|
- between angle brackets (``<`` and ``>``), separated by spaces
|
|
- ``foo = <0xdeadbeef 1234 0>;``
|
|
|
|
* - uint8-array
|
|
- in hexadecimal *without* leading ``0x``, between square brackets (``[`` and ``]``).
|
|
- ``a-byte-array = [00 01 ab];``
|
|
|
|
* - string-array
|
|
- separated by commas
|
|
- ``a-string-array = "string one", "string two", "string three";``
|
|
|
|
* - phandle
|
|
- between angle brackets (``<`` and ``>``)
|
|
- ``a-phandle = <&mynode>;``
|
|
|
|
* - phandles
|
|
- between angle brackets (``<`` and ``>``), separated by spaces
|
|
- ``some-phandles = <&mynode0 &mynode1 &mynode2>;``
|
|
|
|
* - phandle-array
|
|
- between angle brackets (``<`` and ``>``), separated by spaces
|
|
- ``a-phandle-array = <&mynode0 1 2>, <&mynode1 3 4>;``
|
|
|
|
Additional notes on the above:
|
|
|
|
- The values in the ``phandle``, ``phandles``, and ``phandle-array`` types are
|
|
described further in :ref:`dt-phandles`
|
|
|
|
- Boolean properties are true if present. They should not have a value.
|
|
A boolean property is only false if it is completely missing in the DTS.
|
|
|
|
- The ``foo`` property value above has three *cells* with values 0xdeadbeef, 1234,
|
|
and 0, in that order. Note that hexadecimal and decimal numbers are allowed and
|
|
can be intermixed. Since Zephyr transforms DTS to C sources, it is not
|
|
necessary to specify the endianness of an individual cell here.
|
|
|
|
- 64-bit integers are written as two 32-bit cells in big-endian order. The value
|
|
0xaaaa0000bbbb1111 would be written ``<0xaaaa0000 0xbbbb1111>``.
|
|
|
|
- The ``a-byte-array`` property value is the three bytes 0x00, 0x01, and 0xab, in
|
|
that order.
|
|
|
|
- Parentheses, arithmetic operators, and bitwise operators are allowed. The
|
|
``bar`` property contains a single cell with value 64:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
bar = <(2 * (1 << 5))>;
|
|
|
|
Note that the entire expression must be parenthesized.
|
|
|
|
- Property values refer to other nodes in the devicetree by their *phandles*.
|
|
You can write a phandle using ``&foo``, where ``foo`` is a :ref:`node label
|
|
<dt-node-labels>`. Here is an example devicetree fragment:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
foo: device@0 { };
|
|
device@1 {
|
|
sibling = <&foo 1 2>;
|
|
};
|
|
|
|
The ``sibling`` property of node ``device@1`` contains three cells, in this order:
|
|
|
|
#. The ``device@0`` node's phandle, which is written here as ``&foo`` since
|
|
the ``device@0`` node has a node label ``foo``
|
|
#. The value 1
|
|
#. The value 2
|
|
|
|
In the devicetree, a phandle value is a cell -- which again is just a 32-bit
|
|
unsigned int. However, the Zephyr devicetree API generally exposes these
|
|
values as *node identifiers*. Node identifiers are covered in more detail in
|
|
:ref:`dt-from-c`.
|
|
|
|
- Array and similar type property values can be split into several ``<>``
|
|
blocks, like this:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
foo = <1 2>, <3 4>; // Okay for 'type: array'
|
|
foo = <&label1 &label2>, <&label3 &label4>; // Okay for 'type: phandles'
|
|
foo = <&label1 1 2>, <&label2 3 4>; // Okay for 'type: phandle-array'
|
|
|
|
This is recommended for readability when possible if the value can be
|
|
logically grouped into blocks of sub-values.
|
|
|
|
.. _dt-alias-chosen:
|
|
|
|
Aliases and chosen nodes
|
|
************************
|
|
|
|
There are two additional ways beyond :ref:`node labels <dt-node-labels>` to
|
|
refer to a particular node without specifying its entire path: by alias, or by
|
|
chosen node.
|
|
|
|
Here is an example devicetree which uses both:
|
|
|
|
.. code-block:: devicetree
|
|
|
|
/dts-v1/;
|
|
|
|
/ {
|
|
chosen {
|
|
zephyr,console = &uart0;
|
|
};
|
|
|
|
aliases {
|
|
my-uart = &uart0;
|
|
};
|
|
|
|
soc {
|
|
uart0: serial@12340000 {
|
|
...
|
|
};
|
|
};
|
|
};
|
|
|
|
The ``/aliases`` and ``/chosen`` nodes do not refer to an actual hardware
|
|
device. Their purpose is to specify other nodes in the devicetree.
|
|
|
|
Above, ``my-uart`` is an alias for the node with path ``/soc/serial@12340000``.
|
|
Using its node label ``uart0``, the same node is set as the value of the chosen
|
|
``zephyr,console`` node.
|
|
|
|
Zephyr sample applications sometimes use aliases to allow overriding the
|
|
particular hardware device used by the application in a generic way. For
|
|
example, :zephyr:code-sample:`blinky` uses this to abstract the LED to blink via the
|
|
``led0`` alias.
|
|
|
|
The ``/chosen`` node's properties are used to configure system- or
|
|
subsystem-wide values. See :ref:`devicetree-chosen-nodes` for more information.
|