diff --git a/Kconfig.zephyr b/Kconfig.zephyr index e17956cc4ce..7b94a03bedc 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -342,13 +342,6 @@ config MAKEFILE_EXPORTS Generates a file with build information that can be read by third party Makefile-based build systems. -config LEGACY_DEVICETREE_MACROS - bool "Allow use of legacy devicetree macros" - help - Allows use of legacy devicetree macros which were used in - Zephyr 2.2 and previous versions, rather than the devicetree.h - API introduced during the Zephyr 2.3 development cycle. - config DEPRECATED_ZEPHYR_INT_TYPES bool "Allow the use of the deprecated zephyr integer types" help diff --git a/boards/arm/nucleo_f429zi/doc/index.rst b/boards/arm/nucleo_f429zi/doc/index.rst index f877613260f..55ec85f301d 100644 --- a/boards/arm/nucleo_f429zi/doc/index.rst +++ b/boards/arm/nucleo_f429zi/doc/index.rst @@ -189,7 +189,7 @@ Flash partitions for MCUBoot bootloader *************************************** The on-board STM32F429ZI MCU has 2MBs of internal flash memory. To use `MCUboot`_, -define a :ref:`Zephyr partition table ` for the flash memory in +define a :ref:`Zephyr partition table ` for the flash memory in its devicetree file ``nucleo_f429zi.dts``. As a reference, a partition table for MCUBoot is already defined in the devicetree file, with these settings: diff --git a/cmake/dts.cmake b/cmake/dts.cmake index 69cdb986bd1..69a96095281 100644 --- a/cmake/dts.cmake +++ b/cmake/dts.cmake @@ -4,15 +4,11 @@ file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include/generated) # Zephyr code can configure itself based on a KConfig'uration with the # header file autoconf.h. There exists an analogous file devicetree_unfixed.h -# that allows configuration based on information encoded in DTS, and a similar -# file with legacy contents called devicetree_unfixed_legacy.h. +# that allows configuration based on information encoded in DTS. # -# Here we call on dtc, the gcc preprocessor, -# scripts/dts/gen_defines.py, and scripts/dts/gen_legacy_defines.py to -# generate various DT-related files at CMake configure-time. -# -# The devicetree.conf file is still needed by some deprecated -# functions in kconfigfunctions.py. +# Here we call on dtc, the gcc preprocessor and +# scripts/dts/gen_defines.py to generate various DT-related files at +# CMake configure-time. # # See the Devicetree user guide in the Zephyr documentation for details. set(GEN_DEFINES_SCRIPT ${ZEPHYR_BASE}/scripts/dts/gen_defines.py) @@ -25,7 +21,6 @@ set(ZEPHYR_DTS ${PROJECT_BINARY_DIR}/zephyr.dts) # and should not be made part of the documentation. set(EDT_PICKLE ${PROJECT_BINARY_DIR}/edt.pickle) set(DEVICETREE_UNFIXED_H ${PROJECT_BINARY_DIR}/include/generated/devicetree_unfixed.h) -set(DEVICETREE_UNFIXED_LEGACY_H ${PROJECT_BINARY_DIR}/include/generated/devicetree_legacy_unfixed.h) set(DTS_POST_CPP ${PROJECT_BINARY_DIR}/${BOARD}.dts.pre.tmp) set_ifndef(DTS_SOURCE ${BOARD_DIR}/${BOARD}.dts) @@ -225,16 +220,6 @@ if(SUPPORTS_DTS) --edt-pickle-out ${EDT_PICKLE} ) - # - # Run gen_legacy_defines.py to create a header file with legacy contents - # and a .conf file. - # - - set(CMD_LEGACY_EXTRACT ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/dts/gen_legacy_defines.py - --edt-pickle ${EDT_PICKLE} - --header-out ${DEVICETREE_UNFIXED_LEGACY_H} - ) - execute_process( COMMAND ${CMD_EXTRACT} WORKING_DIRECTORY ${PROJECT_BINARY_DIR} @@ -247,15 +232,6 @@ if(SUPPORTS_DTS) message(STATUS "Generated devicetree_unfixed.h: ${DEVICETREE_UNFIXED_H}") endif() - execute_process( - COMMAND ${CMD_LEGACY_EXTRACT} - WORKING_DIRECTORY ${PROJECT_BINARY_DIR} - RESULT_VARIABLE ret - ) - if(NOT "${ret}" STREQUAL "0") - message(FATAL_ERROR "gen_legacy_defines.py failed with return code: ${ret}") - endif() - # A file that used to be generated by 'dtc'. zephyr.dts is the new # equivalent. Will be removed in Zephyr 2.3. file(WRITE ${PROJECT_BINARY_DIR}/${BOARD}.dts_compiled @@ -263,5 +239,4 @@ if(SUPPORTS_DTS) else() file(WRITE ${DEVICETREE_UNFIXED_H} "/* WARNING. THIS FILE IS AUTO-GENERATED. DO NOT MODIFY! */") - file(WRITE ${DEVICETREE_UNFIXED_LEGACY_H} "/* WARNING. THIS FILE IS AUTO-GENERATED. DO NOT MODIFY! */") endif(SUPPORTS_DTS) diff --git a/doc/guides/device_mgmt/dfu.rst b/doc/guides/device_mgmt/dfu.rst index 015b26f508e..732c187520e 100644 --- a/doc/guides/device_mgmt/dfu.rst +++ b/doc/guides/device_mgmt/dfu.rst @@ -34,8 +34,8 @@ is the boot loader used with Zephyr. The source code itself is hosted in the In order to use MCUboot with Zephyr you need to take the following into account: -1. You will need to define the :ref:`mcuboot_partitions` required by MCUboot in - the :ref:`legacy_flash_partitions`. +1. You will need to define the flash partitions required by MCUboot; see + :ref:`flash_map_api` for details. 2. Your application's :file:`.conf` file needs to enable the :option:`CONFIG_BOOTLOADER_MCUBOOT` Kconfig option in order for Zephyr to be built in an MCUboot-compatible manner diff --git a/doc/guides/dts/howtos.rst b/doc/guides/dts/howtos.rst index 9fb357af061..b2ca1e8d17b 100644 --- a/doc/guides/dts/howtos.rst +++ b/doc/guides/dts/howtos.rst @@ -566,218 +566,6 @@ done in the :ref:`blinky-sample`. The application can then be configured in :ref:`BOARD.dts ` files or via :ref:`devicetree 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 `. (Please feel free to :ref:`ask for 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 diff --git a/doc/guides/dts/index.rst b/doc/guides/dts/index.rst index 80070a4d161..8e1b7e7ff42 100644 --- a/doc/guides/dts/index.rst +++ b/doc/guides/dts/index.rst @@ -15,6 +15,5 @@ development. See :ref:`devicetree_api` for an API reference. design.rst bindings.rst api-usage.rst - legacy-macros.rst howtos.rst dt-vs-kconfig.rst diff --git a/doc/guides/dts/intro.rst b/doc/guides/dts/intro.rst index 9a408588bc6..6ec0794aca8 100644 --- a/doc/guides/dts/intro.rst +++ b/doc/guides/dts/intro.rst @@ -336,6 +336,8 @@ interrupts .. _Devicetree Specification release v0.3: https://www.devicetree.org/specifications/ +.. _dt-alias-chosen: + Aliases and chosen nodes ************************ @@ -514,10 +516,6 @@ These are created in your application's build directory. The generated macros and additional comments describing the devicetree. Included by ``devicetree.h``. -:file:`/zephyr/include/generated/devicetree_legacy_unfixed.h` - The generated :ref:`dt-legacy-macros`. - Included by ``devicetree.h``. - :file:`/zephyr/include/generated/devicetree_fixups.h` The concatenated contents of any :file:`dts_fixup.h` files. Included by ``devicetree.h``. diff --git a/doc/guides/dts/legacy-macros.bnf b/doc/guides/dts/legacy-macros.bnf deleted file mode 100644 index 05501d2b4bb..00000000000 --- a/doc/guides/dts/legacy-macros.bnf +++ /dev/null @@ -1,106 +0,0 @@ -; dt-macro is the top level nonterminal. It defines the possible -; macros generated by gen_defines.py. -; -; A dt-macro starts with uppercase "DT_" followed by either: -; -; - a property-macro, generated for a particular node -; property -; - some other-macro, a catch-all for other types of macros, -; which contain either global information about the tree or -; are special cases -; -; This does *not* cover macros pulled out of DT via Kconfig, -; like CONFIG_SRAM_BASE_ADDRESS, etc. -dt-macro = %s"DT_" ( property-macro / other-macro ) - -; -------------------------------------------------------------------- -; A property-macro is a sequence of: -; -; - node-id: a way to identify a node -; - property-id: a way to identify one of the node's properties -; - property-suf: an optional property-specific suffix -property-macro = node-id "_" property-id ["_" property-suf] - -; A node-id is a way to refer to a node within the devicetree. -; There are a few different flavors. - -node-id = compat-unit-id / inst-id / alias-id - -compat-unit-id = [bus-id-part "_"] compat-id-part "_" unit-addr-id-part -inst-id = %s"INST_" 1*DIGIT "_" compat-id-part -alias-id = %s"ALIAS_" alias-id-part - -; Various components of a property-macro are just c-idents, -; which are made of uppercase letters, numbers, and underscores. -; -; This is a problem, because it makes it possible for different nodes -; or properties in a devicetree to generate the same macro twice -; with different values. - -bus-id-part = c-ident ; ID for information about a node's bus -compat-id-part = c-ident ; ID for a node's compatible -unit-addr-id-part = c-ident ; ID for a node's unit-address -alias-id-part = c-ident ; ID for an /aliases node property -property-id = c-ident ; ID for a node property -- this also - ; covers special cases like "reg", - ; "interrupts", and "cs-gpios" for now, - ; as they all collide with non-special - ; cases. -property-suf = c-ident ; a suffix for part of a property value, - ; like an array index or a phandle - ; specifier name converted to a c-ident - -; -------------------------------------------------------------------- -; An other-macro is a grab bag for everything that isn't a -; property-macro. It reuses some of the nonterminals (namely node-id -; and compat-id-part) defined above. -other-macro = existence-flag / bus-macro / flash-macro / chosen-macro - -existence-flag = compat-existence-flag / inst-existence-flag -compat-flag = %s"COMPAT_" c-ident -inst-flag = %s"INST_" 1*DIGIT "_" c-ident - -bus-macro = bus-name-macro / on-bus-macro -bus-name-macro = node-id %s"_BUS_NAME" -on-bus-macro = compat-id-part %s"_BUS_" bus-name -bus-name = c-ident ; a bus name ("i2c") to a DT C - ; identifier ("I2C") - -flash-macro = %s"FLASH_AREA_" node-label-ident "_" flash-suf -flash-suf = %s"ID" / %s"READ_ONLY" / (%s"OFFSET" ["_" 1*DIGIT]) / - (%s"SIZE" ["_" 1*DIGIT]) / %s"DEV" - -; Macros generated from /chosen node properties. -chosen-macro = chosen-flash / - %s"CODE_PARTITION_OFFSET" / %s"CODE_PARTITION_SIZE" / - %s"CCM_BASE_ADDRESS" / %s"CCM_SIZE" / - %s"DTCM_BASE_ADDRESS" / %s"DTCM_SIZE" / - %s"IPC_SHM_BASE_ADDRESS" / %s"IPC_SHM_SIZE" -; These come from the /chosen/zephyr,flash property. -chosen-flash = %s"FLASH_BASE_ADDRESS" / - %s"FLASH_SIZE" / - %s"FLASH_ERASE_BLOCK_SIZE" / - %s"FLASH_WRITE_BLOCK_SIZE" - -; -------------------------------------------------------------------- -; Helper definitions. - -; A c-ident is one or more: -; - uppercase letters (A-Z) -; - numbers (0-9) -; - underscores ("_") -; -; They are the result of converting names or combinations of names -; from devicetree to a valid component of a C identifier by -; uppercasing letters and converting non-alphanumeric characters to -; underscores. -c-ident = 1*( UPPER / DIGIT / "_" ) - -; a node's "label" property value, as an identifier -node-label-ident = c-ident - -; "uppercase ASCII letter" turns out to be pretty annoying to specify -; in RFC-7405 syntax. -; -; This is just ASCII letters A (0x41) through Z (0x5A). -UPPER = %x41-5A diff --git a/doc/guides/dts/legacy-macros.rst b/doc/guides/dts/legacy-macros.rst deleted file mode 100644 index 6cd17018b27..00000000000 --- a/doc/guides/dts/legacy-macros.rst +++ /dev/null @@ -1,1154 +0,0 @@ -.. _dt-legacy-macros: - -Legacy devicetree macros -######################## - -.. warning:: - - 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, 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 ` generates from a devicetree. It assumes you're -familiar with the concepts in :ref:`devicetree-intro` and :ref:`dt-bindings`. - -These macros have somewhat inconsistent names, and their use in new code is -discouraged. See :ref:`dt-from-c` for the recommended API. - -These macros are generated by the :ref:`devicetree scripts `, -start with ``DT_``, and use all-uppercase. - -.. _dt-legacy-node-identifiers: - -Legacy node identifiers -*********************** - -Macros generated from individual devicetree nodes or their properties start -with ``DT_``, where ```` is a C identifier for the devicetree node. -This section describes the different ```` values in the legacy macros. - -.. _dt-legacy-node-main-ex: - -We'll use the following DTS fragment from the :ref:`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 -` 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 ` built for the ``frdm_k64f`` -board, in the file -:file:`build/zephyr/include/generated/devicetree_legacy_unfixed.h`. - -Here is part of :file:`devicetree_legacy_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_`` macro prefixes are created for each -node. - -``DT_(_)_`` - The node's compatible property converted to a C identifier, followed by its - :ref:`unit address `. If the node has multiple compatible - strings, the one for its :ref:`matching binding ` 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 ``_`` portion in the node - identifier. - - The ``i2c@40066000`` node identifier is ``NXP_KINETIS_I2C_40066000``: - - - there is no ``_`` portion - - ```` 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 - - ```` is ``40066000`` - - The ``fxos8700@1d`` node identifier is - ``NXP_KINETIS_I2C_40066000_NXP_FXOS8700_1D``: - - - ```` is ``NXP_KINETIS_I2C_40066000`` - - ```` is ``NXP_FXOS8700`` - - ```` 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 ```` - 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 ``_`` portion - - ```` is ``NXP_KINETIS_PTP`` - - ```` 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 ``_`` portion - - ```` is ``NXP_KINETIS_TEMPERATURE`` - - ```` is the fallback value ``TEMP1``, because neither - the node nor its parent have a unit address - -``DT_INST__`` - 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 - ` is ``INST_0_NXP_KINETIS_I2C``: - - - ```` 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 - - ```` 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_`` - Generated from the names of any properties in the ``/aliases`` node. - See :ref:`dt-alias-chosen` for an overview. - - Here is a simple example. - - .. code-block:: DTS - - / { - aliases { - uart-1 = &my_uart; - }; - - my_uart: uart@12345 { /* ... */ }; - }; - - The ``uart@12345`` node identifier is ``ALIAS_UART_1``: ```` is - ``UART_1`` by uppercasing ``uart-1`` and replacing non-alphanumeric - characters with underscores. The alias refers to ``uart@12345`` using its - :ref:`label ` ``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 ` is ``ALIAS_I2C_0``: - ```` 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:: - - Another ``DT__`` 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``. - -.. _legacy-property-macros: - -Macros generated for properties -******************************* - -Macros for node property values have the form ``DT__``, where -```` is a :ref:`node identifier ` and ```` -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-legacy-macros` -- :ref:`phandle-array-legacy-macros` -- :ref:`enum-legacy-macros` - -However, some "special" properties get individual treatment: - -- :ref:`reg_legacy_macros` -- :ref:`irq_legacy_macros` -- :ref:`clk_legacy_macros` -- :ref:`spi_cs_legacy_macros` - -No macros are currently generated for properties with type ``phandle``, -``phandles``, ``path``, or ``compound``. - -.. _generic-legacy-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 ```` portion of a ``DT__`` -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 ```` 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__FOO 1`` | -+------------------+------------------------+----------------------------------------+ -| ``array`` | ``foo = <1 2>`` | | ``#define DT__FOO_0 1`` | -| | | | ``#define DT__FOO_1 2`` | -| | | | ``#define DT__FOO {1, 2}`` | -+------------------+------------------------+----------------------------------------+ -| ``string`` | ``foo = "bar"`` | ``#define DT__FOO "bar"`` | -+------------------+------------------------+----------------------------------------+ -| ``string-array`` | ``foo = "bar", "baz"`` | | ``#define DT__FOO_0 "bar"`` | -| | | | ``#define DT__FOO_1 "baz"`` | -+------------------+------------------------+----------------------------------------+ -| ``uint8-array`` | ``foo = [01 02]`` | ``#define DT__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__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-legacy-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__PWMS_CONTROLLER_0 "pwm-0" - #define DT__PWMS_CHANNEL_0 1 - #define DT__PWMS_PERIOD_0 10 - - #define DT__PWMS_CONTROLLER_1 "pwm-1" - #define DT__PWMS_CHANNEL_1 2 - #define DT__PWMS_PERIOD_1 20 - - #define DT__PWMS_NAMES_0 "first" - #define DT__PWMS_NAMES_1 "second" - - #define DT__FIRST_PWMS_CONTROLLER DT__PWMS_CONTROLLER_0 - #define DT__FIRST_PWMS_CHANNEL DT__PWMS_CHANNEL_0 - #define DT__FIRST_PWMS_PERIOD DT__PWMS_PERIOD_0 - - #define DT__SECOND_PWMS_CONTROLLER DT__PWMS_CONTROLLER_1 - #define DT__SECOND_PWMS_CHANNEL DT__PWMS_CHANNEL_1 - #define DT__SECOND_PWMS_PERIOD DT__PWMS_PERIOD_1 - - /* Initializers */ - - #define DT__PWMS_0 {"pwm-0", 1, 10} - #define DT__PWMS_1 {"pwm-1", 2, 20} - #define DT__PWMS {DT__PWMS_0, DT__PWMS_1} - #define DT__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__PWMS_CONTROLLER(_)`` macros are set to the string from -the ``label`` property of the referenced controller. The -``DT__PWMS_CHANNEL(_)`` and ``DT__PWMS_PERIOD(_)`` -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__PWMS_{CONTROLLER,CHANNEL,PERIOD}(_)``, 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__FIRST_PWMS_CONTROLLER`` above. - -.. _enum-legacy-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__FOO_ENUM 2 - -.. _reg_legacy_macros: - -``reg`` property macros -======================= - -``reg`` properties generate the macros ``DT__BASE_ADDRESS(_)`` and -``DT__SIZE(_)``. ```` 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__BASE_ADDRESS 0x40047000 - #define DT__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__FOO_BASE_ADDRESS 0x40047000 - #define DT__FOO_SIZE 4192 - -.. _irq_legacy_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__IRQ_0 1 - #define DT__IRQ_0_PRIORITY 5 - #define DT__IRQ_1 2 - #define DT__IRQ_1_PRIORITY 6 - -These macros have the the format ``DT__IRQ_(_)``, where -```` is the node identifier for ``timer@123``, ```` is an index -that identifies the particular interrupt, and ```` 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 ``_`` suffix is -skipped for macros generated from ``irq`` cells, which is why there's e.g. a -``DT__IRQ_0`` macro and no ``DT__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__IRQ_TIMER_A 1 - #define DT__IRQ_TIMER_A_PRIORITY 5 - #define DT__IRQ_TIMER_B 2 - #define DT__IRQ_TIMER_B_PRIORITY 6 - -.. _clk_legacy_macros: - -``clocks`` property macros -========================== - -``clocks`` work the same as other :ref:`phandle-array-legacy-macros`, except the -generated macros have ``CLOCK`` in them instead of ``CLOCKS``, giving for -example ``DT__CLOCK_CONTROLLER_0`` instead of -``DT__CLOCKS_CONTROLLER_0``. - -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__CLOCKS_CLOCK_FREQUENCY - -.. _spi_cs_legacy_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-legacy-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__CS_GPIOS_CONTROLLER "GPIOA" - #define DT__CS_GPIOS_PIN 1 - -.. _other-macros: - -Other macros -************ - -These are generated in addition to macros generated for :ref:`properties -`. - -- :ref:`dt-existence-legacy-macros` -- :ref:`bus-legacy-macros` -- :ref:`flash-legacy-macros` - -.. _dt-existence-legacy-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_ 1 - -An existence flag is also written for all enabled nodes with a matching -compatible: - -.. code-block:: none - - #define DT_INST__ 1 - -For the ``i2c@40066000`` node in the :ref:`example ` 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-legacy-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__BUS_NAME "" - #define DT__BUS_ 1 - -```` is taken from the ``label`` property on the bus node, which -must exist. ```` is the identifier for the bus as given in -``on-bus:`` in the binding. - -.. _flash-legacy-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@``, 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_`` and ``*_SIZE_`` 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). - -.. _dt-alias-chosen: - -``aliases`` and ``chosen`` nodes -================================ - -Using an alias with a common name for a particular node makes it easier for you -to write board-independent source code. Devicetree ``aliases`` nodes are used -for this purpose, by mapping certain generic, commonly used names to specific -hardware resources: - -.. code-block:: yaml - - aliases { - led0 = &led0; - sw0 = &button0; - sw1 = &button1; - uart-0 = &uart0; - uart-1 = &uart1; - }; - -Certain software subsystems require a specific hardware resource to bind to in -order to function properly. Some of those subsystems are used with many -different boards, which makes using the devicetree ``chosen`` nodes very -convenient. By doing so, the software subsystem can rely on having the specific -hardware peripheral assigned to it. In the following example we bind the shell -to ``uart1`` in this board: - -.. code-block:: yaml - - chosen { - zephyr,shell-uart = &uart1; - }; - -The table below lists Zephyr-specific ``chosen`` properties. The macro -identifiers that start with ``CONFIG_*`` are generated from Kconfig symbols -that reference devicetree data via the :ref:`Kconfig preprocessor -`. - -.. note:: - - Since the particular devicetree isn't known while generating Kconfig - documentation, the Kconfig symbol reference pages linked below do not - include information derived from devicetree. Instead, you might see e.g. an - empty default: - - .. code-block:: none - - default "" if HAS_DTS - - To see how the preprocessor is used for a symbol, look it up directly in the - :file:`Kconfig` file where it is defined instead. The reference page for the - symbol gives the definition location. - -.. list-table:: - :header-rows: 1 - - * - ``chosen`` node name - - Generated macros - - * - ``zephyr,flash`` - - ``DT_FLASH_BASE_ADDRESS``/``DT_FLASH_SIZE``/``DT_FLASH_ERASE_BLOCK_SIZE``/``DT_FLASH_WRITE_BLOCK_SIZE`` - * - ``zephyr,code-partition`` - - ``DT_CODE_PARTITION_OFFSET``/``DT_CODE_PARTITION_SIZE`` - * - ``zephyr,sram`` - - :option:`CONFIG_SRAM_BASE_ADDRESS`/:option:`CONFIG_SRAM_SIZE` - * - ``zephyr,ccm`` - - ``DT_CCM_BASE_ADDRESS``/``DT_CCM_SIZE`` - * - ``zephyr,dtcm`` - - ``DT_DTCM_BASE_ADDRESS``/``DT_DTCM_SIZE`` - * - ``zephyr,ipc_shm`` - - ``DT_IPC_SHM_BASE_ADDRESS``/``DT_IPC_SHM_SIZE`` - * - ``zephyr,console`` - - :option:`CONFIG_UART_CONSOLE_ON_DEV_NAME` - * - ``zephyr,shell-uart`` - - :option:`CONFIG_UART_SHELL_ON_DEV_NAME` - * - ``zephyr,bt-uart`` - - :option:`CONFIG_BT_UART_ON_DEV_NAME` - * - ``zephyr,uart-pipe`` - - :option:`CONFIG_UART_PIPE_ON_DEV_NAME` - * - ``zephyr,bt-mon-uart`` - - :option:`CONFIG_BT_MONITOR_ON_DEV_NAME` - * - ``zephyr,bt-c2h-uart`` - - :option:`CONFIG_BT_CTLR_TO_HOST_UART_DEV_NAME` - * - ``zephyr,uart-mcumgr`` - - :option:`CONFIG_UART_MCUMGR_ON_DEV_NAME` - -.. _legacy_flash_partitions: - -Legacy flash partitions -*********************** - -Devicetree can be used to describe a partition layout for any flash -device in the system. - -Two important uses for this mechanism are: - -#. To force the Zephyr image to be linked into a specific area on - Flash. - - This is useful, for example, if the Zephyr image must be linked at - some offset from the flash device's start, to be loaded by a - bootloader at runtime. - -#. To generate compile-time definitions for the partition layout, - which can be shared by Zephyr subsystems and applications to - operate on specific areas in flash. - - This is useful, for example, to create areas for storing file - systems or other persistent state. These defines only describe the - boundaries of each partition. They don't, for example, initialize a - partition's flash contents with a file system. - -Partitions are generally managed using device tree overlays. See -:ref:`set-devicetree-overlays` for examples. - -Defining Partitions -=================== - -The partition layout for a flash device is described inside the -``partitions`` child node of the flash device's node in the device -tree. - -You can define partitions for any flash device on the system. - -Most Zephyr-supported SoCs with flash support in device tree -will define a label ``flash0``. This label refers to the primary -on-die flash programmed to run Zephyr. To generate partitions -for this device, add the following snippet to a device tree overlay -file: - -.. code-block:: DTS - - &flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Define your partitions here; see below */ - }; - }; - -To define partitions for another flash device, modify the above to -either use its label or provide a complete path to the flash device -node in the device tree. - -The content of the ``partitions`` node looks like this: - -.. code-block:: DTS - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition1_label: partition@START_OFFSET_1 { - label = "partition1_name"; - reg = <0xSTART_OFFSET_1 0xSIZE_1>; - }; - - /* ... */ - - partitionN_label: partition@START_OFFSET_N { - label = "partitionN_name"; - reg = <0xSTART_OFFSET_N 0xSIZE_N>; - }; - }; - -Where: - -- ``partitionX_label`` are device tree labels that can be used - elsewhere in the device tree to refer to the partition - -- ``partitionX_name`` controls how defines generated by the Zephyr - build system for this partition will be named - -- ``START_OFFSET_x`` is the start offset in hexadecimal notation of - the partition from the beginning of the flash device - -- ``SIZE_x`` is the hexadecimal size, in bytes, of the flash partition - -The partitions do not have to cover the entire flash device. The -device tree compiler currently does not check if partitions overlap; -you must ensure they do not when defining them. - -Example Primary Flash Partition Layout -====================================== - -Here is a complete (but hypothetical) example device tree overlay -snippet illustrating these ideas. Notice how the partitions do not -overlap, but also do not cover the entire device. - -.. code-block:: DTS - - &flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - code_dts_label: partition@8000 { - label = "zephyr-code"; - reg = <0x00008000 0x34000>; - }; - - data_dts_label: partition@70000 { - label = "application-data"; - reg = <0x00070000 0xD000>; - }; - }; - }; - -Linking Zephyr Within a Partition -================================= - -To force the linker to output a Zephyr image within a given flash -partition, add this to a device tree overlay: - -.. code-block:: DTS - - / { - chosen { - zephyr,code-partition = &slot0_partition; - }; - }; - -Then, enable the :option:`CONFIG_USE_DT_CODE_PARTITION` Kconfig option. - -Flash Partition Macros -====================== - -The Zephyr build system generates definitions for each flash device -partition. These definitions are available to any files which -include ````. - -Consider this flash partition: - -.. code-block:: DTS - - dts_label: partition@START_OFFSET { - label = "def-name"; - reg = <0xSTART_OFFSET 0xSIZE>; - }; - -The build system will generate the following corresponding defines: - -.. code-block:: c - - #define DT_FLASH_AREA_DEF_NAME_DEV "def-name" - #define DT_FLASH_AREA_DEF_NAME_OFFSET_0 0xSTART_OFFSET - #define DT_FLASH_AREA_DEF_NAME_SIZE_0 0xSIZE - #define DT_FLASH_AREA_DEF_NAME_OFFSET DT_FLASH_AREA_DEF_NAME_OFFSET_0 - #define DT_FLASH_AREA_DEF_NAME_SIZE DT_FLASH_AREA_DEF_NAME_SIZE_0 - -As you can see, the ``label`` property is capitalized when forming the -macro names. Other simple conversions to ensure it is a valid C -identifier, such as converting "-" to "_", are also performed. The -offsets and sizes are available as well. - -.. _mcuboot_partitions: - -MCUboot Partitions -================== - -`MCUboot`_ is a secure bootloader for 32-bit microcontrollers. - -Some Zephyr boards provide definitions for the flash partitions which -are required to build MCUboot itself, as well as any applications -which must be chain-loaded by MCUboot. - -The device tree labels for these partitions are: - -**boot_partition** - This is the partition where the bootloader is expected to be - placed. MCUboot's build system will attempt to link the MCUboot - image into this partition. - -**slot0_partition** - MCUboot loads the executable application image from this - partition. Any application bootable by MCUboot must be linked to run - from this partition. - -**slot1_partition** - This is the partition which stores firmware upgrade images. Zephyr - applications which receive firmware updates must ensure the upgrade - images are placed in this partition (the Zephyr DFU subsystem can be - used for this purpose). MCUboot checks for upgrade images in this - partition, and can move them to ``slot0_partition`` for execution. - The ``slot0_partition`` and ``slot1_partition`` must be the same - size. - -**scratch_partition** - This partition is used as temporary storage while swapping the - contents of ``slot0_partition`` and ``slot1_partition``. - -.. important:: - - Upgrade images are only temporarily stored in ``slot1_partition``. - They must be linked to execute of out of ``slot0_partition``. - -See the `MCUboot documentation`_ for more details on these partitions. - -.. _MCUboot: https://mcuboot.com/ - -.. _MCUboot documentation: - https://github.com/runtimeco/mcuboot/blob/master/docs/design.md#image-slots - -File System Partitions -====================== - -**storage_partition** - This is the area where e.g. LittleFS or NVS or FCB expects its partition. - -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:: legacy-macros.bnf - :language: abnf - -.. _RFC 7405: https://tools.ietf.org/html/rfc7405 -.. _RFC 5234: https://tools.ietf.org/html/rfc5234 diff --git a/doc/reference/devicetree/index.rst b/doc/reference/devicetree/index.rst index 1b43ae48c87..cea67c9366b 100644 --- a/doc/reference/devicetree/index.rst +++ b/doc/reference/devicetree/index.rst @@ -211,7 +211,8 @@ Fixed flash partitions These conveniences may be used for the special-purpose ``fixed-partitions`` compatible used to encode information about flash memory partitions in the -device tree. +device tree. See :zephyr_file:`dts/bindings/mtd/partition.yaml` for this +compatible's binding. .. doxygengroup:: devicetree-fixed-partition :project: Zephyr diff --git a/doc/reference/storage/flash_map/example_fragment.dts b/doc/reference/storage/flash_map/example_fragment.dts new file mode 100644 index 00000000000..cdcef3eacbe --- /dev/null +++ b/doc/reference/storage/flash_map/example_fragment.dts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + */ +/* start-after-here */ +/ { + soc { + flashctrl: flash-controller@deadbeef { + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0x0 0x100000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <0x1>; + #size-cells = <0x1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x10000>; + read-only; + }; + storage_partition: partition@1e000 { + label = "storage"; + reg = <0x1e000 0x2000>; + }; + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x20000 0x60000>; + }; + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x80000 0x60000>; + }; + scratch_partition: partition@e0000 { + label = "image-scratch"; + reg = <0xe0000 0x20000>; + }; + }; + }; + }; + }; +}; diff --git a/doc/reference/storage/flash_map/flash_map.rst b/doc/reference/storage/flash_map/flash_map.rst index eaf6e810a45..788451dfb88 100644 --- a/doc/reference/storage/flash_map/flash_map.rst +++ b/doc/reference/storage/flash_map/flash_map.rst @@ -1,36 +1,96 @@ .. _flash_map_api: -Flash map (flash_map) -########################## +Flash map +######### -Flash map is a way for storing flash partitioning information in one central -location in flash_area structures array form. +The ```` API allows accessing information about device +flash partitions via :c:struct:`flash_area` structures. -Flash map is generated from DTS based on content of :ref:`legacy_flash_partitions` -nodes. -The flash_area API provides a way to access data in the flash map. -The flash_area_open() API is the interface for obtaining the flash partitions -flash_area from the flash map. +Each ``struct flash_area`` describes a flash partition. The API provides access +to a "flash map", which contains predefined flash areas accessible via globally +unique ID numbers. You can also create ``flash_area`` structures at runtime for +application-specific purposes. +The ``flash_area`` structure contains the name of the flash device the +partition is part of; this name can be passed to :c:func:`device_get_binding` +to get the corresponding :c:struct:`device` structure which can be read and +written to using the :ref:`flash API `. The ``flash_area`` also +contains the start offset and size of the partition within the flash memory the +device represents. -Flash Area API (flash_area) -########################### +The flash_map.h API provides functions for operating on a ``flash_area``. The +main examples are :c:func:`flash_area_read` and :c:func:`flash_area_write`. +These functions are basically wrappers around the flash API with input +parameter range checks. Not all flash APIs have flash_map.h wrappers, but +:c:func:`flash_area_get_device` allows easily retrieving the ``struct device`` +from a ``struct flash_area``. -The flash_area concept combines methods for operating on a flash chunk -together with a description of this chunk. Its methods are basically wrappers -around the flash API, with input parameter range checks. Not all flash -operation are wrapped so an API call to retrieve the flash area driver is -included as well. The flash area methods are designed to be used along with -the flash_area structures of flash_map and user-specific flash_areas, with -the exception of the area_open API used to fetch a flash_area from -the flash_map. +Use :c:func:`flash_area_open()` to access a ``struct flash_area``. This +function takes a flash area ID number and returns a pointer to the flash area +structure. The ID number for a flash area can be obtained from a human-readable +"label" using :c:macro:`FLASH_AREA_ID`; these labels are obtained from the +devicetree as described below. +Relationship with Devicetree +**************************** + +The flash_map.h API uses data generated from the :ref:`devicetree_api`, in +particular its :ref:`devicetree-flash-api`. Zephyr additionally has some +partitioning conventions used for :ref:`dfu` via the MCUboot bootloader, as +well as defining partitions usable by :ref:`file systems ` or +other nonvolatile :ref:`storage `. + +Here is an example devicetree fragment which uses fixed flash partitions for +both MCUboot and a storage partition. Some details were left out for clarity. + +.. literalinclude:: example_fragment.dts + :language: DTS + :start-after: start-after-here + +The ``boot_partition``, ``slot0_partition``, ``slot1_partition``, and +``scratch_partition`` nodes are defined for MCUboot, though not all MCUboot +configurations require all of them to be defined. See the `MCUboot +documentation`_ for more details. + +The ``storage_partition`` node is defined for use by a file system or other +nonvolatile storage API. + +.. _MCUboot documentation: https://mcuboot.com/ + +To get a numeric flash area ID from one of the child nodes of the +``partitions`` node: + +#. take the node's ``label`` property value +#. lowercase it +#. convert all special characters to underscores (``_``) +#. pass the result **without quotes** to ``FLASH_AREA_ID()`` + +For example, the ``flash_area`` ID number for ``slot0_partition`` is +``FLASH_AREA_ID(image_0)``. + +The same rules apply for other macros which take a "label", such as +:c:macro:`FLASH_AREA_OFFSET` and :c:macro:`FLASH_AREA_SIZE`. For example, +``FLASH_AREA_OFFSET(image_0)`` would return the start offset for +``slot0_partition`` within its flash device. This is determined by the node's +:ref:`devicetree-reg-property`, and in this case is 0x20000. + +To get a pointer to the flash area structure and do something with it starting +with a devicetree label like ``"image-0"``, use something like this: + +.. code-block:: c + + struct flash_area *my_area; + int err = flash_area_open(FLASH_AREA_ID(image_0), &my_area); + + if (err != 0) { + handle_the_error(err); + } else { + flash_area_read(my_area, ...); + } API Reference ************* -flash_area API -============== - .. doxygengroup:: flash_area_api :project: Zephyr + :members: diff --git a/doc/releases/release-notes-2.3.rst b/doc/releases/release-notes-2.3.rst index 5d6d03104a3..b280d1b484c 100644 --- a/doc/releases/release-notes-2.3.rst +++ b/doc/releases/release-notes-2.3.rst @@ -133,8 +133,12 @@ Deprecated in this release * See :ref:`dt-from-c` for a high-level guide to the new API, and :ref:`devicetree_api` for an API reference. * Use of the legacy macros now requires explicitly enabling - :option:`CONFIG_LEGACY_DEVICETREE_MACROS`. See :ref:`dt-legacy-macros` for - more information, including a link to a migration guide to the new API. + ``CONFIG_LEGACY_DEVICETREE_MACROS``. See `the Zephyr v2.3 legacy devicetree + macro page`_ for more information, including a link to a migration guide to + the new API. + +.. _the Zephyr v2.3 legacy devicetree macro page: + https://docs.zephyrproject.org/2.3.0/guides/dts/legacy-macros.html#dt-legacy-macros * Other @@ -666,9 +670,12 @@ Build and Infrastructure * Devicetree * A new :ref:`devicetree_api` was added. This API is not generated, but is - still included via ````. The :ref:`dt-legacy-macros` are now - deprecated; users should replace the generated macros with new API. The - :ref:`dt-howtos` page has been extended for the new API, and a new + still included via ````. + + See `the Zephyr v2.3 legacy devicetree macro page`_ for more information, + including a link to a migration guide to the new API. + + The :ref:`dt-howtos` page has been extended for the new API, and a new :ref:`dt-from-c` API usage guide was also added. Libraries / Subsystems diff --git a/doc/releases/release-notes-2.5.rst b/doc/releases/release-notes-2.5.rst index 33739dc706d..fb618e95f2d 100644 --- a/doc/releases/release-notes-2.5.rst +++ b/doc/releases/release-notes-2.5.rst @@ -190,6 +190,11 @@ Build and Infrastructure * Devicetree * :c:macro:`DT_ENUM_IDX_OR`: new macro + * Support for legacy devicetree macros via + ``CONFIG_LEGACY_DEVICETREE_MACROS`` was removed. All devicetree-based code + should be using the new devicetree API introduced in Zephyr 2.3 and + documented in :ref:`dt-from-c`. Information on flash partitions has moved + to :ref:`flash_map_api`. Libraries / Subsystems ********************** diff --git a/include/devicetree.h b/include/devicetree.h index 49f2574264a..9f67b0aed15 100644 --- a/include/devicetree.h +++ b/include/devicetree.h @@ -16,20 +16,7 @@ #ifndef DEVICETREE_H #define DEVICETREE_H -#ifdef _LINKER -/* - * Linker scripts include this file too, and autoconf.h isn't - * automatically included for those files the way it is for C source - * files. Make sure we pull it in before using - * CONFIG_LEGACY_DEVICETREE_MACROS in that case. - */ -#include -#endif - #include -#ifdef CONFIG_LEGACY_DEVICETREE_MACROS -#include -#endif #include #include diff --git a/include/storage/flash_map.h b/include/storage/flash_map.h index dcfaa2edfd0..0f209036294 100644 --- a/include/storage/flash_map.h +++ b/include/storage/flash_map.h @@ -14,29 +14,22 @@ #define ZEPHYR_INCLUDE_STORAGE_FLASH_MAP_H_ /** - * @brief Abstraction over flash area and its driver which helps to operate on - * flash regions easily and effectively. + * @brief Abstraction over flash partitions/areas and their drivers * * @defgroup flash_area_api flash area Interface * @{ */ +/* + * This API makes it possible to operate on flash areas easily and + * effectively. + * + * The system contains global data about flash areas. Every area + * contains an ID number, offset, and length. + */ + /** * - * Provides abstraction of flash regions for type of use, - * for example, where's my image? - * - * System will contain a map which contains flash areas. Every - * region will contain flash identifier, offset within flash, and length. - * - * 1. This system map could be in a file within filesystem (Initializer - * must know/figure out where the filesystem is at). - * 2. Map could be at fixed location for project (compiled to code) - * 3. Map could be at specific place in flash (put in place at mfg time). - * - * Note that the map you use must be valid for BSP it's for, - * match the linker scripts when platform executes from flash, - * and match the target offset specified in download script. */ #include #include @@ -46,22 +39,32 @@ extern "C" { #endif -#define SOC_FLASH_0_ID 0 /** device_id for SoC flash memory driver */ -#define SPI_FLASH_0_ID 1 /** device_id for external SPI flash driver */ +/** Provided for compatibility with MCUboot */ +#define SOC_FLASH_0_ID 0 +/** Provided for compatibility with MCUboot */ +#define SPI_FLASH_0_ID 1 /** - * @brief Structure for store flash partition data + * @brief Flash partition * - * It is used as the flash_map array entry or stand-alone user data. Structure - * contains all data needed to operate on the flash partitions. + * This structure represents a fixed-size partition on a flash device. + * Each partition contains one or more flash sectors. */ struct flash_area { - uint8_t fa_id; /** ID of flash area */ + /** ID number */ + uint8_t fa_id; + /** Provided for compatibility with MCUboot */ uint8_t fa_device_id; uint16_t pad16; - off_t fa_off; /** flash partition offset */ - size_t fa_size; /** flash partition size */ - const char *fa_dev_name; /** flash device name */ + /** Start offset from the beginning of the flash device */ + off_t fa_off; + /** Total size */ + size_t fa_size; + /** + * Name of the flash device, suitable for passing to + * device_get_binding(). + */ + const char *fa_dev_name; }; /** @@ -71,8 +74,10 @@ struct flash_area { * consumes much less RAM than @ref flash_area */ struct flash_sector { - off_t fs_off; /** flash sector offset */ - size_t fs_size; /** flash sector size */ + /** Sector offset from the beginning of the flash device */ + off_t fs_off; + /** Sector size in bytes */ + size_t fs_size; }; #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY) diff --git a/samples/subsys/fs/littlefs/README.rst b/samples/subsys/fs/littlefs/README.rst index ff5c098c91c..b032f8a43bf 100644 --- a/samples/subsys/fs/littlefs/README.rst +++ b/samples/subsys/fs/littlefs/README.rst @@ -18,7 +18,7 @@ Requirements ************ The partition labeled "storage" will be used for the file system; see -:ref:`legacy_flash_partitions`. If that area does not already have a +:ref:`flash_map_api`. If that area does not already have a compatible littlefs file system its contents will be replaced by an empty file system. You will see diagnostics like this:: diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst index d07774f708f..b24aa911730 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst +++ b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst @@ -183,8 +183,7 @@ Flashing the sample image ************************* Upload the :file:`zephyr.signed.bin` file from the previous to image slot-0 of your -board. The location of image slot-0 varies by board, as described in -:ref:`mcuboot_partitions`. +board. See :ref:`flash_map_api` for details on flash partitioning. To upload the initial image file to an empty slot-0, we simply use ``west flash`` like normal. ``west flash`` will automatically detect slot-0 address and confirm diff --git a/samples/subsys/mgmt/updatehub/README.rst b/samples/subsys/mgmt/updatehub/README.rst index 8e0b633dda4..333b1fca714 100644 --- a/samples/subsys/mgmt/updatehub/README.rst +++ b/samples/subsys/mgmt/updatehub/README.rst @@ -150,8 +150,8 @@ Step 6: Flash the first image ============================= Upload the :file:`signed.bin` file from Step 4 to image slot-0 of your -board. The location of image slot-0 varies by board, as described in -:ref:`mcuboot_partitions`. For the frdm_k64f, slot-0 is located at address +board. The location of the slot 0 image varies by board; see +:ref:`flash_map_api` for details. For the frdm_k64f, slot-0 is located at address ``0xc000``. Using :file:`pyocd` you don't need to specify the slot-0 starting address. diff --git a/samples/subsys/usb/dfu/README.rst b/samples/subsys/usb/dfu/README.rst index ba44ca6d5cb..f18e22ee985 100644 --- a/samples/subsys/usb/dfu/README.rst +++ b/samples/subsys/usb/dfu/README.rst @@ -14,7 +14,7 @@ Requirements This project requires an USB device driver. Currently, the USB DFU class provided by the Zephyr project depends on DFU image manager and -partition layout. Refer to :ref:`legacy_flash_partitions` for details about +partition layout. Refer to :ref:`flash_map_api` for details about partition layout. You SoC must run MCUboot as the stage 1 bootloader. This sample is built as an application for the MCUboot bootloader. diff --git a/scripts/dts/edtlib.py b/scripts/dts/edtlib.py index 1b63b96e678..fa37228ee38 100644 --- a/scripts/dts/edtlib.py +++ b/scripts/dts/edtlib.py @@ -100,27 +100,6 @@ class EDT: nodes: A list of Node objects for the nodes that appear in the devicetree - compat2enabled: - A collections.defaultdict that maps each 'compatible' string that appears - on some enabled Node to a list of enabled Nodes. - - For example, edt.compat2enabled["bar"] would include the 'foo' and 'bar' - nodes below. - - foo { - compatible = "bar"; - status = "okay"; - ... - }; - bar { - compatible = "foo", "bar", "baz"; - status = "okay"; - ... - }; - - This exists only for the sake of gen_legacy_defines.py. It will probably - be removed following the Zephyr 2.3 release. - compat2nodes: A collections.defaultdict that maps each 'compatible' string that appears on some Node to a list of Nodes with that compatible. @@ -524,7 +503,6 @@ class EDT: self.label2node = OrderedDict() self.dep_ord2node = OrderedDict() - self.compat2enabled = defaultdict(list) self.compat2nodes = defaultdict(list) self.compat2okay = defaultdict(list) @@ -535,9 +513,6 @@ class EDT: for compat in node.compats: self.compat2nodes[compat].append(node) - if node.enabled: - self.compat2enabled[compat].append(node) - if node.status == "okay": self.compat2okay[compat].append(node) @@ -703,8 +678,8 @@ class Node: A non-negative integer value such that the value for a Node is less than the value for all Nodes that depend on it. - The ordinal is defined for all Nodes including those that are not - 'enabled', and is unique among nodes in its EDT 'nodes' list. + The ordinal is defined for all Nodes, and is unique among nodes in its + EDT 'nodes' list. required_by: A list with the nodes that directly depend on the node @@ -717,12 +692,6 @@ class Node: has no status property set. If the node's status property is "ok", it is converted to "okay" for consistency. - enabled: - True unless the node has 'status = "disabled"' - - This exists only for the sake of gen_legacy_defines.py. It will probably - be removed following the Zephyr 2.3 release. - read_only: True if the node has a 'read-only' property, and False otherwise @@ -866,11 +835,6 @@ class Node: return as_string - @property - def enabled(self): - "See the class docstring" - return "status" not in self._node.props or self.status != "disabled" - @property def read_only(self): "See the class docstring" @@ -1182,7 +1146,7 @@ class Node: prop = node.props.get(name) if not prop: - if required and self.enabled: + if required and self.status == "okay": _err("'{}' is marked as required in 'properties:' in {}, but " "does not appear in {!r}".format( name, self.binding_path, node)) diff --git a/scripts/dts/gen_legacy_defines.py b/scripts/dts/gen_legacy_defines.py deleted file mode 100755 index 0baa8d31655..00000000000 --- a/scripts/dts/gen_legacy_defines.py +++ /dev/null @@ -1,827 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2019 Nordic Semiconductor ASA -# Copyright (c) 2019 Linaro Limited -# SPDX-License-Identifier: BSD-3-Clause - -# This script is similar to gen_defines.py, but is for the legacy -# macro syntax used in e.g. Zephyr 2.2. -# -# It should be considered frozen code. New macro-related functionality -# should be done by modifying the macro namespaces managed by -# gen_defines.py. - -import argparse -import os -import pathlib -import pickle - -# 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 - - args = parse_args() - - with open(args.edt_pickle, 'rb') as f: - edt = pickle.load(f) - - header_file = open(args.header_out, "w", encoding="utf-8") - flash_area_num = 0 - - write_top_comment(edt) - - for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal): - write_node_comment(node) - - # Flash partition nodes are handled as a special case. It - # would be nicer if we had bindings that would let us - # avoid that, but this will do for now. - if node.name.startswith("partition@"): - write_flash_partition(node, flash_area_num) - flash_area_num += 1 - - if node.enabled and node.matching_compat: - write_regs(node) - write_irqs(node) - write_props(node) - write_clocks(node) - write_spi_dev(node) - write_bus(node) - write_existence_flags(node) - - out_comment("Compatibles appearing on enabled nodes") - for compat in sorted(edt.compat2enabled): - #define DT_COMPAT_ 1 - out(f"COMPAT_{str2ident(compat)}", 1) - - # Definitions derived from /chosen nodes - write_addr_size(edt, "zephyr,ccm", "CCM") - write_addr_size(edt, "zephyr,dtcm", "DTCM") - write_addr_size(edt, "zephyr,ipc_shm", "IPC_SHM") - write_flash(edt) - - header_file.close() - - -def parse_args(): - # Returns parsed command-line arguments - - parser = argparse.ArgumentParser() - parser.add_argument("--edt-pickle", required=True, - help="pickle file containing EDT object") - parser.add_argument("--header-out", required=True, - help="path to write header to") - - return parser.parse_args() - - -def write_top_comment(edt): - # Writes an overview comment with misc. info at the top of the header and - # configuration file - - s = f"""\ -Generated by gen_legacy_defines.py - -DTS input file: - {edt.dts_path} - -Directories with bindings: - {", ".join(map(relativize, edt.bindings_dirs))} - -Nodes in dependency order (ordinal and path): -""" - - for scc in edt.scc_order: - if len(scc) > 1: - err("cycle in devicetree involving " - + ", ".join(node.path for node in scc)) - s += f" {scc[0].dep_ordinal:<3} {scc[0].path}\n" - - s += """ -Definitions derived from these nodes in dependency order are next, -followed by tree-wide information (active compatibles, chosen nodes, -etc.). -""" - - out_comment(s, blank_before=False) - - -def write_node_comment(node): - # Writes a comment describing 'node' to the header and configuration file - - s = f"""\ -Devicetree node: - {node.path} -""" - if node.matching_compat: - if node.binding_path: - s += f""" -Binding (compatible = {node.matching_compat}): - {relativize(node.binding_path)} -""" - else: - s += f""" -Binding (compatible = {node.matching_compat}): - No yaml (bindings inferred from properties) -""" - else: - s += "\nNo matching binding.\n" - - s += f"\nDependency Ordinal: {node.dep_ordinal}\n" - - if node.depends_on: - s += "\nRequires:\n" - for dep in node.depends_on: - s += f" {dep.dep_ordinal:<3} {dep.path}\n" - - if node.required_by: - s += "\nSupports:\n" - for req in node.required_by: - s += f" {req.dep_ordinal:<3} {req.path}\n" - - if node.description: - # Indent description by two spaces - s += "\nDescription:\n" + \ - "\n".join(" " + line for line in - node.description.splitlines()) + \ - "\n" - - if not node.enabled: - s += "\nNode is disabled.\n" - - out_comment(s) - - -def relativize(path): - # If 'path' is within $ZEPHYR_BASE, returns it relative to $ZEPHYR_BASE, - # with a "$ZEPHYR_BASE/..." hint at the start of the string. Otherwise, - # returns 'path' unchanged. - - zbase = os.getenv("ZEPHYR_BASE") - if zbase is None: - return path - - try: - return str("$ZEPHYR_BASE" / pathlib.Path(path).relative_to(zbase)) - except ValueError: - # Not within ZEPHYR_BASE - return path - - -def write_regs(node): - # Writes address/size output for the registers in the node's 'reg' property - - def write_reg(reg, base_ident, val): - # Drop '_0' from the identifier if there's a single register, for - # backwards compatibility - if len(reg.node.regs) > 1: - ident = f"{base_ident}_{reg.node.regs.index(reg)}" - else: - ident = base_ident - - out_node(node, ident, val, - # Name alias from 'reg-names = ...' - f"{str2ident(reg.name)}_{base_ident}" if reg.name else None) - - for reg in node.regs: - write_reg(reg, "BASE_ADDRESS", hex(reg.addr)) - if reg.size: - write_reg(reg, "SIZE", reg.size) - - -def write_props(node): - # Writes any properties defined in the "properties" section of the binding - # for the node - - for prop in node.props.values(): - if not should_write(prop): - continue - - if prop.description is not None: - out_comment(prop.description, blank_before=False) - - ident = str2ident(prop.name) - - if prop.type == "boolean": - out_node(node, ident, 1 if prop.val else 0) - elif prop.type == "string": - out_node_s(node, ident, prop.val) - elif prop.type == "int": - out_node(node, ident, prop.val) - elif prop.type == "array": - for i, val in enumerate(prop.val): - out_node(node, f"{ident}_{i}", val) - out_node_init(node, ident, prop.val) - elif prop.type == "string-array": - for i, val in enumerate(prop.val): - out_node_s(node, f"{ident}_{i}", val) - elif prop.type == "uint8-array": - out_node_init(node, ident, - [f"0x{b:02x}" for b in prop.val]) - else: # prop.type == "phandle-array" - write_phandle_val_list(prop) - - # Generate DT_..._ENUM if there's an 'enum:' key in the binding - if prop.enum_index is not None: - out_node(node, ident + "_ENUM", prop.enum_index) - - -def should_write(prop): - # write_props() helper. Returns True if output should be generated for - # 'prop'. - - # Skip #size-cell and other property starting with #. Also skip mapping - # properties like 'gpio-map'. - if prop.name[0] == "#" or prop.name.endswith("-map"): - return False - - # See write_clocks() - if prop.name == "clocks": - return False - - # For these, Property.val becomes an edtlib.Node, a list of edtlib.Nodes, - # or None. Nothing is generated for them at the moment. - if prop.type in {"phandle", "phandles", "path", "compound"}: - return False - - # Skip properties that we handle elsewhere - if prop.name in { - "reg", "compatible", "status", "interrupts", - "interrupt-controller", "gpio-controller" - }: - return False - - return True - - -def write_bus(node): - # Generate bus-related #defines - - if not node.bus_node: - return - - if node.bus_node.label is None: - err(f"missing 'label' property on bus node {node.bus_node!r}") - - # #define DT__BUS_NAME - out_node_s(node, "BUS_NAME", str2ident(node.bus_node.label), "Macro is deprecated") - - for compat in node.compats: - # #define DT__BUS_ 1 - out(f"{str2ident(compat)}_BUS_{str2ident(node.on_bus)}", 1) - - -def write_existence_flags(node): - # Generate #defines of the form - # - # #define DT_INST__ 1 - # - # for enabled nodes. These are flags for which devices exist. - - for compat in node.compats: - instance_no = node.edt.compat2enabled[compat].index(node) - out(f"INST_{instance_no}_{str2ident(compat)}", 1) - - -def node_ident(node): - # Returns an identifier for 'node'. Used e.g. when building macro names. - - # TODO: Handle PWM on STM - # TODO: Better document the rules of how we generate things - - ident = "" - - if node.bus_node: - if node.bus_node.unit_addr is not None: - ident += "{}_{:X}_".format( - str2ident(node.bus_node.matching_compat), node.bus_node.unit_addr) - else: - ident += str2ident(node.bus_node.matching_compat) - - ident += f"{str2ident(node.matching_compat)}_" - - if node.unit_addr is not None: - ident += f"{node.unit_addr:X}" - elif node.parent.unit_addr is not None: - ident += f"{node.parent.unit_addr:X}_{str2ident(node.name)}" - else: - # This is a bit of a hack - ident += str2ident(node.name) - - return ident - - -def node_aliases(node): - # Returns a list of aliases for 'node', used e.g. when building macro names - - return node_path_aliases(node) + node_instance_aliases(node) - - -def node_path_aliases(node): - # Returns a list of aliases for 'node', based on the aliases registered for - # it in the /aliases node. Used e.g. when building macro names. - - if node.matching_compat is None: - return [] - - compat_s = str2ident(node.matching_compat) - - aliases = [] - for alias in node.aliases: - aliases.append(f"ALIAS_{str2ident(alias)}") - # TODO: See if we can remove or deprecate this form - aliases.append(f"{compat_s}_{str2ident(alias)}") - - return aliases - - -def node_instance_aliases(node): - # Returns a list of aliases for 'node', based on the compatible string and - # the instance number (each node with a particular compatible gets its own - # instance number, starting from zero). - # - # This is a list since a node can have multiple 'compatible' strings, each - # with their own instance number. - - res = [] - for compat in node.compats: - instance_no = node.edt.compat2enabled[compat].index(node) - res.append(f"INST_{instance_no}_{str2ident(compat)}") - return res - - -def write_addr_size(edt, prop_name, prefix): - # Writes _BASE_ADDRESS and _SIZE for the node pointed at by - # the /chosen property named 'prop_name', if it exists - - node = edt.chosen_node(prop_name) - if not node: - return - - if not node.regs: - err("missing 'reg' property in node pointed at by " - f"/chosen/{prop_name} ({node!r})") - - out_comment(f"/chosen/{prop_name} ({node.path})") - out(f"{prefix}_BASE_ADDRESS", hex(node.regs[0].addr)) - out(f"{prefix}_SIZE", node.regs[0].size//1024) - - -def write_flash(edt): - # Writes chosen and tree-wide flash-related output - - write_flash_node(edt) - write_code_partition(edt) - - if flash_area_num != 0: - out_comment("Number of flash partitions") - out("FLASH_AREA_NUM", flash_area_num) - - -def write_flash_node(edt): - # Writes output for the top-level flash node pointed at by - # zephyr,flash in /chosen - - node = edt.chosen_node("zephyr,flash") - - out_comment(f"/chosen/zephyr,flash ({node.path if node else 'missing'})") - - if not node: - # No flash node. Write dummy values. - out("FLASH_BASE_ADDRESS", 0) - out("FLASH_SIZE", 0) - return - - if len(node.regs) != 1: - err("expected zephyr,flash to have a single register, has " - f"{len(node.regs)}") - - if node.on_bus == "spi" and len(node.bus_node.regs) == 2: - reg = node.bus_node.regs[1] # QSPI flash - else: - reg = node.regs[0] - - out("FLASH_BASE_ADDRESS", hex(reg.addr)) - if reg.size: - out("FLASH_SIZE", reg.size//1024) - - if "erase-block-size" in node.props: - out("FLASH_ERASE_BLOCK_SIZE", node.props["erase-block-size"].val) - - if "write-block-size" in node.props: - out("FLASH_WRITE_BLOCK_SIZE", node.props["write-block-size"].val) - - -def write_code_partition(edt): - # Writes output for the node pointed at by zephyr,code-partition in /chosen - - node = edt.chosen_node("zephyr,code-partition") - - out_comment("/chosen/zephyr,code-partition " - f"({node.path if node else 'missing'})") - - if not node: - # No code partition. Write dummy values. - out("CODE_PARTITION_OFFSET", 0) - out("CODE_PARTITION_SIZE", 0) - return - - if not node.regs: - err(f"missing 'regs' property on {node!r}") - - out("CODE_PARTITION_OFFSET", node.regs[0].addr) - out("CODE_PARTITION_SIZE", node.regs[0].size) - - -def write_flash_partition(partition_node, index): - if partition_node.label is None: - err(f"missing 'label' property on {partition_node!r}") - - # Generate label-based identifiers - write_flash_partition_prefix( - "FLASH_AREA_" + str2ident(partition_node.label), partition_node, index) - - # Generate index-based identifiers - write_flash_partition_prefix(f"FLASH_AREA_{index}", partition_node, index) - - -def write_flash_partition_prefix(prefix, partition_node, index): - # write_flash_partition() helper. Generates identifiers starting with - # 'prefix'. - - out(f"{prefix}_ID", index) - - out(f"{prefix}_READ_ONLY", 1 if partition_node.read_only else 0) - - for i, reg in enumerate(partition_node.regs): - # Also add aliases that point to the first sector (TODO: get rid of the - # aliases?) - out(f"{prefix}_OFFSET_{i}", reg.addr, - aliases=[f"{prefix}_OFFSET"] if i == 0 else []) - out(f"{prefix}_SIZE_{i}", reg.size, - aliases=[f"{prefix}_SIZE"] if i == 0 else []) - - controller = partition_node.flash_controller - if controller.label is not None: - out_s(f"{prefix}_DEV", controller.label) - - -def write_irqs(node): - # Writes IRQ num and data for the interrupts in the node's 'interrupt' - # property - - def irq_name_alias(irq, cell_name): - if not irq.name: - return None - - alias = f"IRQ_{str2ident(irq.name)}" - if cell_name != "irq": - alias += f"_{str2ident(cell_name)}" - return alias - - def map_arm_gic_irq_type(irq, irq_num): - # Maps ARM GIC IRQ (type)+(index) combo to linear IRQ number - if "type" not in irq.data: - err(f"Expected binding for {irq.controller!r} to have 'type' in " - "interrupt-cells") - irq_type = irq.data["type"] - - if irq_type == 0: # GIC_SPI - return irq_num + 32 - if irq_type == 1: # GIC_PPI - return irq_num + 16 - err(f"Invalid interrupt type specified for {irq!r}") - - def encode_zephyr_multi_level_irq(irq, irq_num): - # See doc/reference/kernel/other/interrupts.rst for details - # on how this encoding works - - irq_ctrl = irq.controller - # Look for interrupt controller parent until we have none - while irq_ctrl.interrupts: - irq_num = (irq_num + 1) << 8 - if "irq" not in irq_ctrl.interrupts[0].data: - err(f"Expected binding for {irq_ctrl!r} to have 'irq' in " - "interrupt-cells") - irq_num |= irq_ctrl.interrupts[0].data["irq"] - irq_ctrl = irq_ctrl.interrupts[0].controller - return irq_num - - for irq_i, irq in enumerate(node.interrupts): - for cell_name, cell_value in irq.data.items(): - ident = f"IRQ_{irq_i}" - if cell_name == "irq": - if "arm,gic" in irq.controller.compats: - cell_value = map_arm_gic_irq_type(irq, cell_value) - cell_value = encode_zephyr_multi_level_irq(irq, cell_value) - else: - ident += f"_{str2ident(cell_name)}" - - out_node(node, ident, cell_value, - name_alias=irq_name_alias(irq, cell_name)) - - -def write_spi_dev(node): - # Writes SPI device GPIO chip select data if there is any - - cs_gpio = node.spi_cs_gpio - if cs_gpio is not None: - write_phandle_val_list_entry(node, cs_gpio, None, "CS_GPIOS") - - -def write_phandle_val_list(prop): - # Writes output for a phandle/value list, e.g. - # - # pwms = <&pwm-ctrl-1 10 20 - # &pwm-ctrl-2 30 40>; - # - # prop: - # phandle/value Property instance. - # - # If only one entry appears in 'prop' (the example above has two), the - # generated identifier won't get a '_0' suffix, and the '_COUNT' and - # group initializer are skipped too. - # - # The base identifier is derived from the property name. For example, 'pwms = ...' - # generates output like this: - # - # #define _PWMS_CONTROLLER_0 "PWM_0" (name taken from 'label = ...') - # #define _PWMS_CHANNEL_0 123 (name taken from *-cells in binding) - # #define _PWMS_0 {"PWM_0", 123} - # #define _PWMS_CONTROLLER_1 "PWM_1" - # #define _PWMS_CHANNEL_1 456 - # #define _PWMS_1 {"PWM_1", 456} - # #define _PWMS_COUNT 2 - # #define _PWMS {_PWMS_0, _PWMS_1} - # ... - - # pwms -> PWMS - # foo-gpios -> FOO_GPIOS - ident = str2ident(prop.name) - - initializer_vals = [] - for i, entry in enumerate(prop.val): - initializer_vals.append(write_phandle_val_list_entry( - prop.node, entry, i if len(prop.val) > 1 else None, ident)) - - if len(prop.val) > 1: - out_node(prop.node, ident + "_COUNT", len(initializer_vals)) - out_node_init(prop.node, ident, initializer_vals) - - -def write_phandle_val_list_entry(node, entry, i, ident): - # write_phandle_val_list() helper. We could get rid of it if it wasn't for - # write_spi_dev(). Adds 'i' as an index to identifiers unless it's None. - # - # 'entry' is an edtlib.ControllerAndData instance. - # - # Returns the identifier for the macro that provides the - # initializer for the entire entry. - - initializer_vals = [] - if entry.controller.label is not None: - ctrl_ident = ident + "_CONTROLLER" # e.g. PWMS_CONTROLLER - if entry.name: - name_alias = f"{str2ident(entry.name)}_{ctrl_ident}" - else: - name_alias = None - # Ugly backwards compatibility hack. Only add the index if there's - # more than one entry. - if i is not None: - ctrl_ident += f"_{i}" - initializer_vals.append(quote_str(entry.controller.label)) - out_node_s(node, ctrl_ident, entry.controller.label, name_alias) - - for cell, val in entry.data.items(): - cell_ident = f"{ident}_{str2ident(cell)}" # e.g. PWMS_CHANNEL - if entry.name: - # From e.g. 'pwm-names = ...' - name_alias = f"{str2ident(entry.name)}_{cell_ident}" - else: - name_alias = None - # Backwards compatibility (see above) - if i is not None: - cell_ident += f"_{i}" - out_node(node, cell_ident, val, name_alias) - - initializer_vals += entry.data.values() - - initializer_ident = ident - if entry.name: - name_alias = f"{initializer_ident}_{str2ident(entry.name)}" - else: - name_alias = None - if i is not None: - initializer_ident += f"_{i}" - return out_node_init(node, initializer_ident, initializer_vals, name_alias) - - -def write_clocks(node): - # Writes clock information. - # - # Most of this ought to be handled in write_props(), but the identifiers - # that get generated for 'clocks' are inconsistent with the with other - # 'phandle-array' properties. - # - # See https://github.com/zephyrproject-rtos/zephyr/pull/19327#issuecomment-534081845. - - if "clocks" not in node.props: - return - - for clock_i, clock in enumerate(node.props["clocks"].val): - controller = clock.controller - - if controller.label is not None: - out_node_s(node, "CLOCK_CONTROLLER", controller.label) - - for name, val in clock.data.items(): - if clock_i == 0: - clk_name_alias = "CLOCK_" + str2ident(name) - else: - clk_name_alias = None - - out_node(node, f"CLOCK_{str2ident(name)}_{clock_i}", val, - name_alias=clk_name_alias) - - if "fixed-clock" not in controller.compats: - continue - - if "clock-frequency" not in controller.props: - err(f"{controller!r} is a 'fixed-clock' but lacks a " - "'clock-frequency' property") - - out_node(node, "CLOCKS_CLOCK_FREQUENCY", - controller.props["clock-frequency"].val) - - -def str2ident(s): - # Converts 's' to a form suitable for (part of) an identifier - - return s.replace("-", "_") \ - .replace(",", "_") \ - .replace("@", "_") \ - .replace("/", "_") \ - .replace(".", "_") \ - .replace("+", "PLUS") \ - .upper() - - -def out_node(node, ident, val, name_alias=None, deprecation_msg=None): - # Writes a - # - # _ = - # - # assignment, along with a set of - # - # _ - # - # aliases, for each path/instance alias for the node. If 'name_alias' (a - # string) is passed, then these additional aliases are generated: - # - # _ - # _ (for each node alias) - # - # 'name_alias' is used for reg-names and the like. - # - # If a 'deprecation_msg' string is passed, the generated identifiers will - # generate a warning if used, via __WARN()). - # - # Returns the identifier used for the macro that provides the value - # for 'ident' within 'node', e.g. DT_MFG_MODEL_CTL_GPIOS_PIN. - - node_prefix = node_ident(node) - - aliases = [f"{alias}_{ident}" for alias in node_aliases(node)] - if name_alias is not None: - aliases.append(f"{node_prefix}_{name_alias}") - aliases += [f"{alias}_{name_alias}" for alias in node_aliases(node)] - - return out(f"{node_prefix}_{ident}", val, aliases, deprecation_msg) - - -def out_node_s(node, ident, s, name_alias=None, deprecation_msg=None): - # Like out_node(), but emits 's' as a string literal - # - # Returns the generated macro name for 'ident'. - - return out_node(node, ident, quote_str(s), name_alias, deprecation_msg) - - -def out_node_init(node, ident, elms, name_alias=None, deprecation_msg=None): - # Like out_node(), but generates an {e1, e2, ...} initializer with the - # elements in the iterable 'elms'. - # - # Returns the generated macro name for 'ident'. - - return out_node(node, ident, "{" + ", ".join(map(str, elms)) + "}", - name_alias, deprecation_msg) - - -def out_s(ident, val): - # Like out(), but puts quotes around 'val' and escapes any double - # quotes and backslashes within it - # - # Returns the generated macro name for 'ident'. - - return out(ident, quote_str(val)) - - -def out(ident, val, aliases=(), deprecation_msg=None): - # Writes '#define ' to the header and '=' to the - # the configuration file. - # - # Also writes any aliases listed in 'aliases' (an iterable). For the - # header, these look like '#define '. For the configuration - # file, the value is just repeated as '=' for each alias. - # - # See out_node() for the meaning of 'deprecation_msg'. - # - # Returns the generated macro name for 'ident'. - - out_define(ident, val, deprecation_msg, header_file) - primary_ident = f"DT_{ident}" - - d_msg = deprecation_msg - - for alias in aliases: - if alias != ident: - if alias.startswith("INST_"): - deprecation_msg = "Macro is deprecated" - - out_define(alias, "DT_" + ident, deprecation_msg, header_file) - - deprecation_msg = d_msg - - return primary_ident - - -def out_define(ident, val, deprecation_msg, out_file): - # out() helper for writing a #define. See out_node() for the meaning of - # 'deprecation_msg'. - - s = f"#define DT_{ident:40}" - - if DEPRECATION_MESSAGES and deprecation_msg: - s += fr' __WARN("{deprecation_msg}")' - s += f" {val}" - print(s, file=out_file) - - -def out_comment(s, blank_before=True): - # Writes 's' as a comment to the header and configuration file. 's' is - # allowed to have multiple lines. blank_before=True adds a blank line - # before the comment. - - if blank_before: - print(file=header_file) - - if "\n" in s: - # Format multi-line comments like - # - # /* - # * first line - # * second line - # * - # * empty line before this line - # */ - res = ["/*"] - for line in s.splitlines(): - # Avoid an extra space after '*' for empty lines. They turn red in - # Vim if space error checking is on, which is annoying. - res.append(" *" if not line.strip() else " * " + line) - res.append(" */") - print("\n".join(res), file=header_file) - else: - # Format single-line comments like - # - # /* foo bar */ - print("/* " + s + " */", file=header_file) - - -def escape(s): - # Backslash-escapes any double quotes and backslashes in 's' - - # \ must be escaped before " to avoid double escaping - return s.replace("\\", "\\\\").replace('"', '\\"') - - -def quote_str(s): - # Puts quotes around 's' and escapes any double quotes and - # backslashes within it - - return f'"{escape(s)}"' - - -def err(s): - raise Exception(s) - - -if __name__ == "__main__": - main() diff --git a/scripts/dts/test.dts b/scripts/dts/test.dts index 8bc4d43d708..e1d2865d9c2 100644 --- a/scripts/dts/test.dts +++ b/scripts/dts/test.dts @@ -311,31 +311,6 @@ default-not-used = <234>; }; - // - // For testing EDT.compat2enabled - // - - compat2enabled { - foo-1 { - status = "okay"; - compatible = "compat2enabled"; - }; - foo-disabled { - status = "disabled"; - compatible = "compat2enabled"; - }; - foo-2 { - // No 'status', which is also treated as enabled - compatible = "compat2enabled"; - }; - // Should not create an entry in compat2enabled, since all nodes - // with the compatible are disabled - bar { - status = "disabled"; - compatible = "compat2enabled-disabled"; - }; - }; - // // For testing 'bus:' and 'on-bus:' // diff --git a/scripts/dts/testedtlib.py b/scripts/dts/testedtlib.py index a2b02475be3..48ec03a8590 100644 --- a/scripts/dts/testedtlib.py +++ b/scripts/dts/testedtlib.py @@ -155,15 +155,6 @@ def test_child_binding(): assert str(grandchild.description) == "grandchild node" assert str(grandchild.props) == "OrderedDict([('grandchild-prop', )])" -def test_compat2enabled(): - '''Test EDT.compat2enabled''' - edt = edtlib.EDT("test.dts", ["test-bindings"]) - - assert str(edt.compat2enabled["compat2enabled"]) == \ - "[, ]" - - assert "compat2enabled-disabled" not in edt.compat2enabled - def test_props(): '''Test Node.props (derived from DT and 'properties:' in the binding)''' edt = edtlib.EDT("test.dts", ["test-bindings"]) diff --git a/scripts/kconfig/kconfigfunctions.py b/scripts/kconfig/kconfigfunctions.py index 957676ae9d7..17ba32dc5e7 100644 --- a/scripts/kconfig/kconfigfunctions.py +++ b/scripts/kconfig/kconfigfunctions.py @@ -72,7 +72,7 @@ def dt_chosen_enabled(kconf, _, chosen): return "n" node = edt.chosen_node(chosen) - return "y" if node and node.enabled else "n" + return "y" if node and node.status == "okay" else "n" def dt_chosen_path(kconf, _, chosen): @@ -117,7 +117,7 @@ def dt_node_enabled(kconf, name, node): except edtlib.EDTError: return "n" - return "y" if node and node.enabled else "n" + return "y" if node and node.status == "okay" else "n" def dt_nodelabel_enabled(kconf, _, label): @@ -132,7 +132,7 @@ def dt_nodelabel_enabled(kconf, _, label): node = edt.label2node.get(label) - return "y" if node and node.enabled else "n" + return "y" if node and node.status == "okay" else "n" def _node_reg_addr(node, index, unit): @@ -350,13 +350,13 @@ def dt_node_int_prop(kconf, name, path, prop): def dt_compat_enabled(kconf, _, compat): """ - This function takes a 'compat' and returns "y" if we find an "enabled" + This function takes a 'compat' and returns "y" if we find a status "okay" compatible node in the EDT otherwise we return "n" """ if doc_mode or edt is None: return "n" - return "y" if compat in edt.compat2enabled else "n" + return "y" if compat in edt.compat2okay else "n" def dt_compat_on_bus(kconf, _, compat, bus): @@ -367,7 +367,7 @@ def dt_compat_on_bus(kconf, _, compat, bus): if doc_mode or edt is None: return "n" - for node in edt.compat2enabled[compat]: + for node in edt.compat2okay[compat]: if node.on_bus is not None and node.on_bus == bus: return "y" @@ -383,7 +383,7 @@ def dt_nodelabel_has_compat(kconf, _, label, compat): if doc_mode or edt is None: return "n" - for node in edt.compat2enabled[compat]: + for node in edt.compat2okay[compat]: if label in node.labels: return "y" diff --git a/scripts/sanity_chk/expr_parser.py b/scripts/sanity_chk/expr_parser.py index b0c87208fdd..4fc324adeb6 100644 --- a/scripts/sanity_chk/expr_parser.py +++ b/scripts/sanity_chk/expr_parser.py @@ -224,20 +224,20 @@ def ast_expr(ast, env, edt): elif ast[0] == "dt_compat_enabled": compat = ast[1][0] for node in edt.nodes: - if compat in node.compats and node.enabled: + if compat in node.compats and node.status == "okay": return True return False elif ast[0] == "dt_alias_exists": alias = ast[1][0] for node in edt.nodes: - if alias in node.aliases and node.enabled: + if alias in node.aliases and node.status == "okay": return True return False elif ast[0] == "dt_compat_enabled_with_alias": compat = ast[1][0] alias = ast[1][1] for node in edt.nodes: - if node.enabled and alias in node.aliases and node.matching_compat == compat: + if node.status == "okay" and alias in node.aliases and node.matching_compat == compat: return True return False diff --git a/tests/deprecated/dts/CMakeLists.txt b/tests/deprecated/dts/CMakeLists.txt deleted file mode 100644 index 5333a6ad575..00000000000 --- a/tests/deprecated/dts/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.13.1) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(test_dts) - -target_sources(app PRIVATE src/main.c) diff --git a/tests/deprecated/dts/boards/frdm_k64f.overlay b/tests/deprecated/dts/boards/frdm_k64f.overlay deleted file mode 100644 index f036a555b48..00000000000 --- a/tests/deprecated/dts/boards/frdm_k64f.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2020, Linaro Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&storage_partition { - status = "disabled"; -}; diff --git a/tests/deprecated/dts/prj.conf b/tests/deprecated/dts/prj.conf deleted file mode 100644 index 10e909f1dde..00000000000 --- a/tests/deprecated/dts/prj.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_LEGACY_DEVICETREE_MACROS=y diff --git a/tests/deprecated/dts/src/main.c b/tests/deprecated/dts/src/main.c deleted file mode 100644 index d4b647e118e..00000000000 --- a/tests/deprecated/dts/src/main.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2020 Linaro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -void main(void) -{ - BUILD_ASSERT(DT_FLASH_AREA_MCUBOOT_ID == FLASH_AREA_ID(mcuboot), - "FLASH AREA ID mismatch for MCUBOOT partition"); - /* disabled status is ignored for partitions */ - BUILD_ASSERT(DT_FLASH_AREA_STORAGE_ID == FLASH_AREA_ID(storage), - "FLASH AREA ID mismatch for STORAGE partition"); - BUILD_ASSERT(DT_FLASH_AREA_IMAGE_0_ID == FLASH_AREA_ID(image_0), - "FLASH AREA ID mismatch for IMAGE_0 partition"); - BUILD_ASSERT(DT_FLASH_AREA_IMAGE_1_ID == FLASH_AREA_ID(image_1), - "FLASH AREA ID mismatch for IMAGE_1 partition"); - BUILD_ASSERT(DT_FLASH_AREA_IMAGE_SCRATCH_ID == - FLASH_AREA_ID(image_scratch), - "FLASH AREA ID mismatch for IMAGE_SCRATCH partition"); -} diff --git a/tests/deprecated/dts/testcase.yaml b/tests/deprecated/dts/testcase.yaml deleted file mode 100644 index cae0776426e..00000000000 --- a/tests/deprecated/dts/testcase.yaml +++ /dev/null @@ -1,4 +0,0 @@ -tests: - dts.build.build: - build_only: true - platform_allow: frdm_k64f diff --git a/tests/lib/devicetree/legacy_api/CMakeLists.txt b/tests/lib/devicetree/legacy_api/CMakeLists.txt deleted file mode 100644 index 60a04403df7..00000000000 --- a/tests/lib/devicetree/legacy_api/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.13.1) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(devicetree) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/tests/lib/devicetree/legacy_api/README b/tests/lib/devicetree/legacy_api/README deleted file mode 100644 index 5ecfd2cc5b4..00000000000 --- a/tests/lib/devicetree/legacy_api/README +++ /dev/null @@ -1,5 +0,0 @@ -Test cases that ensure the legacy macros match the results for the -devicetree.h API. This directory is safe to remove once the legacy -devicetree macros documented here are no longer supported: - -https://docs.zephyrproject.org/latest/guides/dts/legacy-macros.html diff --git a/tests/lib/devicetree/legacy_api/app.overlay b/tests/lib/devicetree/legacy_api/app.overlay deleted file mode 100644 index 3ff374d5eeb..00000000000 --- a/tests/lib/devicetree/legacy_api/app.overlay +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - * - * Application overlay for testing the legacy devicetree macros can - * be migrated to the devicetree.h API. - * - * Names in this file should be chosen in a way that won't conflict - * with real-world devicetree nodes, to allow these tests to run on - * (and be extended to test) real hardware. - */ -#include - -/* - * The "start-after..." and "end-before..." comments are because - * this file is included in the migration HOWTO. - */ - -/* start-after-here */ -/ { - aliases { - mgr-gpio = &migration_gpio; - mgr-serial = &migration_serial; - mgr-i2c-dev = &mgr_i2c_device; - mgr-spi-dev = &mgr_spi_device; - }; - - migration { - #address-cells = <0x1>; - #size-cells = <0x1>; - interrupt-parent = <&migration_intc>; - - migration_gpio: gpio@1000 { - compatible = "vnd,gpio"; - gpio-controller; - reg = <0x1000 0x2000>; - interrupts = <0 1>; - #gpio-cells = <0x2>; - label = "MGR_GPIO"; - }; - - migration_serial: serial@3000 { - compatible = "vnd,serial"; - reg = <0x3000 0x1000>; - interrupts = <2 1>; - label = "MGR_SERIAL"; - baud-rate = <115200>; - }; - - i2c@10000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "vnd,i2c"; - reg = < 0x10000 0x1000 >; - label = "MGR_I2C"; - clock-frequency = <100000>; - interrupts = <10 1>; - - mgr_i2c_device: i2c-dev@10 { - compatible = "vnd,i2c-device"; - label = "MGR_I2C_DEV"; - reg = <0x10>; - }; - }; - - spi@20000 { - #address-cells = < 1 >; - #size-cells = < 0 >; - compatible = "vnd,spi"; - reg = <0x20000 0x1000>; - interrupts = <20 1>; - label = "MGR_SPI"; - clock-frequency = <2000000>; - - cs-gpios = <&migration_gpio 17 GPIO_ACTIVE_LOW>; - - mgr_spi_device: spi-dev@0 { - compatible = "vnd,spi-device"; - label = "MGR_SPI_DEV"; - reg = <0>; - spi-max-frequency = <2000000>; - }; - }; - - migration_intc: interrupt-controller@30000 { - compatible = "vnd,intc"; - reg = <0x30000 0x1000>; - label = "MGR_INTC"; - interrupt-controller; - #interrupt-cells = <2>; - }; - }; -}; -/* end-before-here */ diff --git a/tests/lib/devicetree/legacy_api/prj.conf b/tests/lib/devicetree/legacy_api/prj.conf deleted file mode 100644 index a4cb36f7751..00000000000 --- a/tests/lib/devicetree/legacy_api/prj.conf +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_ZTEST=y -CONFIG_LEGACY_DEVICETREE_MACROS=y diff --git a/tests/lib/devicetree/legacy_api/src/main.c b/tests/lib/devicetree/legacy_api/src/main.c deleted file mode 100644 index 6c012539e24..00000000000 --- a/tests/lib/devicetree/legacy_api/src/main.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -/* - * We test most common properties (label, reg, interrupts) on just the - * GPIO node, since they work the same way on all nodes. - */ - -static void test_gpio(void) -{ - /* label */ - zassert_equal(DT_VND_GPIO_1000_LABEL, - DT_LABEL(DT_PATH(migration, gpio_1000)), - ""); - - zassert_equal(DT_INST_0_VND_GPIO_LABEL, - DT_LABEL(DT_INST(0, vnd_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_LABEL, - DT_LABEL(DT_ALIAS(mgr_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_LABEL, - DT_LABEL(DT_NODELABEL(migration_gpio)), - ""); - - /* reg base address */ - zassert_equal(DT_VND_GPIO_1000_BASE_ADDRESS, - DT_REG_ADDR(DT_PATH(migration, gpio_1000)), - ""); - - zassert_equal(DT_INST_0_VND_GPIO_BASE_ADDRESS, - DT_REG_ADDR(DT_INST(0, vnd_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_BASE_ADDRESS, - DT_REG_ADDR(DT_ALIAS(mgr_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_BASE_ADDRESS, - DT_REG_ADDR(DT_NODELABEL(migration_gpio)), - ""); - - /* reg size */ - zassert_equal(DT_VND_GPIO_1000_SIZE, - DT_REG_SIZE(DT_PATH(migration, gpio_1000)), - ""); - - zassert_equal(DT_INST_0_VND_GPIO_SIZE, - DT_REG_SIZE(DT_INST(0, vnd_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_SIZE, - DT_REG_SIZE(DT_ALIAS(mgr_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_SIZE, - DT_REG_SIZE(DT_NODELABEL(migration_gpio)), - ""); - - /* irq number */ - zassert_equal(DT_VND_GPIO_1000_IRQ_0, - DT_IRQN(DT_PATH(migration, gpio_1000)), - ""); - - zassert_equal(DT_INST_0_VND_GPIO_IRQ_0, - DT_IRQN(DT_INST(0, vnd_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_IRQ_0, - DT_IRQN(DT_ALIAS(mgr_gpio)), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_IRQ_0, - DT_IRQN(DT_NODELABEL(migration_gpio)), - ""); - - /* irq priority */ - zassert_equal(DT_VND_GPIO_1000_IRQ_0_PRIORITY, - DT_IRQ(DT_PATH(migration, gpio_1000), priority), - ""); - - zassert_equal(DT_INST_0_VND_GPIO_IRQ_0_PRIORITY, - DT_IRQ(DT_INST(0, vnd_gpio), priority), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_IRQ_0_PRIORITY, - DT_IRQ(DT_ALIAS(mgr_gpio), priority), - ""); - - zassert_equal(DT_ALIAS_MGR_GPIO_IRQ_0_PRIORITY, - DT_IRQ(DT_NODELABEL(migration_gpio), priority), - ""); -} - -/* - * The serial device is how we test specific properties. - */ - -static void test_serial(void) -{ - zassert_equal(DT_VND_SERIAL_3000_BAUD_RATE, - DT_PROP(DT_PATH(migration, serial_3000), baud_rate), - ""); - zassert_equal(DT_ALIAS_MGR_SERIAL_BAUD_RATE, - DT_PROP(DT_ALIAS(mgr_serial), baud_rate), - ""); - zassert_equal(DT_ALIAS_MGR_SERIAL_BAUD_RATE, - DT_PROP(DT_NODELABEL(migration_serial), baud_rate), - ""); - zassert_equal(DT_INST_0_VND_SERIAL_BAUD_RATE, - DT_PROP(DT_INST(0, vnd_serial), baud_rate), - ""); -} - -/* - * The I2C and SPI devices are used to test inter-device relationships. - */ - -#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) -static void test_i2c_device(void) -{ - /* Bus controller name */ - zassert_true(!strcmp(DT_VND_I2C_10000_VND_I2C_DEVICE_10_BUS_NAME, - DT_LABEL(DT_BUS(I2C_DEV_PATH))), - ""); - zassert_true(!strcmp(DT_ALIAS_MGR_I2C_DEV_BUS_NAME, - DT_LABEL(DT_BUS(I2C_DEV_ALIAS))), - ""); - zassert_true(!strcmp(DT_ALIAS_MGR_I2C_DEV_BUS_NAME, - DT_LABEL(DT_BUS(I2C_DEV_NODELABEL))), - ""); - zassert_true(!strcmp(DT_INST_0_VND_I2C_DEVICE_BUS_NAME, - DT_LABEL(DT_BUS(I2C_DEV_INST))), - ""); -} - -#define SPI_DEV_PATH DT_PATH(migration, spi_20000, 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) -static void test_spi_device(void) -{ - /* cs-gpios controller label */ - zassert_true( - !strcmp(DT_VND_SPI_20000_VND_SPI_DEVICE_0_CS_GPIOS_CONTROLLER, - DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_PATH)), - ""); - zassert_true(!strcmp(DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_CONTROLLER, - DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_ALIAS)), - ""); - zassert_true(!strcmp(DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_CONTROLLER, - DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_NODELABEL)), - ""); - zassert_true(!strcmp(DT_INST_0_VND_SPI_DEVICE_CS_GPIOS_CONTROLLER, - DT_SPI_DEV_CS_GPIOS_LABEL(SPI_DEV_INST)), - ""); - - /* cs-gpios pin number */ - zassert_equal(DT_VND_SPI_20000_VND_SPI_DEVICE_0_CS_GPIOS_PIN, - DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_PATH), - ""); - zassert_equal(DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_PIN, - DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_ALIAS), - ""); - zassert_equal(DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_PIN, - DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_NODELABEL), - ""); - zassert_equal(DT_INST_0_VND_SPI_DEVICE_CS_GPIOS_PIN, - DT_SPI_DEV_CS_GPIOS_PIN(SPI_DEV_INST), - ""); - - /* cs-gpios GPIO flags */ - zassert_equal(DT_VND_SPI_20000_VND_SPI_DEVICE_0_CS_GPIOS_FLAGS, - DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_PATH), - ""); - zassert_equal(DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_FLAGS, - DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_ALIAS), - ""); - zassert_equal(DT_ALIAS_MGR_SPI_DEV_CS_GPIOS_FLAGS, - DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_NODELABEL), - ""); - zassert_equal(DT_INST_0_VND_SPI_DEVICE_CS_GPIOS_FLAGS, - DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_DEV_INST), - ""); -} - -void test_main(void) -{ - ztest_test_suite(devicetree_legacy_api, - ztest_unit_test(test_gpio), - ztest_unit_test(test_serial), - ztest_unit_test(test_i2c_device), - ztest_unit_test(test_spi_device) - ); - ztest_run_test_suite(devicetree_legacy_api); -} diff --git a/tests/lib/devicetree/legacy_api/testcase.yaml b/tests/lib/devicetree/legacy_api/testcase.yaml deleted file mode 100644 index 628acd56b6c..00000000000 --- a/tests/lib/devicetree/legacy_api/testcase.yaml +++ /dev/null @@ -1,8 +0,0 @@ -tests: - libraries.devicetree.legacy: - tags: devicetree - # We only need this to run on one platform so use native_posix as it - # will mostly likely be the fastest. - integration_platforms: - - native_posix - platform_exclude: pinnacle_100_dvk