Skip to content

Commit 38fdd95

Browse files
57300jukkar
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) (cherry picked from commit 46d86b4) (cherry picked from commit c58279c)
1 parent 4cd36a9 commit 38fdd95

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
@@ -3611,6 +3611,9 @@ endfunction()
36113611
# alias at the beginning of a path interchangeably with the full
36123612
# path to the aliased node in these functions. The usage comments
36133613
# will make this clear in each case.
3614+
#
3615+
# - Each of these methods also has a sysbuild_dt_* counterpart.
3616+
# See share/sysbuild/cmake/modules/sysbuild_extensions.cmake.
36143617

36153618
# Usage:
36163619
# dt_nodelabel(<var> NODELABEL <label>)
@@ -3638,6 +3641,10 @@ endfunction()
36383641
# NODELABEL <label> : Node label
36393642
# REQUIRED : Generate a fatal error if the node-label is not found
36403643
function(dt_nodelabel var)
3644+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3645+
message(FATAL_ERROR "dt_nodelabel(${ARGV0} ...) devicetree is not available.")
3646+
endif()
3647+
36413648
set(options "REQUIRED")
36423649
set(req_single_args "NODELABEL")
36433650
cmake_parse_arguments(DT_LABEL "${options}" "${req_single_args}" "" ${ARGN})
@@ -3654,7 +3661,7 @@ function(dt_nodelabel var)
36543661
endif()
36553662
endforeach()
36563663

3657-
get_target_property(${var} devicetree_target "DT_NODELABEL|${DT_LABEL_NODELABEL}")
3664+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_NODELABEL|${DT_LABEL_NODELABEL}")
36583665
if(${${var}} STREQUAL ${var}-NOTFOUND)
36593666
if(DT_LABEL_REQUIRED)
36603667
message(FATAL_ERROR "required nodelabel not found: ${DT_LABEL_NODELABEL}")
@@ -3686,6 +3693,10 @@ endfunction()
36863693
# PROPERTY <prop> : The alias to check
36873694
# REQUIRED : Generate a fatal error if the alias is not found
36883695
function(dt_alias var)
3696+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3697+
message(FATAL_ERROR "dt_alias(${ARGV0} ...) devicetree is not available.")
3698+
endif()
3699+
36893700
set(options "REQUIRED")
36903701
set(req_single_args "PROPERTY")
36913702
cmake_parse_arguments(DT_ALIAS "${options}" "${req_single_args}" "" ${ARGN})
@@ -3702,7 +3713,7 @@ function(dt_alias var)
37023713
endif()
37033714
endforeach()
37043715

3705-
get_target_property(${var} devicetree_target "DT_ALIAS|${DT_ALIAS_PROPERTY}")
3716+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_ALIAS|${DT_ALIAS_PROPERTY}")
37063717
if(${${var}} STREQUAL ${var}-NOTFOUND)
37073718
if(DT_ALIAS_REQUIRED)
37083719
message(FATAL_ERROR "required alias not found: ${DT_ALIAS_PROPERTY}")
@@ -3730,6 +3741,10 @@ endfunction()
37303741
# <var> : Return variable where the check result will be returned
37313742
# PATH <path> : Node path
37323743
function(dt_node_exists var)
3744+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3745+
message(FATAL_ERROR "dt_node_exists(${ARGV0} ...) devicetree is not available.")
3746+
endif()
3747+
37333748
set(req_single_args "PATH")
37343749
cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
37353750

@@ -3775,6 +3790,10 @@ endfunction()
37753790
# PATH <path> : Node path
37763791
# STATUS <status> : Status to check
37773792
function(dt_node_has_status var)
3793+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3794+
message(FATAL_ERROR "dt_node_has_status(${ARGV0} ...) devicetree is not available.")
3795+
endif()
3796+
37783797
set(req_single_args "PATH;STATUS")
37793798
cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
37803799

@@ -3861,6 +3880,10 @@ endfunction()
38613880
# INDEX <idx> : Optional index when retrieving a value in an array property
38623881
# REQUIRED : Generate a fatal error if the property is not found
38633882
function(dt_prop var)
3883+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3884+
message(FATAL_ERROR "dt_prop(${ARGV0} ...) devicetree is not available.")
3885+
endif()
3886+
38643887
set(options "REQUIRED")
38653888
set(req_single_args "PATH;PROPERTY")
38663889
set(single_args "INDEX")
@@ -3879,7 +3902,7 @@ function(dt_prop var)
38793902
endforeach()
38803903

38813904
dt_path_internal(canonical "${DT_PROP_PATH}")
3882-
get_property(exists TARGET devicetree_target
3905+
get_property(exists TARGET "${DEVICETREE_TARGET}"
38833906
PROPERTY "DT_PROP|${canonical}|${DT_PROP_PROPERTY}"
38843907
SET
38853908
)
@@ -3892,7 +3915,7 @@ function(dt_prop var)
38923915
return()
38933916
endif()
38943917

3895-
get_target_property(val devicetree_target
3918+
get_target_property(val "${DEVICETREE_TARGET}"
38963919
"DT_PROP|${canonical}|${DT_PROP_PROPERTY}"
38973920
)
38983921

@@ -3921,6 +3944,10 @@ endfunction()
39213944
# INDEX <idx> : Optional index when retrieving a value in an array property
39223945

39233946
function(dt_comp_path var)
3947+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
3948+
message(FATAL_ERROR "dt_comp_path(${ARGV0} ...) devicetree is not available.")
3949+
endif()
3950+
39243951
set(req_single_args "COMPATIBLE")
39253952
set(single_args "INDEX")
39263953
cmake_parse_arguments(DT_COMP "" "${req_single_args};${single_args}" "" ${ARGN})
@@ -3937,7 +3964,7 @@ function(dt_comp_path var)
39373964
endif()
39383965
endforeach()
39393966

3940-
get_property(exists TARGET devicetree_target
3967+
get_property(exists TARGET "${DEVICETREE_TARGET}"
39413968
PROPERTY "DT_COMP|${DT_COMP_COMPATIBLE}"
39423969
SET
39433970
)
@@ -3947,7 +3974,7 @@ function(dt_comp_path var)
39473974
return()
39483975
endif()
39493976

3950-
get_target_property(val devicetree_target
3977+
get_target_property(val "${DEVICETREE_TARGET}"
39513978
"DT_COMP|${DT_COMP_COMPATIBLE}"
39523979
)
39533980

@@ -3976,6 +4003,10 @@ endfunction()
39764003
# <var> : Return variable where the property value will be stored
39774004
# PATH <path> : Node path
39784005
function(dt_num_regs var)
4006+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4007+
message(FATAL_ERROR "dt_num_regs(${ARGV0} ...) devicetree is not available.")
4008+
endif()
4009+
39794010
set(req_single_args "PATH")
39804011
cmake_parse_arguments(DT_REG "" "${req_single_args}" "" ${ARGN})
39814012

@@ -3992,7 +4023,7 @@ function(dt_num_regs var)
39924023
endforeach()
39934024

39944025
dt_path_internal(canonical "${DT_REG_PATH}")
3995-
get_target_property(${var} devicetree_target "DT_REG|${canonical}|NUM")
4026+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_REG|${canonical}|NUM")
39964027

39974028
set(${var} ${${var}} PARENT_SCOPE)
39984029
endfunction()
@@ -4022,6 +4053,10 @@ endfunction()
40224053
# INDEX <idx> : Register block index number
40234054
# NAME <name> : Register block name
40244055
function(dt_reg_addr var)
4056+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4057+
message(FATAL_ERROR "dt_reg_addr(${ARGV0} ...) devicetree is not available.")
4058+
endif()
4059+
40254060
set(req_single_args "PATH")
40264061
set(single_args "INDEX;NAME")
40274062
cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
@@ -4051,7 +4086,7 @@ function(dt_reg_addr var)
40514086
endif()
40524087

40534088
dt_path_internal(canonical "${DT_REG_PATH}")
4054-
get_target_property(${var}_list devicetree_target "DT_REG|${canonical}|ADDR")
4089+
get_target_property(${var}_list "${DEVICETREE_TARGET}" "DT_REG|${canonical}|ADDR")
40554090

40564091
list(GET ${var}_list ${DT_REG_INDEX} ${var})
40574092

@@ -4082,6 +4117,10 @@ endfunction()
40824117
# INDEX <idx> : Register block index number
40834118
# NAME <name> : Register block name
40844119
function(dt_reg_size var)
4120+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4121+
message(FATAL_ERROR "dt_reg_size(${ARGV0} ...) devicetree is not available.")
4122+
endif()
4123+
40854124
set(req_single_args "PATH")
40864125
set(single_args "INDEX;NAME")
40874126
cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
@@ -4111,7 +4150,7 @@ function(dt_reg_size var)
41114150
endif()
41124151

41134152
dt_path_internal(canonical "${DT_REG_PATH}")
4114-
get_target_property(${var}_list devicetree_target "DT_REG|${canonical}|SIZE")
4153+
get_target_property(${var}_list "${DEVICETREE_TARGET}" "DT_REG|${canonical}|SIZE")
41154154

41164155
list(GET ${var}_list ${DT_REG_INDEX} ${var})
41174156

@@ -4159,6 +4198,10 @@ endfunction()
41594198
# <var> : Return variable
41604199
# PROPERTY <prop> : Chosen property
41614200
function(dt_has_chosen var)
4201+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4202+
message(FATAL_ERROR "dt_has_chosen(${ARGV0} ...) devicetree is not available.")
4203+
endif()
4204+
41624205
set(req_single_args "PROPERTY")
41634206
cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
41644207

@@ -4174,7 +4217,7 @@ function(dt_has_chosen var)
41744217
endif()
41754218
endforeach()
41764219

4177-
get_target_property(exists devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
4220+
get_target_property(exists "${DEVICETREE_TARGET}" "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
41784221

41794222
if(${exists} STREQUAL exists-NOTFOUND)
41804223
set(${var} FALSE PARENT_SCOPE)
@@ -4194,6 +4237,10 @@ endfunction()
41944237
# <var> : Return variable where the node path will be stored
41954238
# PROPERTY <prop> : Chosen property
41964239
function(dt_chosen var)
4240+
if(NOT DEFINED DEVICETREE_TARGET OR NOT TARGET "${DEVICETREE_TARGET}")
4241+
message(FATAL_ERROR "dt_chosen(${ARGV0} ...) devicetree is not available.")
4242+
endif()
4243+
41974244
set(req_single_args "PROPERTY")
41984245
cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
41994246

@@ -4209,7 +4256,7 @@ function(dt_chosen var)
42094256
endif()
42104257
endforeach()
42114258

4212-
get_target_property(${var} devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
4259+
get_target_property(${var} "${DEVICETREE_TARGET}" "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
42134260

42144261
if(${${var}} STREQUAL ${var}-NOTFOUND)
42154262
set(${var} PARENT_SCOPE)
@@ -4281,7 +4328,7 @@ endfunction()
42814328
# to an existing node. Set it to FALSE otherwise. See
42824329
# dt_path_internal for a definition and examples of 'canonical' paths.
42834330
function(dt_path_internal_exists var path)
4284-
get_target_property(path_prop devicetree_target "DT_NODE|${path}")
4331+
get_target_property(path_prop "${DEVICETREE_TARGET}" "DT_NODE|${path}")
42854332
if (path_prop)
42864333
set(${var} TRUE PARENT_SCOPE)
42874334
else()

share/sysbuild/cmake/modules/sysbuild_extensions.cmake

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,8 @@ function(ExternalZephyrProject_Cmake)
503503
endif()
504504
load_cache(IMAGE ${ZCMAKE_APPLICATION} BINARY_DIR ${BINARY_DIR})
505505
import_kconfig(CONFIG_ ${BINARY_DIR}/zephyr/.config TARGET ${ZCMAKE_APPLICATION})
506+
set(DEVICETREE_TARGET ${ZCMAKE_APPLICATION}_devicetree_target)
507+
include(${BINARY_DIR}/zephyr/dts.cmake)
506508

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

0 commit comments

Comments
 (0)