| .. _dt-macros: |
| |
| Macros generated from devicetree |
| ################################ |
| |
| This page describes the C preprocessor macros which Zephyr's :ref:`build system |
| <build_overview>` generates from a :ref:`devicetree`. It assumes you're |
| familiar with the concepts in :ref:`devicetree-intro` and :ref:`dt-bindings`. |
| |
| The macros directly generated by the :ref:`devicetree scripts <dt-scripts>` all |
| start with ``DT_`` and use all-uppercase. |
| |
| .. _dt-node-identifiers: |
| |
| Node identifiers |
| **************** |
| |
| Macros generated from individual devicetree nodes or their properties start |
| with ``DT_<node>``, where ``<node>`` is a C identifier for the devicetree node. |
| This section describes the different ``<node>`` values. |
| |
| .. _dt-node-main-ex: |
| |
| We'll use the following DTS fragment from the :ref:`FRDM-K64F <frdm_k64f>` |
| board's devicetree as the main example throughout this section. |
| |
| .. code-block:: DTS |
| |
| / { |
| |
| aliases { |
| i2c-0 = &i2c0; |
| }; |
| |
| soc { |
| i2c0: i2c@40066000 { |
| compatible = "nxp,kinetis-i2c"; |
| reg = <0x40066000 0x1000>; |
| status = "okay"; |
| /* ... */ |
| |
| fxos8700@1d { |
| compatible = "nxp,fxos8700"; |
| status = "okay"; |
| /* ... */ |
| }; |
| }; |
| }; |
| }; |
| |
| The binding for the "nxp,fxos8700" :ref:`compatible property |
| <dt-important-props>` contains this line: |
| |
| .. code-block:: yaml |
| |
| on-bus: i2c |
| |
| The generated macros for this example can be found in a build directory for the |
| :ref:`FXOS8700 sample application <fxos8700>` built for the ``frdm_k64f`` |
| board, in the file :file:`build/zephyr/include/generated/devicetree_unfixed.h`. |
| |
| Here is part of :file:`devicetree_unfixed.h` showing some of the macros for the |
| node labeled ``i2c0``. Notice the comment with the node's path in the |
| devicetree and its dependency relationships with other nodes. |
| |
| .. code-block:: c |
| |
| /* |
| * Devicetree node: |
| * /soc/i2c@40066000 |
| * |
| * Binding (compatible = nxp,kinetis-i2c): |
| * $ZEPHYR_BASE/dts/bindings/i2c/nxp,kinetis-i2c.yaml |
| * |
| * Dependency Ordinal: 66 |
| * |
| * Requires: |
| * 6 /soc |
| * ... |
| * |
| * Supports: |
| * 67 /soc/i2c@40066000/fxos8700@1d |
| * |
| * Description: |
| * Kinetis I2C node |
| */ |
| #define DT_NXP_KINETIS_I2C_40066000_BASE_ADDRESS 0x40066000 |
| #define DT_NXP_KINETIS_I2C_40066000_SIZE 4096 |
| #define DT_ALIAS_I2C_0_BASE_ADDRESS DT_NXP_KINETIS_I2C_40066000_BASE_ADDRESS |
| #define DT_ALIAS_I2C_0_SIZE DT_NXP_KINETIS_I2C_40066000_SIZE |
| #define DT_INST_0_NXP_KINETIS_I2C_BASE_ADDRESS DT_NXP_KINETIS_I2C_40066000_BASE_ADDRESS |
| #define DT_INST_0_NXP_KINETIS_I2C_SIZE DT_NXP_KINETIS_I2C_40066000_SIZE |
| |
| Most macros are generated for individual nodes or their properties. Some macros |
| are generated for "global" information about the entire devicetree. |
| |
| In this example, the node identifiers for ``i2c@40066000`` are: |
| |
| - ``NXP_KINETIS_I2C_40066000`` |
| - ``ALIAS_I2C_0`` |
| - ``INST_0_NXP_KINETIS_I2C`` |
| |
| In general, the following ``DT_<node>`` macro prefixes are created for each |
| node. |
| |
| ``DT_(<bus>_)<compatible>_<unit-address>`` |
| The node's compatible property converted to a C identifier, followed by its |
| :ref:`unit address <dt-unit-address>`. If the node has multiple compatible |
| strings, the one for its :ref:`matching binding <dt-binding-compat>` is |
| used. |
| |
| If the node appears on a bus (and therefore has ``on-bus:`` in its binding, |
| like ``fxos8700@1d`` does), then the compatible string and unit address of |
| the bus node is put before the compatible string for the node itself. If |
| the node does not appear on a bus (no ``on-bus:`` in the binding, like |
| ``i2c@40066000``) then there will be no ``<bus>_`` portion in the node |
| identifier. |
| |
| The ``i2c@40066000`` node identifier is ``NXP_KINETIS_I2C_40066000``: |
| |
| - there is no ``<bus>_`` portion |
| - ``<compatible>`` is ``NXP_KINETIS_I2C``, which is its |
| compatible ``"nxp,kinetis-i2c"`` converted to a C identifier |
| by uppercasing and replacing non-alphanumeric characters with underscores |
| - ``<unit-address>`` is ``40066000`` |
| |
| The ``fxos8700@1d`` node identifier is |
| ``NXP_KINETIS_I2C_40066000_NXP_FXOS8700_1D``: |
| |
| - ``<bus>`` is ``NXP_KINETIS_I2C_40066000`` |
| - ``<compatible>`` is ``NXP_FXOS8700`` |
| - ``<unit-address>`` is ``1D`` |
| |
| If the node has no unit address, the unit address of the parent node plus |
| the node's name converted to a C identifier is used for ``<unit-address>`` |
| instead. If the parent node has no unit address either, the name of the |
| node is used as a fallback. |
| |
| For example, take this DTS fragment: |
| |
| .. code-block:: DTS |
| |
| ethernet@400c0004 { |
| compatible = "nxp,kinetis-ethernet"; |
| reg = <0x400c0004 0x620>; |
| status = "okay"; |
| ptp { |
| compatible = "nxp,kinetis-ptp"; |
| status = "okay"; |
| interrupts = <0x52 0x0>; |
| }; |
| }; |
| |
| The ``ptp`` node identifier is ``NXP_KINETIS_PTP_400C0004_PTP``: |
| |
| - there is no ``<bus>_`` portion |
| - ``<compatible>`` is ``NXP_KINETIS_PTP`` |
| - ``<unit-address>`` is ``400C0004_PTP``, which combines its parent's unit |
| address and the node's name converted to a C identifier |
| |
| Here is another example DTS fragment. |
| |
| .. code-block:: DTS |
| |
| soc { |
| temp1 { |
| compatible = "nxp,kinetis-temperature"; |
| status = "okay"; |
| }; |
| }; |
| |
| The ``temp1`` node identifier is ``NXP_KINETIS_TEMPERATURE_TEMP1``: |
| |
| - there is no ``<bus>_`` portion |
| - ``<compatible>`` is ``NXP_KINETIS_TEMPERATURE`` |
| - ``<unit-address>`` is the fallback value ``TEMP1``, because neither |
| the node nor its parent have a unit address |
| |
| ``DT_INST_<instance-number>_<compatible>`` |
| An instance number for the node, combined with its compatible |
| converted to a C identifier. |
| |
| The instance number is a unique index among all enabled |
| (``status = "okay"``) nodes that have a particular compatible string, |
| starting from zero. |
| |
| The ``i2c@40066000`` node identifier in the :ref:`main example |
| <dt-node-main-ex>` is ``INST_0_NXP_KINETIS_I2C``: |
| |
| - ``<instance-number>`` is 0 because it was the first node with compatible |
| "nxp,kinetis-i2c" that the devicetree scripts happened to discover as they |
| walked the tree |
| - ``<compatible>`` is ``NXP_KINETIS_I2C`` |
| |
| As another example, if there are two enabled nodes that have ``compatible = |
| "foo,uart"``, then these node identifiers get generated: |
| |
| .. code-block:: none |
| |
| INST_0_FOO_UART |
| INST_1_FOO_UART |
| |
| .. warning:: |
| |
| Instance numbers are simple indexes among enabled nodes with the same |
| compatible. They **in no way reflect** any numbering scheme that might |
| exist in SoC documentation, node labels or unit addresses, or properties |
| of the /aliases node. |
| |
| There is no guarantee that the same node will have the same instance |
| number between application builds. The only guarantee is that instance |
| numbers will start at 0, be contiguous, and be assigned for each enabled |
| node with a matching compatible. |
| |
| ``DT_ALIAS_<alias>`` |
| Generated from the names of any properties in the ``/aliases`` node. |
| See :ref:`dt-alias-chosen` for an overview. |
| |
| Here is simple example. |
| |
| .. code-block:: DTS |
| |
| / { |
| aliases { |
| uart-1 = &my_uart; |
| }; |
| |
| my_uart: uart@12345 { /* ... */ }; |
| }; |
| |
| The ``uart@12345`` node identifier is ``ALIAS_UART_1``: ``<alias>`` is |
| ``UART_1`` by uppercasing ``uart-1`` and replacing non-alphanumeric |
| characters with underscores. The alias refers to ``uart@12345`` using its |
| :ref:`label <dt-node-labels>` ``my_uart``. |
| |
| For such a simple concept, dealing with aliases can be surprisingly tricky |
| due to multiple names which have only minor differences. |
| |
| For a real-world example, the ``i2c@40066000`` node's alias identifier in |
| the :ref:`main example <dt-node-main-ex>` is ``ALIAS_I2C_0``: |
| ``<alias>`` is ``I2C_0`` because the property ``i2c-0 = &i2c0;`` in the |
| ``/aliases`` node "points at" ``i2c@40066000`` using its label ``i2c0``. |
| The alias name ``i2c-0`` is converted to C identifier ``I2C_0``. |
| |
| The differences between ``i2c-0``, ``&i2c0``, ``i2c0``, and |
| ``i2c@40006000`` in this example are very subtle and can be quite confusing |
| at first. Here is some more clarification: |
| |
| - ``i2c-0`` is the *name* of a property in the ``/aliases`` node; this is |
| the alias name |
| - ``&i2c0`` is that property's *value*, which is the *phandle* of the |
| the node with label ``i2c0`` |
| - ``i2c@40006000`` is the name of the node which happens to have label |
| ``i2c0`` in this example |
| |
| See the devicetree specification for full details. |
| |
| .. note:: |
| |
| Currently, an older deprecated ``DT_<compatible>_<alias>`` form is also |
| generated for aliases. For the example above, assuming the compatible |
| string for the ``&uart1`` node is ``"foo,uart"``, this gives |
| ``DT_FOO_UART_UART_1``. |
| |
| Work is underway to replace this form with ``DT_ALIAS_*``. |
| |
| .. _property-macros: |
| |
| Macros generated for properties |
| ******************************* |
| |
| Macros for node property values have the form ``DT_<node>_<property>``, where |
| ``<node>`` is a :ref:`node identifier <dt-node-identifiers>` and ``<property>`` |
| identifies the property. The macros generated for a property usually depend on |
| its ``type:`` key in the matching devicetree binding. |
| |
| The following general purpose rules apply in most cases: |
| |
| - :ref:`generic-macros` |
| - :ref:`phandle-array-macros` |
| - :ref:`enum-macros` |
| |
| However, some "special" properties get individual treatment: |
| |
| - :ref:`reg_macros` |
| - :ref:`irq_macros` |
| - :ref:`clk_macros` |
| - :ref:`spi_cs_macros` |
| |
| No macros are currently generated for properties with type ``phandle``, |
| ``phandles``, ``path``, or ``compound``. |
| |
| .. _generic-macros: |
| |
| Generic property macros |
| ======================= |
| |
| This section documents the macros generated for non-"special" properties by |
| example. These properties are handled based on their devicetree binding |
| ``type:`` keys. |
| |
| In the generic case, the ``<property>`` portion of a ``DT_<node>_<property>`` |
| macro begins with the property's name converted to a C identifier by |
| uppercasing it and replacing non-alphanumeric characters with underscores. For |
| example, a ``baud-rate`` property has a ``<property>`` portion that starts with |
| ``BAUD_RATE``. |
| |
| The table below gives the values generated for simple types. Note that an index |
| is added at the end of identifiers generated from properties with ``array`` or |
| ``string-array`` type, and that ``array`` properties generate an additional |
| compound initializer (``{ ... }``). |
| |
| |
| |
| +------------------+------------------------+----------------------------------------+ |
| | Type | Property and value | Generated macros | |
| +==================+========================+========================================+ |
| | ``int`` | ``foo = <1>`` | ``#define DT_<node>_FOO 1`` | |
| +------------------+------------------------+----------------------------------------+ |
| | ``array`` | ``foo = <1 2>`` | | ``#define DT_<node>_FOO_0 1`` | |
| | | | | ``#define DT_<node>_FOO_1 2`` | |
| | | | | ``#define DT_<node>_FOO {1, 2}`` | |
| +------------------+------------------------+----------------------------------------+ |
| | ``string`` | ``foo = "bar"`` | ``#define DT_<node>_FOO "bar"`` | |
| +------------------+------------------------+----------------------------------------+ |
| | ``string-array`` | ``foo = "bar", "baz"`` | | ``#define DT_<node>_FOO_0 "bar"`` | |
| | | | | ``#define DT_<node>_FOO_1 "baz"`` | |
| +------------------+------------------------+----------------------------------------+ |
| | ``uint8-array`` | ``foo = [01 02]`` | ``#define DT_<node>_FOO {0x01, 0x02}`` | |
| +------------------+------------------------+----------------------------------------+ |
| |
| For ``type: boolean``, the generated macro is set to 1 if the property exists |
| on the node, and to 0 otherwise: |
| |
| .. code-block:: none |
| |
| #define DT_<node>_FOO 0/1 |
| |
| For non-boolean types the property macros are not generated if the binding's |
| ``category`` is ``optional`` and the property is not present in the devicetree |
| source. |
| |
| .. _phandle-array-macros: |
| |
| Properties with type ``phandle-array`` |
| ====================================== |
| |
| The generation for properties with type ``phandle-array`` is the most complex. |
| To understand it, it is a good idea to first go through the documentation for |
| ``phandle-array`` in :ref:`dt-bindings`. |
| |
| Take the following devicetree nodes and binding contents as an example: |
| |
| .. code-block:: DTS |
| :caption: Devicetree nodes for PWM controllers |
| |
| pwm_ctrl_0: pwm-controller-0 { |
| label = "pwm-0"; |
| #pwm-cells = <2>; |
| /* ... */ |
| }; |
| |
| pwm_ctrl_1: pwm-controller-1 { |
| label = "pwm-1"; |
| #pwm-cells = <2>; |
| /* ... */ |
| }; |
| |
| .. code-block:: yaml |
| :caption: ``pwm-cells`` declaration in binding for ``vendor,pwm-controller`` |
| |
| pwm-cells: |
| - channel |
| - period |
| |
| Assume the property assignment looks like this: |
| |
| .. code-block:: DTS |
| |
| pwm-user@0 { |
| status = "okay"; |
| pwms = <&pwm_ctrl_0 1 10>, <&pwm_ctrl_1 2 20>; |
| pwm-names = "first", "second"; |
| /* ... */ |
| }; |
| |
| These macros then get generated. |
| |
| .. code-block:: none |
| |
| #define DT_<node>_PWMS_CONTROLLER_0 "pwm-0" |
| #define DT_<node>_PWMS_CHANNEL_0 1 |
| #define DT_<node>_PWMS_PERIOD_0 10 |
| |
| #define DT_<node>_PWMS_CONTROLLER_1 "pwm-1" |
| #define DT_<node>_PWMS_CHANNEL_1 2 |
| #define DT_<node>_PWMS_PERIOD_1 20 |
| |
| #define DT_<node>_PWMS_NAMES_0 "first" |
| #define DT_<node>_PWMS_NAMES_1 "second" |
| |
| #define DT_<node>_FIRST_PWMS_CONTROLLER DT_<node>_PWMS_CONTROLLER_0 |
| #define DT_<node>_FIRST_PWMS_CHANNEL DT_<node>_PWMS_CHANNEL_0 |
| #define DT_<node>_FIRST_PWMS_PERIOD DT_<node>_PWMS_PERIOD_0 |
| |
| #define DT_<node>_SECOND_PWMS_CONTROLLER DT_<node>_PWMS_CONTROLLER_1 |
| #define DT_<node>_SECOND_PWMS_CHANNEL DT_<node>_PWMS_CHANNEL_1 |
| #define DT_<node>_SECOND_PWMS_PERIOD DT_<node>_PWMS_PERIOD_1 |
| |
| /* Initializers */ |
| |
| #define DT_<node>_PWMS_0 {"pwm-0", 1, 10} |
| #define DT_<node>_PWMS_1 {"pwm-1", 2, 20} |
| #define DT_<node>_PWMS {DT_<node>_PWMS_0, DT_<node>_PWMS_1} |
| #define DT_<node>_PWMS_COUNT 2 |
| |
| Macros with a ``*_0`` suffix deal with the first entry in ``pwms`` |
| (``<&pwm_ctrl_0 1 10>``). Macros with a ``*_1`` suffix deal with the second |
| entry (``<&pwm_ctrl_1 2 20>``). The index suffix is only added if there's more |
| than one entry in the property. |
| |
| The ``DT_<node>_PWMS_CONTROLLER(_<index>)`` macros are set to the string from |
| the ``label`` property of the referenced controller. The |
| ``DT_<node>_PWMS_CHANNEL(_<index>)`` and ``DT_<node>_PWMS_PERIOD(_<index>)`` |
| macros are set to the values of the corresponding cells in the ``pwms`` |
| property, with macro names generated from the strings in ``pwm-cells:`` in |
| the binding for the controller. |
| |
| The macros in the ``/* Initializers */`` section provide the same information |
| as ``DT_<node>_PWMS_{CONTROLLER,CHANNEL,PERIOD}(_<index>)``, except as compound |
| initializers that can be used to initialize C ``struct`` variables. |
| |
| If a ``pwm-names`` property exists on the same node as ``pwms`` (more |
| generally, if a ``foo-names`` property is defined next to a ``foo`` property |
| with type ``phandle-array``), it gives a list of strings that name each entry |
| in ``pwms``. The names are used to generate extra macro names with the name |
| instead of an index, like ``DT_<node>_FIRST_PWMS_CONTROLLER`` above. |
| |
| .. _enum-macros: |
| |
| Properties with ``enum:`` in the binding |
| ======================================== |
| |
| Properties declared with an ``enum:`` key in their binding generate a macro |
| that gives the the zero-based index of the property's value in the ``enum:`` |
| list. |
| |
| Take this binding declaration as an example: |
| |
| .. code-block:: yaml |
| |
| properties: |
| foo: |
| type: string |
| enum: |
| - one |
| - two |
| - three |
| |
| The property ``foo = "three"`` then generates this macro: |
| |
| .. code-block:: none |
| |
| #define DT_<node>_FOO_ENUM 2 |
| |
| .. _reg_macros: |
| |
| ``reg`` property macros |
| ======================= |
| |
| ``reg`` properties generate the macros ``DT_<node>_BASE_ADDRESS(_<index>)`` and |
| ``DT_<node>_SIZE(_<index>)``. ``<index>`` is a numeric index starting from 0, |
| which is only added if there's more than one register defined in ``reg``. |
| |
| For example, the ``reg = <0x4004700 0x1060>`` assignment in the example |
| devicetree above gives these macros: |
| |
| .. code-block:: none |
| |
| #define DT_<node>_BASE_ADDRESS 0x40047000 |
| #define DT_<node>_SIZE 4192 |
| |
| .. note:: |
| |
| The length of the address and size portions of ``reg`` is determined from |
| the ``#address-cells`` and ``#size-cells`` properties. See the devicetree |
| specification for more information. |
| |
| In this case, both ``#address-cells`` and ``#size-cells`` are 1, and there's |
| just a single register in ``reg``. Four numbers would give two registers. |
| |
| If a ``reg-names`` property exists on the same node as ``reg``, it gives a list |
| of strings that names each register in ``reg``. The names are used to generate |
| extra macros. For example, ``reg-names = "foo"`` together with the example node |
| generates these macros: |
| |
| .. code-block:: c |
| |
| #define DT_<node>_FOO_BASE_ADDRESS 0x40047000 |
| #define DT_<node>_FOO_SIZE 4192 |
| |
| .. _irq_macros: |
| |
| ``interrupts`` property macros |
| ============================== |
| |
| Take these devicetree nodes as an example: |
| |
| .. code-block:: DTS |
| |
| timer@123 { |
| interrupts = <1 5 2 6>; |
| interrupt-parent = <&intc>; |
| /* ... */ |
| }; |
| |
| intc: interrupt-controller { /* ... */ }; |
| |
| Assume that the binding for ``interrupt-controller`` has these lines: |
| |
| .. code-block:: yaml |
| |
| interrupt-cells: |
| - irq |
| - priority |
| |
| Then these macros get generated for ``timer@123``: |
| |
| .. code-block:: c |
| |
| #define DT_<node>_IRQ_0 1 |
| #define DT_<node>_IRQ_0_PRIORITY 5 |
| #define DT_<node>_IRQ_1 2 |
| #define DT_<node>_IRQ_1_PRIORITY 6 |
| |
| These macros have the the format ``DT_<node>_IRQ_<index>(_<name>)``, where |
| ``<node>`` is the node identifier for ``timer@123``, ``<index>`` is an index |
| that identifies the particular interrupt, and ``<name>`` is the identifier for |
| the cell value (a number within ``interrupts = <...>``), taken from the |
| binding. |
| |
| Bindings for interrupt controllers are expected to declare a cell named ``irq`` |
| in ``interrupt-cells``, giving the interrupt number. The ``_<name>`` suffix is |
| skipped for macros generated from ``irq`` cells, which is why there's e.g. a |
| ``DT_<node>_IRQ_0`` macro and no ``DT_<node>_IRQ_0_IRQ`` macro. |
| |
| If the interrupt controller in turn generates other interrupts, Zephyr uses a |
| multi-level interrupt encoding for the interrupt numbers at each level. See |
| :ref:`multi_level_interrupts` for more information. |
| |
| There is also hard-coded logic for mapping Arm GIC interrupts to linear IRQ |
| numbers. See the source code for details. |
| |
| Additional macros that use names instead of indices for interrupts can be |
| generated by including an ``interrupt-names`` property on the |
| interrupt-generating node. For example, this node: |
| |
| .. code-block:: DTS |
| |
| timer@456 { |
| interrupts = <10 50 20 60>; |
| interrupt-parent = <&intc>; |
| interrupt-names = "timer-a", "timer-b"; |
| /* ... */ |
| }; |
| |
| generates these macros: |
| |
| .. code-block:: c |
| |
| #define DT_<node>_IRQ_TIMER_A 1 |
| #define DT_<node>_IRQ_TIMER_A_PRIORITY 5 |
| #define DT_<node>_IRQ_TIMER_B 2 |
| #define DT_<node>_IRQ_TIMER_B_PRIORITY 6 |
| |
| .. _clk_macros: |
| |
| ``clocks`` property macros |
| ========================== |
| |
| ``clocks`` work the same as other :ref:`phandle-array-macros`, except the |
| generated macros have ``CLOCK`` in them instead of ``CLOCKS``, giving for |
| example ``DT_<node>_CLOCK_CONTROLLER_0`` instead of |
| ``DT_<node>_CLOCKS_CONTROLLER_0``. |
| |
| .. note:: |
| |
| This inconsistency might be fixed in the future. |
| |
| If a ``clocks`` controller node has a ``"fixed-clock"`` compatible, it |
| must also have a ``clock-frequency`` property giving its frequency in Hertz. |
| In this case, an additional macro is generated: |
| |
| .. code-block:: none |
| |
| #define DT_<node>_CLOCKS_CLOCK_FREQUENCY <frequency> |
| |
| .. _spi_cs_macros: |
| |
| ``cs-gpios`` property macros |
| ============================ |
| |
| .. boards/arm/sensortile_box/sensortile_box.dts has a real-world example |
| |
| Take these devicetree nodes as an example. where the binding for |
| ``vendor,spi-controller`` is assumed to have ``bus: spi``, and the bindings for |
| the SPI slaves are assumed to have ``on-bus: spi``: |
| |
| .. code-block:: DTS |
| |
| gpioa: gpio@400ff000 { |
| compatible = "vendor,gpio-ctlr"; |
| reg = <0x400ff000 0x40>; |
| label = "GPIOA"; |
| gpio-controller; |
| #gpio-cells = <0x1>; |
| }; |
| |
| spi { |
| compatible = "vendor,spi-controller"; |
| cs-gpios = <&gpioa 1>, <&gpioa 2>; |
| spi-slave@0 { |
| compatible = "vendor,foo-spi-device"; |
| reg = <0>; |
| }; |
| spi-slave@1 { |
| compatible = "vendor,bar-spi-device"; |
| reg = <1>; |
| }; |
| }; |
| |
| Here, the unit address of the SPI slaves (0 and 1) is taken as a chip select |
| number, which is used as an index into ``cs-gpios`` (a ``phandle-array``). |
| ``spi-slave@0`` is matched to ``<&gpioa 1>``, and ``spi-slave@1`` to |
| ``<&gpiob 2>``. |
| |
| The output for ``spi-slave@0`` and ``spi-slave@1`` is the same as if the |
| devicetree had looked like this: |
| |
| .. code-block:: DTS |
| |
| gpioa: gpio@400ff000 { |
| compatible = "vendor,gpio-ctlr"; |
| reg = <0x400ff000 0x40>; |
| label = "GPIOA"; |
| gpio-controller; |
| #gpio-cells = <1>; |
| }; |
| |
| spi { |
| compatible = "vendor,spi-controller"; |
| spi-slave@0 { |
| compatible = "vendor,foo-spi-device"; |
| reg = <0>; |
| cs-gpios = <&gpioa 1>; |
| }; |
| spi-slave@1 { |
| compatible = "vendor,bar-spi-device"; |
| reg = <1>; |
| cs-gpios = <&gpioa 2>; |
| }; |
| }; |
| |
| See the ``phandle-array`` section in :ref:`generic-macros` for more |
| information. |
| |
| For example, since the node labeled ``gpioa`` has property |
| ``label = "GPIOA"`` and 1 and 2 are pin numbers, macros like the following |
| will be generated for ``spi-slave@0``: |
| |
| .. code-block:: none |
| |
| #define DT_<node>_CS_GPIOS_CONTROLLER "GPIOA" |
| #define DT_<node>_CS_GPIOS_PIN 1 |
| |
| .. _other-macros: |
| |
| Other macros |
| ************ |
| |
| These are generated in addition to macros generated for :ref:`properties |
| <property-macros>`. |
| |
| - :ref:`dt-existence-macros` |
| - :ref:`bus-macros` |
| - :ref:`flash-macros` |
| |
| .. _dt-existence-macros: |
| |
| Node existence flags |
| ==================== |
| |
| An "existence flag" is a macro which is defined when the devicetree contains |
| nodes matching some criterion. |
| |
| Existence flags are generated for each compatible property that appears on an |
| enabled node: |
| |
| .. code-block:: none |
| |
| #define DT_COMPAT_<compatible> 1 |
| |
| An existence flag is also written for all enabled nodes with a matching |
| compatible: |
| |
| .. code-block:: none |
| |
| #define DT_INST_<instance-number>_<compatible> 1 |
| |
| For the ``i2c@40066000`` node in the :ref:`example <dt-node-main-ex>` above, |
| assuming the node is the first node with ``compatible = "nxp,kinetis-i2c"``, |
| the following existence flags would be generated: |
| |
| .. code-block:: c |
| |
| /* At least one node had compatible nxp,kinetis-i2c: */ |
| #define DT_COMPAT_NXP_KINETIS_I2C 1 |
| |
| /* Instance 0 of compatible nxp,kinetis-i2c exists: */ |
| #define DT_INST_0_NXP_KINETIS_I2C 1 |
| |
| If additional nodes had compatible ``nxp,kinetis-i2c``, additional existence |
| flags would be generated: |
| |
| .. code-block:: c |
| |
| #define DT_INST_1_NXP_KINETIS_I2C 1 |
| #define DT_INST_2_NXP_KINETIS_I2C 1 |
| /* ... and so on, one for each node with this compatible. */ |
| |
| .. _bus-macros: |
| |
| Bus-related macros |
| ================== |
| |
| These macros get generated for nodes that appear on buses (have ``on-bus:`` in |
| their binding): |
| |
| .. code-block:: none |
| |
| #define DT_<node>_BUS_NAME "<bus-label>" |
| #define DT_<compatible>_BUS_<bus-name> 1 |
| |
| ``<bus-label>`` is taken from the ``label`` property on the bus node, which |
| must exist. ``<bus-name>`` is the identifier for the bus as given in |
| ``on-bus:`` in the binding. |
| |
| .. _flash-macros: |
| |
| Macros generated from flash partitions |
| ====================================== |
| |
| .. note:: |
| |
| This section only covers flash partitions. See :ref:`dt-alias-chosen` for |
| some other flash-related macros that get generated from devicetree, via |
| ``/chosen``. |
| |
| If a node has a name that looks like ``partition@<unit-address>``, it is |
| assumed to represent a flash partition. |
| |
| Assume the devicetree has this: |
| |
| .. code-block:: DTS |
| |
| flash@0 { |
| /* ... */ |
| label = "foo-flash"; |
| |
| partitions { |
| /* ... */ |
| #address-cells = <1>; |
| #size-cells = <1>; |
| |
| boot_partition: partition@0 { |
| label = "mcuboot"; |
| reg = <0x00000000 0x00010000>; |
| read-only; |
| }; |
| slot0_partition: partition@10000 { |
| label = "image-0"; |
| reg = <0x00010000 0x00020000 |
| 0x00040000 0x00010000>; |
| }; |
| /* ... */ |
| }; |
| |
| These macros then get generated: |
| |
| .. code-block:: c |
| |
| #define DT_FLASH_AREA_MCUBOOT_ID 0 |
| #define DT_FLASH_AREA_MCUBOOT_READ_ONLY 1 |
| #define DT_FLASH_AREA_MCUBOOT_OFFSET_0 0x0 |
| #define DT_FLASH_AREA_MCUBOOT_SIZE_0 0x10000 |
| #define DT_FLASH_AREA_MCUBOOT_OFFSET DT_FLASH_AREA_MCUBOOT_OFFSET_0 |
| #define DT_FLASH_AREA_MCUBOOT_SIZE DT_FLASH_AREA_MCUBOOT_SIZE_0 |
| #define DT_FLASH_AREA_MCUBOOT_DEV "foo-flash" |
| |
| #define DT_FLASH_AREA_IMAGE_0_ID 0 |
| #define DT_FLASH_AREA_IMAGE_0_READ_ONLY 1 |
| #define DT_FLASH_AREA_IMAGE_0_OFFSET_0 0x10000 |
| #define DT_FLASH_AREA_IMAGE_0_SIZE_0 0x20000 |
| #define DT_FLASH_AREA_IMAGE_0_OFFSET_1 0x40000 |
| #define DT_FLASH_AREA_IMAGE_0_SIZE_1 0x10000 |
| #define DT_FLASH_AREA_IMAGE_0_OFFSET DT_FLASH_AREA_IMAGE_0_OFFSET_0 |
| #define DT_FLASH_AREA_IMAGE_0_SIZE DT_FLASH_AREA_IMAGE_0_SIZE_0 |
| #define DT_FLASH_AREA_IMAGE_0_DEV "foo-flash" |
| |
| /* Same macros, just with index instead of label */ |
| #define DT_FLASH_AREA_0_ID 0 |
| #define DT_FLASH_AREA_0_READ_ONLY 1 |
| ... |
| |
| The ``*_ID`` macro gives the zero-based index for the partition. |
| |
| The ``*_OFFSET_<index>`` and ``*_SIZE_<index>`` macros give the offset and size |
| for each partition, derived from ``reg``. The ``*_OFFSET`` and ``*_SIZE`` |
| macros, with no index, are aliases that point to the first sector (with index |
| 0). |
| |
| An ABNF grammar |
| *************** |
| |
| This section contains an Augmented Backus-Naur Form grammar for the macros |
| generated from a devicetree. See `RFC 7405`_ (which extends `RFC 5234`_) for a |
| syntax specification. |
| |
| .. literalinclude:: macros.bnf |
| :language: abnf |
| |
| .. _RFC 7405: https://tools.ietf.org/html/rfc7405 |
| .. _RFC 5234: https://tools.ietf.org/html/rfc5234 |