diff --git a/cmake/app/boilerplate.cmake b/cmake/app/boilerplate.cmake index 769499a1e57..6d7f628b354 100644 --- a/cmake/app/boilerplate.cmake +++ b/cmake/app/boilerplate.cmake @@ -186,6 +186,65 @@ message(STATUS "Selected BOARD ${BOARD}") # Store the selected board in the cache set(CACHED_BOARD ${BOARD} CACHE STRING "Selected board") +# The SHIELD can be set by 3 sources. Through environment variables, +# through the cmake CLI, and through CMakeLists.txt. +# +# CLI has the highest precedence, then comes environment variables, +# and then finally CMakeLists.txt. +# +# A user can ignore all the precedence rules if he simply always uses +# the same source. E.g. always specifies -DSHIELD= on the command line, +# always has an environment variable set, or always has a set(SHIELD +# foo) line in his CMakeLists.txt and avoids mixing sources. +# +# The selected SHIELD can be accessed through the variable 'SHIELD'. + +# Read out the cached shield value if present +get_property(cached_shield_value CACHE SHIELD PROPERTY VALUE) + +# There are actually 4 sources, the three user input sources, and the +# previously used value (CACHED_SHIELD). The previously used value has +# precedence, and if we detect that the user is trying to change the +# value we give him a warning about needing to clean the build +# directory to be able to change shields. + +set(shield_cli_argument ${cached_shield_value}) # Either new or old +if(shield_cli_argument STREQUAL CACHED_SHIELD) + # We already have a CACHED_SHIELD so there is no new input on the CLI + unset(shield_cli_argument) +endif() + +set(shield_app_cmake_lists ${SHIELD}) +if(cached_shield_value STREQUAL SHIELD) + # The app build scripts did not set a default, The SHIELD we are + # reading is the cached value from the CLI + unset(shield_app_cmake_lists) +endif() + +if(CACHED_SHIELD) + # Warn the user if it looks like he is trying to change the shield + # without cleaning first + if(shield_cli_argument) + if(NOT (CACHED_SHIELD STREQUAL shield_cli_argument)) + message(WARNING "The build directory must be cleaned pristinely when changing shields") + # TODO: Support changing shields without requiring a clean build + endif() + endif() + + set(SHIELD ${CACHED_SHIELD}) +elseif(shield_cli_argument) + set(SHIELD ${shield_cli_argument}) + +elseif(DEFINED ENV{SHIELD}) + set(SHIELD $ENV{SHIELD}) + +elseif(shield_app_cmake_lists) + set(SHIELD ${shield_app_cmake_lists}) +endif() + +# Store the selected shield in the cache +set(CACHED_SHIELD ${SHIELD} CACHE STRING "Selected shield") + # 'BOARD_ROOT' is a prioritized list of directories where boards may # be found. It always includes ${ZEPHYR_BASE} at the lowest priority. list(APPEND BOARD_ROOT ${ZEPHYR_BASE}) @@ -210,6 +269,48 @@ foreach(root ${BOARD_ROOT}) if(BOARD_DIR AND NOT (${root} STREQUAL ${ZEPHYR_BASE})) set(USING_OUT_OF_TREE_BOARD 1) endif() + + set(shield_dir ${root}/boards/shields) + if(DEFINED SHIELD) + string(REPLACE " " ";" SHIELD_AS_LIST "${SHIELD}") + endif() + # Match the .overlay files in the shield directories to make sure we are + # finding shields, e.g. x_nucleo_iks01a1/x_nucleo_iks01a1.overlay + file(GLOB_RECURSE shields_refs_list + RELATIVE ${shield_dir} + ${shield_dir}/*/*.overlay + ) + + # The above gives a list like + # x_nucleo_iks01a1/x_nucleo_iks01a1.overlay;x_nucleo_iks01a2/x_nucleo_iks01a2.overlay + # we construct a list of shield names by extracting file name and + # removing the extension. + foreach(shield_path ${shields_refs_list}) + get_filename_component(shield ${shield_path} NAME_WE) + list(APPEND SHIELD_LIST ${shield}) + endforeach() + + if(DEFINED SHIELD) + foreach(s ${SHIELD_AS_LIST}) + list(FIND SHIELD_LIST ${s} _idx) + if (NOT _idx EQUAL -1) + list(GET shields_refs_list ${_idx} s_path) + + # if shield config flag is on, add shield overlay to the shield overlays + # list and dts_fixup file to the shield fixup file + list(APPEND + shield_dts_files + ${shield_dir}/${s_path} + ) + list(APPEND + shield_dts_fixups + ${shield_dir}/${s}/dts_fixup.h + ) + else() + list(APPEND NOT_FOUND_SHIELD_LIST ${s}) + endif() + endforeach() + endif() endforeach() if(NOT BOARD_DIR) @@ -219,6 +320,15 @@ if(NOT BOARD_DIR) message(FATAL_ERROR "Invalid usage") endif() +if(DEFINED SHIELD AND DEFINED NOT_FOUND_SHIELD_LIST) + foreach (s ${NOT_FOUND_SHIELD_LIST}) + message("No shield named '${s}' found") + endforeach() + print_usage() + unset(CACHED_SHIELD CACHE) + message(FATAL_ERROR "Invalid usage") +endif() + get_filename_component(BOARD_ARCH_DIR ${BOARD_DIR} DIRECTORY) get_filename_component(BOARD_FAMILY ${BOARD_DIR} NAME) get_filename_component(ARCH ${BOARD_ARCH_DIR} NAME) diff --git a/cmake/dts.cmake b/cmake/dts.cmake index 073c52f7fd6..b1b76aa8a1e 100644 --- a/cmake/dts.cmake +++ b/cmake/dts.cmake @@ -18,44 +18,9 @@ set_ifndef(DTS_APP_INCLUDE ${APPLICATION_SOURCE_DIR}/dts) set(dts_files ${DTS_SOURCE} ${DTS_COMMON_OVERLAYS} + ${shield_dts_files} ) -# Parse boards/shields of each board root to generate the shield list -foreach(board_root ${BOARD_ROOT}) - set(shield_dir ${board_root}/boards/shields) - - # Match the .overlay files in the shield directories to make sure we are - # finding shields, e.g. x_nucleo_iks01a1/x_nucleo_iks01a1.overlay - file(GLOB_RECURSE shields_refs_list - RELATIVE ${shield_dir} - ${shield_dir}/*/*.overlay - ) - - # The above gives a list like - # x_nucleo_iks01a1/x_nucleo_iks01a1.overlay;x_nucleo_iks01a2/x_nucleo_iks01a2.overlay - # we construct a list of shield names by extracting file name and - # removing the extension. - foreach(shield_path ${shields_refs_list}) - get_filename_component(shield ${shield_path} NAME_WE) - - # Generate CONFIG flags matching each shield - string(TOUPPER "CONFIG_SHIELD_${shield}" shield_config) - - if(${shield_config}) - # if shield config flag is on, add shield overlay to the shield overlays - # list and dts_fixup file to the shield fixup file - list(APPEND - dts_files - ${shield_dir}/${shield_path} - ) - list(APPEND - dts_fixups - ${shield_dir}/${shield}/dts_fixup.h - ) - endif() - endforeach() -endforeach() - if(CONFIG_HAS_DTS) if(DTC_OVERLAY_FILE) @@ -155,6 +120,7 @@ if(CONFIG_HAS_DTS) ${DTS_BOARD_FIXUP_FILE} ${DTS_SOC_FIXUP_FILE} ${APPLICATION_SOURCE_DIR}/dts_fixup.h + ${shield_dts_fixups} ) foreach(fixup ${dts_fixups}) diff --git a/cmake/extensions.cmake b/cmake/extensions.cmake index 344b2812e67..a19b07329ee 100644 --- a/cmake/extensions.cmake +++ b/cmake/extensions.cmake @@ -1108,10 +1108,12 @@ endmacro() function(print_usage) message("see usage:") string(REPLACE ";" " " BOARD_ROOT_SPACE_SEPARATED "${BOARD_ROOT}") + string(REPLACE ";" " " SHIELD_LIST_SPACE_SEPARATED "${SHIELD_LIST}") execute_process( COMMAND ${CMAKE_COMMAND} -DBOARD_ROOT_SPACE_SEPARATED=${BOARD_ROOT_SPACE_SEPARATED} + -DSHIELD_LIST_SPACE_SEPARATED=${SHIELD_LIST_SPACE_SEPARATED} -P ${ZEPHYR_BASE}/cmake/usage/usage.cmake ) endfunction() diff --git a/cmake/usage/CMakeLists.txt b/cmake/usage/CMakeLists.txt index 85ad5d1cc60..9a1001de554 100644 --- a/cmake/usage/CMakeLists.txt +++ b/cmake/usage/CMakeLists.txt @@ -1,9 +1,11 @@ string(REPLACE ";" " " BOARD_ROOT_SPACE_SEPARATED "${BOARD_ROOT}") +string(REPLACE ";" " " SHIELD_LIST_SPACE_SEPARATED "${SHIELD_LIST}") add_custom_target( usage ${CMAKE_COMMAND} -DBOARD_ROOT_SPACE_SEPARATED=${BOARD_ROOT_SPACE_SEPARATED} + -DSHIELD_LIST_SPACE_SEPARATED=${SHIELD_LIST_SPACE_SEPARATED} -P ${CMAKE_CURRENT_SOURCE_DIR}/usage.cmake ) diff --git a/cmake/usage/usage.cmake b/cmake/usage/usage.cmake index 05b19f9cb86..34dbbbdde05 100644 --- a/cmake/usage/usage.cmake +++ b/cmake/usage/usage.cmake @@ -13,6 +13,7 @@ set(arch_list ) string(REPLACE " " ";" BOARD_ROOT "${BOARD_ROOT_SPACE_SEPARATED}") +string(REPLACE " " ";" SHIELD_LIST "${SHIELD_LIST_SPACE_SEPARATED}") foreach(arch ${arch_list}) foreach(root ${BOARD_ROOT}) @@ -60,11 +61,12 @@ message("Supported Boards:") message("") message(" To generate project files for one of the supported boards below, run:") message("") -message(" $ cmake -DBOARD= -Bpath/to/build_dir -Hpath/to/source_dir") +message(" $ cmake -DBOARD= [-DSHIELD=] -Bpath/to/build_dir -Hpath/to/source_dir") message("") message(" or") message("") message(" $ export BOARD=") +message(" $ export SHIELD= #optional") message(" $ cmake -Bpath/to/build_dir -Hpath/to/source_dir") message("") foreach(arch ${arch_list}) @@ -74,6 +76,12 @@ foreach(arch ${arch_list}) endforeach() endforeach() message("") +message("Supported Shields:") +message("") +foreach(shield ${SHIELD_LIST}) + message(" ${shield}") +endforeach() +message("") message("Build flags:") message("") message(" ${generator} VERBOSE=1 [targets] verbose build") diff --git a/doc/porting/shields.rst b/doc/porting/shields.rst index 7c261625a3e..e643595a87b 100644 --- a/doc/porting/shields.rst +++ b/doc/porting/shields.rst @@ -17,22 +17,11 @@ under :file:`/boards/shields`: .. code-block:: none boards/shields/ - ├── Kconfig.shield - ├── Kconfig.defconfig ├── .overlay └── dts_fixup.h These files provides shield configuration as follows: -* **Kconfig.shield**: This file defines the shield's config flag - (CONFIG_SHIELD_X). Applications use this flag to trigger the shield - configuration on top of the board configuration, enabling each shield - component or sensor driver. - -* **Kconfig.defconfig**: This file provides conditional configuration of - specific driver default configurations, offering flexibility for broad - board support. - * **.overlay**: This file provides a shield description in device tree format that is merged with the board's device tree information before compilation. @@ -74,9 +63,17 @@ introduced overriding node element: Shield activation ***************** -Activate support for a shield by enabling the corresponding Kconfig shield -option in the application's prj.conf file. +Activate support for a shield by adding the matching -DSHIELD arg to CMake +command + + .. zephyr-app-commands:: + :zephyr-app: your_app + :gen-args: -DSHIELD=x_nucleo_iks01a1 + :goals: build + + +Alternatively, it could be set by default in a project's CMakeLists.txt: .. code-block:: none - #CONFIG_SHIELD_X_NUCLEO_IKS01A2=y + set(SHIELD x_nucleo_iks01a1) diff --git a/samples/bluetooth/peripheral_hr/CMakeLists.txt b/samples/bluetooth/peripheral_hr/CMakeLists.txt index 28edde4b97c..04f10ca6936 100644 --- a/samples/bluetooth/peripheral_hr/CMakeLists.txt +++ b/samples/bluetooth/peripheral_hr/CMakeLists.txt @@ -1,4 +1,14 @@ cmake_minimum_required(VERSION 3.13.1) + +# Some boards could run this sample using frdm_kw41z shield, enforce +# -DSHIELD option in case they are used +if(BOARD STREQUAL mimxrt1020_evk OR + BOARD STREQUAL mimxrt1050_evk OR + BOARD STREQUAL mimxrt1060_evk OR + BOARD STREQUAL frdm_k64f) +set(SHIELD frdm_kw41z) +endif() + include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) project(peripheral_hr) diff --git a/samples/bluetooth/peripheral_hr/overlay-shield_frdm_kw41z.conf b/samples/bluetooth/peripheral_hr/overlay-shield_frdm_kw41z.conf deleted file mode 100644 index 1c6f93e315c..00000000000 --- a/samples/bluetooth/peripheral_hr/overlay-shield_frdm_kw41z.conf +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (c) 2018, NXP -# -# SPDX-License-Identifier: Apache-2.0 -# - -CONFIG_SHIELD_FRDM_KW41Z=y diff --git a/samples/bluetooth/peripheral_hr/sample.yaml b/samples/bluetooth/peripheral_hr/sample.yaml index a882d5ac050..4beb080fcef 100644 --- a/samples/bluetooth/peripheral_hr/sample.yaml +++ b/samples/bluetooth/peripheral_hr/sample.yaml @@ -4,10 +4,5 @@ sample: tests: test: harness: bluetooth - platform_whitelist: qemu_cortex_m3 qemu_x86 - tags: bluetooth - test.overlay-shield_frdm_kw41z: - harness: bluetooth - extra_args: OVERLAY_CONFIG=overlay-shield_frdm_kw41z.conf - platform_whitelist: mimxrt1020_evk mimxrt1050_evk mimxrt1060_evk frdm_k64f + platform_whitelist: qemu_cortex_m3 qemu_x86 mimxrt1020_evk mimxrt1050_evk mimxrt1060_evk frdm_k64f tags: bluetooth diff --git a/samples/shields/x_nucleo_iks01a1/CMakeLists.txt b/samples/shields/x_nucleo_iks01a1/CMakeLists.txt index 02ab9fd6456..d4242783e01 100644 --- a/samples/shields/x_nucleo_iks01a1/CMakeLists.txt +++ b/samples/shields/x_nucleo_iks01a1/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 3.13.1) +# This sample is specific to x_nucleo_iks01a1 shield. Enforce -DSHIELD option +set(SHIELD x_nucleo_iks01a1) + include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) project(x_nucleo_iks01a1) diff --git a/samples/shields/x_nucleo_iks01a1/README.rst b/samples/shields/x_nucleo_iks01a1/README.rst index 8dd2f438d0f..406db5b2163 100644 --- a/samples/shields/x_nucleo_iks01a1/README.rst +++ b/samples/shields/x_nucleo_iks01a1/README.rst @@ -20,6 +20,9 @@ This sample communicates over I2C with the X-NUCLEO-IKS01A1 shield stacked on a board with an Arduino connector. The board's I2C must be configured for the I2C Arduino connector (both for pin muxing and device tree). +Please note that this sample can't be used with boards already supporting +one of the sensors available on the shield (such as disco_l475_iot1) as zephyr +does not yet support sensors multiple instances. References ********** diff --git a/samples/shields/x_nucleo_iks01a1/prj.conf b/samples/shields/x_nucleo_iks01a1/prj.conf index 305ffb25faa..c164f74a04c 100644 --- a/samples/shields/x_nucleo_iks01a1/prj.conf +++ b/samples/shields/x_nucleo_iks01a1/prj.conf @@ -1,2 +1,10 @@ CONFIG_STDOUT_CONSOLE=y -CONFIG_SHIELD_X_NUCLEO_IKS01A1=y +CONFIG_I2C=y +CONFIG_I2C_STM32_INTERRUPT=y +CONFIG_SENSOR=y +CONFIG_HTS221=y +CONFIG_LPS25HB=y +CONFIG_LSM6DS0=y +CONFIG_LIS3MDL=y +CONFIG_HTS221_TRIGGER_NONE=y +CONFIG_LIS3MDL_TRIGGER_NONE=y diff --git a/samples/shields/x_nucleo_iks01a1/sample.yaml b/samples/shields/x_nucleo_iks01a1/sample.yaml index bfddeae065b..c9aacb3e047 100644 --- a/samples/shields/x_nucleo_iks01a1/sample.yaml +++ b/samples/shields/x_nucleo_iks01a1/sample.yaml @@ -6,3 +6,4 @@ tests: harness: shield tags: shield depends_on: arduino_i2c + platform_exclude: disco_l475_iot1