From 6c24e5edc002c986b85469dc71edb295ddbcec01 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Fri, 10 Jan 2025 21:39:23 +0900 Subject: [PATCH 1/3] dts: doxygen: including dts/common/ to doxygen sources Add dts/common directory to doxygen sources list. And updated `dts/common/freq.h` and `dts/common/mem.h` to generate readable API reference. Signed-off-by: TOKITA Hiroshi --- doc/zephyr.doxyfile.in | 1 + dts/common/freq.h | 22 +++++++++++++++++++ dts/common/mem.h | 50 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/doc/zephyr.doxyfile.in b/doc/zephyr.doxyfile.in index 036bef82c6624..c8d3fe7943863 100644 --- a/doc/zephyr.doxyfile.in +++ b/doc/zephyr.doxyfile.in @@ -980,6 +980,7 @@ INPUT = @ZEPHYR_BASE@/doc/_doxygen/mainpage.md \ @ZEPHYR_BASE@/subsys/testsuite/include/ \ @ZEPHYR_BASE@/subsys/testsuite/ztest/include/ \ @ZEPHYR_BASE@/subsys/secure_storage/include/ \ + @ZEPHYR_BASE@/dts/common/ \ # This tag can be used to specify the character encoding of the source files # that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/dts/common/freq.h b/dts/common/freq.h index 10522bcd175c0..1dc332310946e 100644 --- a/dts/common/freq.h +++ b/dts/common/freq.h @@ -7,7 +7,29 @@ #ifndef ZEPHYR_DTS_COMMON_FREQ_H_ #define ZEPHYR_DTS_COMMON_FREQ_H_ +/** + * @ingroup dts_utils + * @{ + */ + +/** + * @brief Converts a frequency value in kilohertz to hertz. + * + * @param x Frequency value in kilohertz. + * @return Frequency value in hertz. + */ #define DT_FREQ_K(x) ((x) * 1000) + +/** + * @brief Converts a frequency value in megahertz to hertz. + * + * @param x Frequency value in megahertz. + * @return Frequency value in hertz. + */ #define DT_FREQ_M(x) (DT_FREQ_K(x) * 1000) +/** + * @} + */ + #endif /* ZEPHYR_DTS_COMMON_FREQ_H_ */ diff --git a/dts/common/mem.h b/dts/common/mem.h index db35f8e3770df..5575d26fa52f6 100644 --- a/dts/common/mem.h +++ b/dts/common/mem.h @@ -7,12 +7,58 @@ #ifndef ZEPHYR_DTS_COMMON_MEM_H_ #define ZEPHYR_DTS_COMMON_MEM_H_ +/** + * @defgroup dts_apis DTS APIs + * @brief APIs that can only be used in DTS (.dts, .dtsi, .overlay) files + */ + +/** + * @defgroup dts_utils Basic utilities for DTS + * @brief Unit definitions etc + * + * @ingroup dts_apis + * @{ + */ + +/** + * @brief Converts a size value in kilobytes to bytes. + * + * @param x Size value in kilobytes. + * @return Size value in bytes. + */ #define DT_SIZE_K(x) ((x) * 1024) + +/** + * @brief Converts a size value in megabytes to bytes. + * + * @param x Size value in megabytes. + * @return Size value in bytes. + */ #define DT_SIZE_M(x) (DT_SIZE_K(x) * 1024) -/* concatenate the values of the arguments into one */ -#define _DT_DO_CONCAT(x, y) x ## y +/** + * @brief Concatenates two values into a single token. + * + * This macro concatenates the two provided arguments `x` and `y` into a single token. + * + * @param x First part of the token. + * @param y Second part of the token. + * @return The concatenated token. + */ +#define _DT_DO_CONCAT(x, y) x##y +/** + * @brief Converts a hexadecimal address fragment into a full address. + * + * This macro prefixes the provided hexadecimal fragment `a` with `0x` to form a complete address. + * + * @param a Hexadecimal address fragment (without `0x` prefix). + * @return Full hexadecimal address with `0x` prefix. + */ #define DT_ADDR(a) _DT_DO_CONCAT(0x, a) +/** + * @} + */ + #endif /* ZEPHYR_DTS_COMMON_MEM_H_ */ From b5e318f357ac025d79bd598782258bb85bf28d5f Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Mon, 9 Dec 2024 21:57:43 +0900 Subject: [PATCH 2/3] cmake: modules: shields: Introducing shield options To create and tune multiple instances of shields, we are introducing shield options. We can now tweak the behavior of a shield by specifying options as a string after the shield name when building. To achieve this, we are changing how build and shield overlays work. See the documentation in this commit for more details. Signed-off-by: TOKITA Hiroshi --- cmake/modules/shields.cmake | 86 ++++-- doc/hardware/porting/shields.rst | 174 ++++++++++- dts/common/shield_utils.h | 324 ++++++++++++++++++++ scripts/build/gen_shield_derived_overlay.py | 251 +++++++++++++++ 4 files changed, 812 insertions(+), 23 deletions(-) create mode 100644 dts/common/shield_utils.h create mode 100644 scripts/build/gen_shield_derived_overlay.py diff --git a/cmake/modules/shields.cmake b/cmake/modules/shields.cmake index 145f559b2922d..26d036a11e5a9 100644 --- a/cmake/modules/shields.cmake +++ b/cmake/modules/shields.cmake @@ -35,6 +35,15 @@ include(extensions) # Check that SHIELD has not changed. zephyr_check_cache(SHIELD WATCH) +set(GEN_SHIELD_DERIVED_OVERLAY_SCRIPT ${ZEPHYR_BASE}/scripts/build/gen_shield_derived_overlay.py) +set(GENERATED_SHIELDS_DIR ${PROJECT_BINARY_DIR}/include/generated/shields) + +# Add the directory derived overlay files to the SHIELD_DIRS output variable. +list(APPEND + SHIELD_DIRS + ${GENERATED_SHIELDS_DIR} +) + if(SHIELD) message(STATUS "Shield(s): ${SHIELD}") endif() @@ -44,7 +53,7 @@ if(DEFINED SHIELD) endif() # SHIELD-NOTFOUND is a real CMake list, from which valid shields can be popped. # After processing all shields, only invalid shields will be left in this list. -set(SHIELD-NOTFOUND ${SHIELD_AS_LIST}) +string(REGEX REPLACE "([@:][^;]*)" "" SHIELD-NOTFOUND "${SHIELD}") foreach(root ${BOARD_ROOT}) set(shield_dir ${root}/boards/shields) @@ -74,43 +83,76 @@ endforeach() # Process shields in-order if(DEFINED SHIELD) - foreach(s ${SHIELD_AS_LIST}) + foreach(shld ${SHIELD_AS_LIST}) + string(REGEX MATCH [[^([^@:]*)([@:].*)?$]] matched "${shld}") + set(s ${CMAKE_MATCH_1}) # name part + set(shield_opts ${CMAKE_MATCH_2}) # options part + if(NOT ${s} IN_LIST SHIELD_LIST) continue() endif() list(REMOVE_ITEM SHIELD-NOTFOUND ${s}) - # Add .overlay to the shield_dts_files output variable. - list(APPEND - shield_dts_files - ${SHIELD_DIR_${s}}/${s}.overlay - ) - # Add the shield's directory to the SHIELD_DIRS output variable. list(APPEND SHIELD_DIRS ${SHIELD_DIR_${s}} ) - # Search for shield/shield.conf file - if(EXISTS ${SHIELD_DIR_${s}}/${s}.conf) - list(APPEND - shield_conf_files - ${SHIELD_DIR_${s}}/${s}.conf - ) - endif() - - # Add board-specific .conf and .overlay files to their - # respective output variables. + # get board-specific .conf and .overlay filenames zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards - DTS shield_dts_files - KCONF shield_conf_files + DTS board_overlay_file + KCONF board_conf_file ) + zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards/${s} - DTS shield_dts_files - KCONF shield_conf_files + DTS board_shield_overlay_file + KCONF board_shield_conf_file ) + + get_filename_component(board_overlay_stem "${board_overlay_file}" NAME_WE) + get_filename_component(shield_overlay_stem "${board_shield_overlay_file}" NAME_WE) + + set(shield_conf_list + "${SHIELD_DIR_${s}}/${s}.conf" + "${board_conf_file}" + "${board_shield_conf_file}") + + set(shield_overlay_list + "${SHIELD_DIR_${s}}/${s}.overlay" + "${board_overlay_file}" + "${board_shield_overlay_file}") + + set(derived_overlay_list + "${GENERATED_SHIELDS_DIR}/${shld}.overlay" + "${GENERATED_SHIELDS_DIR}/${shld}_${board_overlay_stem}.overlay" + "${GENERATED_SHIELDS_DIR}/${shld}_${board_overlay_stem}_${shield_overlay_stem}.overlay") + + # Add board-specific .conf files to the shield_conf_files output variable. + foreach(src_conf ${shield_conf_list}) + if(EXISTS ${src_conf}) + list(APPEND shield_conf_files ${src_conf}) + endif() + endforeach() + + foreach(shield_overlay derived_overlay IN ZIP_LISTS shield_overlay_list derived_overlay_list) + if (EXISTS ${shield_overlay}) + # Generate a derived overlay for each file, reflecting the options. + execute_process(COMMAND + ${PYTHON_EXECUTABLE} + ${GEN_SHIELD_DERIVED_OVERLAY_SCRIPT} + "${shield_overlay}" + "--derived-overlay=${derived_overlay}" + "--shield-options=${shield_opts}" + COMMAND_ERROR_IS_FATAL ANY + ) + + # Add the derived overlay file to the shield_dts_files output variable. + list(APPEND shield_dts_files "${derived_overlay}") + endif() + endforeach() + endforeach() endif() diff --git a/doc/hardware/porting/shields.rst b/doc/hardware/porting/shields.rst index 6f3dff1be5fb8..7fe55c49ed9e1 100644 --- a/doc/hardware/porting/shields.rst +++ b/doc/hardware/porting/shields.rst @@ -17,15 +17,25 @@ under :zephyr_file:`boards/shields`: .. code-block:: none boards/shields/ + ├── shield.yml ├── .overlay ├── Kconfig.shield └── Kconfig.defconfig These files provides shield configuration as follows: +* **shield.yml**: This file defines the name of the shield, its variant + information, and the information it accepts if parameterized. + The :ref:`shield_yaml_format` section for details. + * **.overlay**: This file provides a shield description in devicetree format that is merged with the board's :ref:`devicetree ` before compilation. + The shield framework provides a mechanism for tweaking shield configurations at build time. + This capability allows developers to tailor shield behavior to specific use cases, + such as adjusting connections, setting hardware parameters, or enabling multiple + instances of the same shield with distinct configurations. + The :ref:`shield_parametrization` section for details. * **Kconfig.shield**: This file defines shield Kconfig symbols that will be used for default shield configuration. To ease use with applications, @@ -48,6 +58,158 @@ to provide a device nodelabel is the form _, for instance: ... }; + +.. _shield_yaml_format: + +Shield YAML Format +****************** + +The ``shield.yml`` file is the shield schema located in each shield directory. +It defines the shield's metadata. And also parameterization options, as described in later sections. + +YAML Schema Field Descriptions +============================== + +- **shield**: + A top-level key that groups all metadata and configuration details related to the shield. + +- **name**: + The short identifier or slug name for the shield. This name is a unique reference within the build system and configurations. + +- **full\_name**: + The complete, human-readable name of the shield. It provides a detailed description, including the vendor and functionality. + +- **vendor**: + The name of the company or organization that manufactures or provides the shield. + +- **options**: + A dictionary of customizable parameters for the shield. Each option defines a configurable property using the following fields: + This is similar to the YAML properties format for defining devicetree bindings, but the difference is that + type is limited to int, boolean and string only, and the default value is required. + + - **type**: + Specifies the data type of the option. Common types include ``int``, ``boolean`` and ``string``. + This field is required. + + - **default**: + Specifies the default value assigned to the option if no explicit value is provided during configuration. + This field is required except in the boolean case. + + - **description**: + Provides a human-readable explanation of the option's purpose and functionality. + +- **variants**: + A list of shield variations, each element having the same fields as the shield, excluding the variants. + These are interpreted as overlays on the base shield definition. + + +Example shield.yml File +----------------------- + +.. code-block:: yaml + + shield: + name: example_grove_i2c + full_name: Example Grove I2C Shield + vendor: example_vendor + options: + conn: + type: string + default: "grove_i2c" + description: Specifies the shield’s connection type. + addr: + type: int + default: 0x11 + description: Defines the I2C address for the shield. + irq-gpio-pin: + type: int + default: 0 + description: Specifies the GPIO pin used for interrupts. + +.. _shield_parametrization: + +Shield Parametrization +********************** + +The ``–shield`` option in the ``west build`` command allows shield options to be appended with a key-value +format after the shield name. +Using it, you can customize how a shield interacts with your hardware. +For example, you can specify the connection type, assign specific addresses for I2C, +or configure GPIO pins for interrupts. This ensures flexibility and adaptability across +a wide range of hardware configurations. + +Specifying Parameters +===================== + +Parameters are specified as part of the ``--shield`` argument using the following syntax: + +``[@][: