Skip to content

Commit 1e0d975

Browse files
57300rlubos
authored andcommitted
[nrf fromlist] sysbuild: dts: Introduce sysbuild_dt_* API
Upstream PR: zephyrproject-rtos/zephyr#73903 Add new functions to `sysbuild_extensions.cmake`, which will mirror the familiar dt_* API from Zephyr `extensions.cmake`. For example: dt_nodelabel(<var> NODELABEL <label>) gets the following sysbuild counterpart, with one extra argument: sysbuild_dt_nodelabel(<var> IMAGE <image> NODELABEL <label>) This API allows sysbuild to retrieve devicetree information for a given <image>, only after its respective `ExternalZephyrProject_Cmake()` call. This works by importing the generated `dts.cmake` files from each image's build directory, and creating multiple CMake targets to hold the generated properties - much like how the `CMakeCache.txt` and `.config` are also imported to be used by the related `sysbuild_get()` function. The dt_* API itself also has to be updated, in order to read properties from a variable `DEVICETREE_TARGET` set in the parent scope. Signed-off-by: Grzegorz Swiderski <[email protected]> (cherry picked from commit 3bf9a41a20ae52adc3ccadc2ff79425160f8ad73)
1 parent d53b51e commit 1e0d975

File tree

2 files changed

+144
-12
lines changed

2 files changed

+144
-12
lines changed

cmake/modules/extensions.cmake

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,6 +3553,9 @@ endfunction()
35533553
# alias at the beginning of a path interchangeably with the full
35543554
# path to the aliased node in these functions. The usage comments
35553555
# will make this clear in each case.
3556+
#
3557+
# - Each of these methods also has a sysbuild_dt_* counterpart.
3558+
# See share/sysbuild/cmake/modules/sysbuild_extensions.cmake.
35563559

35573560
# Usage:
35583561
# dt_nodelabel(<var> NODELABEL <label>)
@@ -3579,6 +3582,10 @@ endfunction()
35793582
# <var> : Return variable where the node path will be stored
35803583
# NODELABEL <label> : Node label
35813584
function(dt_nodelabel var)
3585+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3586+
message(FATAL_ERROR "dt_nodelabel(${ARGV0} ...) devicetree is not available.")
3587+
endif()
3588+
35823589
set(req_single_args "NODELABEL")
35833590
cmake_parse_arguments(DT_LABEL "" "${req_single_args}" "" ${ARGN})
35843591

@@ -3594,7 +3601,7 @@ function(dt_nodelabel var)
35943601
endif()
35953602
endforeach()
35963603

3597-
get_target_property(${var} devicetree_target "DT_NODELABEL|${DT_LABEL_NODELABEL}")
3604+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_NODELABEL|${DT_LABEL_NODELABEL}")
35983605
if(${${var}} STREQUAL ${var}-NOTFOUND)
35993606
set(${var})
36003607
endif()
@@ -3622,6 +3629,10 @@ endfunction()
36223629
# <var> : Return variable where the node path will be stored
36233630
# PROPERTY <prop> : The alias to check
36243631
function(dt_alias var)
3632+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3633+
message(FATAL_ERROR "dt_alias(${ARGV0} ...) devicetree is not available.")
3634+
endif()
3635+
36253636
set(req_single_args "PROPERTY")
36263637
cmake_parse_arguments(DT_ALIAS "" "${req_single_args}" "" ${ARGN})
36273638

@@ -3637,7 +3648,7 @@ function(dt_alias var)
36373648
endif()
36383649
endforeach()
36393650

3640-
get_target_property(${var} devicetree_target "DT_ALIAS|${DT_ALIAS_PROPERTY}")
3651+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_ALIAS|${DT_ALIAS_PROPERTY}")
36413652
if(${${var}} STREQUAL ${var}-NOTFOUND)
36423653
set(${var})
36433654
endif()
@@ -3662,6 +3673,10 @@ endfunction()
36623673
# <var> : Return variable where the check result will be returned
36633674
# PATH <path> : Node path
36643675
function(dt_node_exists var)
3676+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3677+
message(FATAL_ERROR "dt_node_exists(${ARGV0} ...) devicetree is not available.")
3678+
endif()
3679+
36653680
set(req_single_args "PATH")
36663681
cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
36673682

@@ -3707,6 +3722,10 @@ endfunction()
37073722
# PATH <path> : Node path
37083723
# STATUS <status> : Status to check
37093724
function(dt_node_has_status var)
3725+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3726+
message(FATAL_ERROR "dt_node_has_status(${ARGV0} ...) devicetree is not available.")
3727+
endif()
3728+
37103729
set(req_single_args "PATH;STATUS")
37113730
cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
37123731

@@ -3792,6 +3811,10 @@ endfunction()
37923811
# appears in the DTS source
37933812
# INDEX <idx> : Optional index when retrieving a value in an array property
37943813
function(dt_prop var)
3814+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3815+
message(FATAL_ERROR "dt_prop(${ARGV0} ...) devicetree is not available.")
3816+
endif()
3817+
37953818
set(req_single_args "PATH;PROPERTY")
37963819
set(single_args "INDEX")
37973820
cmake_parse_arguments(DT_PROP "" "${req_single_args};${single_args}" "" ${ARGN})
@@ -3809,7 +3832,7 @@ function(dt_prop var)
38093832
endforeach()
38103833

38113834
dt_path_internal(canonical "${DT_PROP_PATH}")
3812-
get_property(exists TARGET devicetree_target
3835+
get_property(exists TARGET "${DEVICETREE_TARGET}"
38133836
PROPERTY "DT_PROP|${canonical}|${DT_PROP_PROPERTY}"
38143837
SET
38153838
)
@@ -3819,7 +3842,7 @@ function(dt_prop var)
38193842
return()
38203843
endif()
38213844

3822-
get_target_property(val devicetree_target
3845+
get_target_property(val "${DEVICETREE_TARGET}"
38233846
"DT_PROP|${canonical}|${DT_PROP_PROPERTY}"
38243847
)
38253848

@@ -3848,6 +3871,10 @@ endfunction()
38483871
# INDEX <idx> : Optional index when retrieving a value in an array property
38493872

38503873
function(dt_comp_path var)
3874+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3875+
message(FATAL_ERROR "dt_comp_path(${ARGV0} ...) devicetree is not available.")
3876+
endif()
3877+
38513878
set(req_single_args "COMPATIBLE")
38523879
set(single_args "INDEX")
38533880
cmake_parse_arguments(DT_COMP "" "${req_single_args};${single_args}" "" ${ARGN})
@@ -3864,7 +3891,7 @@ function(dt_comp_path var)
38643891
endif()
38653892
endforeach()
38663893

3867-
get_property(exists TARGET devicetree_target
3894+
get_property(exists TARGET "${DEVICETREE_TARGET}"
38683895
PROPERTY "DT_COMP|${DT_COMP_COMPATIBLE}"
38693896
SET
38703897
)
@@ -3874,7 +3901,7 @@ function(dt_comp_path var)
38743901
return()
38753902
endif()
38763903

3877-
get_target_property(val devicetree_target
3904+
get_target_property(val "${DEVICETREE_TARGET}"
38783905
"DT_COMP|${DT_COMP_COMPATIBLE}"
38793906
)
38803907

@@ -3903,6 +3930,10 @@ endfunction()
39033930
# <var> : Return variable where the property value will be stored
39043931
# PATH <path> : Node path
39053932
function(dt_num_regs var)
3933+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3934+
message(FATAL_ERROR "dt_num_regs(${ARGV0} ...) devicetree is not available.")
3935+
endif()
3936+
39063937
set(req_single_args "PATH")
39073938
cmake_parse_arguments(DT_REG "" "${req_single_args}" "" ${ARGN})
39083939

@@ -3919,7 +3950,7 @@ function(dt_num_regs var)
39193950
endforeach()
39203951

39213952
dt_path_internal(canonical "${DT_REG_PATH}")
3922-
get_target_property(${var} devicetree_target "DT_REG|${canonical}|NUM")
3953+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_REG|${canonical}|NUM")
39233954

39243955
set(${var} ${${var}} PARENT_SCOPE)
39253956
endfunction()
@@ -3949,6 +3980,10 @@ endfunction()
39493980
# INDEX <idx> : Register block index number
39503981
# NAME <name> : Register block name
39513982
function(dt_reg_addr var)
3983+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3984+
message(FATAL_ERROR "dt_reg_addr(${ARGV0} ...) devicetree is not available.")
3985+
endif()
3986+
39523987
set(req_single_args "PATH")
39533988
set(single_args "INDEX;NAME")
39543989
cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
@@ -3978,7 +4013,7 @@ function(dt_reg_addr var)
39784013
endif()
39794014

39804015
dt_path_internal(canonical "${DT_REG_PATH}")
3981-
get_target_property(${var}_list devicetree_target "DT_REG|${canonical}|ADDR")
4016+
get_target_property(${var}_list "${DEVICETREE_TARGET}" "DT_REG|${canonical}|ADDR")
39824017

39834018
list(GET ${var}_list ${DT_REG_INDEX} ${var})
39844019

@@ -4009,6 +4044,10 @@ endfunction()
40094044
# INDEX <idx> : Register block index number
40104045
# NAME <name> : Register block name
40114046
function(dt_reg_size var)
4047+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4048+
message(FATAL_ERROR "dt_reg_size(${ARGV0} ...) devicetree is not available.")
4049+
endif()
4050+
40124051
set(req_single_args "PATH")
40134052
set(single_args "INDEX;NAME")
40144053
cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
@@ -4038,7 +4077,7 @@ function(dt_reg_size var)
40384077
endif()
40394078

40404079
dt_path_internal(canonical "${DT_REG_PATH}")
4041-
get_target_property(${var}_list devicetree_target "DT_REG|${canonical}|SIZE")
4080+
get_target_property(${var}_list "${DEVICETREE_TARGET}" "DT_REG|${canonical}|SIZE")
40424081

40434082
list(GET ${var}_list ${DT_REG_INDEX} ${var})
40444083

@@ -4086,6 +4125,10 @@ endfunction()
40864125
# <var> : Return variable
40874126
# PROPERTY <prop> : Chosen property
40884127
function(dt_has_chosen var)
4128+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4129+
message(FATAL_ERROR "dt_has_chosen(${ARGV0} ...) devicetree is not available.")
4130+
endif()
4131+
40894132
set(req_single_args "PROPERTY")
40904133
cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
40914134

@@ -4101,7 +4144,7 @@ function(dt_has_chosen var)
41014144
endif()
41024145
endforeach()
41034146

4104-
get_target_property(exists devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
4147+
get_target_property(exists "${DEVICETREE_TARGET}" "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
41054148

41064149
if(${exists} STREQUAL exists-NOTFOUND)
41074150
set(${var} FALSE PARENT_SCOPE)
@@ -4121,6 +4164,10 @@ endfunction()
41214164
# <var> : Return variable where the node path will be stored
41224165
# PROPERTY <prop> : Chosen property
41234166
function(dt_chosen var)
4167+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4168+
message(FATAL_ERROR "dt_chosen(${ARGV0} ...) devicetree is not available.")
4169+
endif()
4170+
41244171
set(req_single_args "PROPERTY")
41254172
cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
41264173

@@ -4136,7 +4183,7 @@ function(dt_chosen var)
41364183
endif()
41374184
endforeach()
41384185

4139-
get_target_property(${var} devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
4186+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
41404187

41414188
if(${${var}} STREQUAL ${var}-NOTFOUND)
41424189
set(${var} PARENT_SCOPE)
@@ -4208,7 +4255,7 @@ endfunction()
42084255
# to an existing node. Set it to FALSE otherwise. See
42094256
# dt_path_internal for a definition and examples of 'canonical' paths.
42104257
function(dt_path_internal_exists var path)
4211-
get_target_property(path_prop devicetree_target "DT_NODE|${path}")
4258+
get_target_property(path_prop "${DEVICETREE_TARGET}" "DT_NODE|${path}")
42124259
if (path_prop)
42134260
set(${var} TRUE PARENT_SCOPE)
42144261
else()

share/sysbuild/cmake/modules/sysbuild_extensions.cmake

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,8 @@ function(ExternalZephyrProject_Cmake)
490490
endif()
491491
load_cache(IMAGE ${ZCMAKE_APPLICATION} BINARY_DIR ${BINARY_DIR})
492492
import_kconfig(CONFIG_ ${BINARY_DIR}/zephyr/.config TARGET ${ZCMAKE_APPLICATION})
493+
set(DEVICETREE_TARGET ${ZCMAKE_APPLICATION}_devicetree_target)
494+
include(${BINARY_DIR}/zephyr/dts.cmake)
493495

494496
# This custom target informs CMake how the BYPRODUCTS are generated if a target
495497
# depends directly on the BYPRODUCT instead of depending on the image target.
@@ -737,3 +739,86 @@ function(sysbuild_images_order variable dependency_type)
737739
topological_sort(TARGETS ${SIS_IMAGES} PROPERTY_NAME ${property_name} RESULT sorted)
738740
set(${variable} ${sorted} PARENT_SCOPE)
739741
endfunction()
742+
743+
# Internal macro for defining the sysbuild_dt_* CMake extensions, used to
744+
# retrieve devicetree information from a Zephyr based build system.
745+
#
746+
# It takes a dt_* function <name> and adds common wrapper code, which
747+
# adds an `IMAGE` argument to select the devicetree of a given <image>,
748+
# and forwards all other arguments to the original function, including
749+
# the sole return variable <var> - a common trait of the dt_* API.
750+
#
751+
# For additional documentation of each dt_* CMake extension,
752+
# see section 4.1. of cmake/modules/extensions.cmake.
753+
#
754+
macro(sysbuild_dt_function name)
755+
function(sysbuild_${name} var)
756+
cmake_parse_arguments(PARSE_ARGV 1 SBDT "" "IMAGE" "")
757+
zephyr_check_arguments_required_all("sysbuild_${name}" SBDT IMAGE)
758+
759+
set(DEVICETREE_TARGET ${SBDT_IMAGE}_devicetree_target)
760+
if(NOT TARGET ${SBDT_IMAGE} OR NOT TARGET ${DEVICETREE_TARGET})
761+
message(FATAL_ERROR "sysbuild_${name}(...) image '${SBDT_IMAGE}' "
762+
"does not exist or its devicetree is not loaded yet"
763+
)
764+
endif()
765+
766+
cmake_language(CALL ${name} ${var} ${SBDT_UNPARSED_ARGUMENTS})
767+
set(${var} "${${var}}" PARENT_SCOPE)
768+
endfunction()
769+
endmacro()
770+
771+
# Usage:
772+
# sysbuild_dt_nodelabel(<var> IMAGE <image> NODELABEL <label>)
773+
#
774+
sysbuild_dt_function(dt_nodelabel)
775+
776+
# Usage:
777+
# sysbuild_dt_alias(<var> IMAGE <image> PROPERTY <prop>)
778+
#
779+
sysbuild_dt_function(dt_alias)
780+
781+
# Usage:
782+
# sysbuild_dt_node_exists(<var> IMAGE <image> PATH <path>)
783+
#
784+
sysbuild_dt_function(dt_node_exists)
785+
786+
# Usage:
787+
# sysbuild_dt_node_has_status(<var> IMAGE <image> PATH <path> STATUS <status>)
788+
#
789+
sysbuild_dt_function(dt_node_has_status)
790+
791+
# Usage:
792+
# sysbuild_dt_prop(<var> IMAGE <image> PATH <path> PROPERTY <prop> [INDEX <idx>])
793+
#
794+
sysbuild_dt_function(dt_prop)
795+
796+
# Usage:
797+
# sysbuild_dt_comp_path(<var> IMAGE <image> COMPATIBLE <compatible> [INDEX <idx>])
798+
#
799+
sysbuild_dt_function(dt_comp_path)
800+
801+
# Usage:
802+
# sysbuild_dt_num_regs(<var> IMAGE <image> PATH <path>)
803+
#
804+
sysbuild_dt_function(dt_num_regs)
805+
806+
# Usage:
807+
# sysbuild_dt_reg_addr(<var> IMAGE <image> PATH <path> [INDEX <idx>] [NAME <name>])
808+
#
809+
sysbuild_dt_function(dt_reg_addr)
810+
811+
# Usage:
812+
# sysbuild_dt_reg_size(<var> IMAGE <image> PATH <path> [INDEX <idx>] [NAME <name>])
813+
#
814+
sysbuild_dt_function(dt_reg_size)
815+
816+
# Usage:
817+
# sysbuild_dt_has_chosen(<var> IMAGE <image> PROPERTY <prop>)
818+
#
819+
sysbuild_dt_function(dt_has_chosen)
820+
821+
# Usage:
822+
# sysbuild_dt_chosen(<var> IMAGE <image> PROPERTY <prop>)
823+
#
824+
sysbuild_dt_function(dt_chosen)

0 commit comments

Comments
 (0)