Commit e4a761cf authored by Martí Bolívar's avatar Martí Bolívar Committed by Carles Cufi
Browse files

devicetree: add migration guide documentation and tests



Add test cases that verify various bits and pieces of the legacy
devicetree macros match the new APIs.

Writing these test cases without giving rise to deprecated macro
warnings which might break people's CI if they build with -Werror
requires turning off the __WARN() generation in
devicetree_legacy_unfixed.h. The entire file is deprecated at this
point and must be explicitly enabled with an opt-in Kconfig option, so
there isn't any harm in doing this.

Nevertheless, take a minimally invasive approach to avoiding __WARN()
generation in gen_legacy_defines.py, to avoid the possibility of
breakage. This code is basically frozen anyway, so hacks like this
won't cause maintainability problems since it isn't being actively
maintained.

Use the new tests as fodder for a migration guide from the old API in
the documentation.

Signed-off-by: default avatarMartí Bolívar <marti.bolivar@nordicsemi.no>
parent f1808c4a
Loading
Loading
Loading
Loading
+212 −0
Original line number Diff line number Diff line
@@ -566,6 +566,218 @@ 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-migrate-legacy:

Migrate from the legacy macros
******************************

This section shows how to migrate from the :ref:`dt-legacy-macros` to the
:ref:`devicetree.h API <dt-from-c>`. (Please feel free to :ref:`ask for help
<help>` if a use case you need is missing here and existing documentation is
not enough to figure out what to do.)

This DTS is used for examples:

.. literalinclude:: ../../../tests/lib/devicetree/legacy_api/app.overlay
   :language: DTS
   :start-after: start-after-here
   :end-before: end-before-here

The following shows equivalent ways to access this devicetree, using legacy
macros and the new devicetree.h API.

.. warning::

   The INST numbers below were carefully chosen to work. Instance numbering
   properties have changed in the devicetree.h API compared to the legacy
   macros, and are not guaranteed to be the same in all cases. See
   :c:func:`DT_INST` for details.

.. code-block:: c

   /*
    * label
    *
    * These use the label property in /migration/gpio@1000.
    * They all expand to "MGR_GPIO".
    */

   /* Legacy: */
   DT_VND_GPIO_1000_LABEL
   DT_INST_0_VND_GPIO_LABEL
   DT_ALIAS_MGR_GPIO_LABEL

   /* Use these instead: */
   DT_LABEL(DT_PATH(migration, gpio_1000))
   DT_LABEL(DT_INST(0, vnd_gpio))
   DT_LABEL(DT_ALIAS(mgr_gpio))
   DT_LABEL(DT_NODELABEL(migration_gpio))

   /*
    * reg base addresses and sizes
    *
    * These use the reg property in /migration/gpio@1000.
    * The base addresses all expand to 0x1000, and sizes to 0x2000.
    */

   /* Legacy addresses: */
   DT_VND_GPIO_1000_BASE_ADDRESS
   DT_INST_0_VND_GPIO_BASE_ADDRESS
   DT_ALIAS_MGR_GPIO_BASE_ADDRESS

   /* Use these instead: */
   DT_REG_ADDR(DT_PATH(migration, gpio_1000))
   DT_REG_ADDR(DT_INST(0, vnd_gpio))
   DT_REG_ADDR(DT_ALIAS(mgr_gpio))
   DT_REG_ADDR(DT_NODELABEL(migration_gpio))

   /* Legacy sizes: */
   DT_VND_GPIO_1000_SIZE
   DT_INST_0_VND_GPIO_SIZE
   DT_ALIAS_MGR_GPIO_SIZE

   /* Use these instead: */
   DT_REG_SIZE(DT_PATH(migration, gpio_1000))
   DT_REG_SIZE(DT_INST(0, vnd_gpio))
   DT_REG_SIZE(DT_ALIAS(mgr_gpio))
   DT_REG_SIZE(DT_NODELABEL(migration_gpio))

   /*
    * interrupts IRQ numbers and priorities
    *
    * These use the interrupts property in /migration/gpio@1000.
    * The interrupt number is 0, and the priority is 1.
    */

   /* Legacy interrupt numbers: */
   DT_VND_GPIO_1000_IRQ_0
   DT_INST_0_VND_GPIO_IRQ_0
   DT_ALIAS_MGR_GPIO_IRQ_0

   /* Use these instead: */
   DT_IRQN(DT_PATH(migration, gpio_1000))
   DT_IRQN(DT_INST(0, vnd_gpio))
   DT_IRQN(DT_ALIAS(mgr_gpio))
   DT_IRQN(DT_NODELABEL(migration_gpio))

   /* Legacy priorities: */
   DT_VND_GPIO_1000_IRQ_0_PRIORITY,
   DT_INST_0_VND_GPIO_IRQ_0_PRIORITY,
   DT_ALIAS_MGR_GPIO_IRQ_0_PRIORITY,

   /* Use these instead: */
   DT_IRQ(DT_PATH(migration, gpio_1000), priority)
   DT_IRQ(DT_INST(0, vnd_gpio), priority)
   DT_IRQ(DT_ALIAS(mgr_gpio), priority)
   DT_IRQ(DT_NODELABEL(migration_gpio), priority)

   /*
    * Other property access
    *
    * These use the baud-rate property in /migration/serial@3000.
    * They all expand to 115200.
    */

   /* Legacy: */
   DT_VND_SERIAL_3000_BAUD_RATE
   DT_ALIAS_MGR_SERIAL_BAUD_RATE
   DT_INST_0_VND_SERIAL_BAUD_RATE

   /* Use these instead: */
   DT_PROP(DT_PATH(migration, serial_3000), baud_rate)
   DT_PROP(DT_ALIAS(mgr_serial), baud_rate)
   DT_PROP(DT_NODELABEL(migration_serial), baud_rate)
   DT_PROP(DT_INST(0, vnd_serial), baud_rate)

   /*
    * I2C bus controller label access for an I2C peripheral device.
    *
    * These are different ways to get the bus controller label property
    * from the peripheral device /migration/i2c@1000/i2c-dev-10.
    *
    * They all expand to "MGR_I2C".
    */

   /* Legacy: */
   DT_VND_I2C_10000_VND_I2C_DEVICE_10_BUS_NAME
   DT_ALIAS_MGR_I2C_DEV_BUS_NAME
   DT_INST_0_VND_I2C_DEVICE_BUS_NAME

   /* Use these instead (the extra #defines are just for readability): */
   #define I2C_DEV_PATH		DT_PATH(migration, i2c_10000, i2c_dev_10)
   #define I2C_DEV_ALIAS		DT_ALIAS(mgr_i2c_dev)
   #define I2C_DEV_NODELABEL	DT_NODELABEL(mgr_i2c_device)
   #define I2C_DEV_INST		DT_INST(0, vnd_i2c_device)

   DT_LABEL(DT_BUS(I2C_DEV_PATH))
   DT_LABEL(DT_BUS(I2C_DEV_ALIAS)))
   DT_LABEL(DT_BUS(I2C_DEV_NODELABEL)))
   DT_LABEL(DT_BUS(I2C_DEV_INST)))

   /*
    * SPI device chip-select controller.
    *
    * These use /migration/spi@2000/spi-dev@0. They all expand to
    * "MGR_GPIO", which is the label property of /migration/gpio@1000,
    * which is the SPI device's chip select pin GPIO controller. This is
    * taken from the parent node's cs-gpios property.
    */

   /* Legacy */
   DT_VND_SPI_20000_VND_SPI_DEVICE_0_CS_GPIOS_CONTROLLER
   DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_CONTROLLER
   DT_INST_0_VND_SPI_DEVICE_CS_GPIOS_CONTROLLER

   /* Use these instead (extra #defines just for readability): */
   #define SPI_DEV_PATH		DT_PATH(migration, spi_20000, migration_spi_dev_0)
   #define SPI_DEV_ALIAS		DT_ALIAS(mgr_spi_dev)
   #define SPI_DEV_NODELABEL	DT_NODELABEL(mgr_spi_device)
   #define SPI_DEV_INST		DT_INST(0, vnd_spi_device)

   DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_PATH)
   DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_ALIAS)
   DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_NODELABEL)
   DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_INST)

   /*
    * SPI device chip-select pin.
    *
    * These use /migration/spi@2000/spi-dev@0.
    * They all expand to 17, which is also from cs-gpios.
    */

   /* Legacy: */
   DT_VND_SPI_20000_VND_SPI_DEVICE_0_CS_GPIOS_PIN
   DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_PIN
   DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_PIN
   DT_INST_0_VND_SPI_DEVICE_CS_GPIOS_PIN

   /* Use these instead (extra #defines from above): */
   DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_PATH)
   DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_ALIAS)
   DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_NODEPIN)
   DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_INST)

   /*
    * SPI device chip-select pin's flags for the gpio.h API.
    *
    * These use /migration/spi@2000/spi-dev@0. They all expand to
    * GPIO_ACTIVE_LOW (technically, its numeric value after
    * preprocessing), which is also from cs-gpios.
    */

   /* Legacy: */
   DT_VND_SPI_20000_VND_SPI_DEVICE_0_CS_GPIOS_FLAGS
   DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_FLAGS
   DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_FLAGS
   DT_INST_0_VND_SPI_DEVICE_CS_GPIOS_FLAGS

   /* Use these instead (extra #defines from above): */
   DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_PATH)
   DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_ALIAS)
   DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_NODEFLAGS)
   DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_INST)

.. _dt-trouble:

Troubleshoot devicetree issues
+6 −3
Original line number Diff line number Diff line
@@ -5,10 +5,13 @@ Legacy devicetree macros

.. warning::

   You can still use the macros documented in this file, but support
   for them will be removed eventually.
   As of Zephyr v2.3, you can still use these macros if you set
   ``CONFIG_LEGACY_DEVICETREE_MACROS=y`` in your application's :ref:`kconfig`.
   Legacy macro support will be maintained for at least two releases, including
   v2.3 itself.

   See :ref:`dt-from-c` for a usage guide for the new API.
   See :ref:`dt-from-c` for a usage guide for the new API, and
   :ref:`dt-migrate-legacy` for a migration guide for existing code.

This page describes legacy C preprocessor macros which Zephyr's :ref:`build
system <build_overview>` generates from a devicetree. It assumes you're
+16 −0
Original line number Diff line number Diff line
description: Test serial port

compatible: "vnd,serial"

include: uart-controller.yaml

properties:
    reg:
      required: true

    interrupts:
      required: true

    baud-rate:
      type: int
      required: false
+9 −1
Original line number Diff line number Diff line
@@ -18,6 +18,13 @@ import sys

import edtlib

# Set this to True to generated deprecated macro warnings. Since this
# entire file is deprecated and must be explicitly enabled with
# CONFIG_LEGACY_DEVICETREE_MACROS, this was turned off by default
# shortly before the v2.3 release (this was the least impactful way to
# do it, which resulted in the smallest and least-risky patch).
DEPRECATION_MESSAGES = False

def main():
    global header_file
    global flash_area_num
@@ -768,7 +775,8 @@ def out_define(ident, val, deprecation_msg, out_file):
    # 'deprecation_msg'.

    s = f"#define DT_{ident:40}"
    if deprecation_msg:

    if DEPRECATION_MESSAGES and deprecation_msg:
        s += fr' __WARN("{deprecation_msg}")'
    s += f" {val}"
    print(s, file=out_file)
+10 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)

set(DTS_ROOTS ${CMAKE_CURRENT_LIST_DIR})
find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
project(devicetree)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
Loading