diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index c9aab665343..94ab5b8d3ad 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -2470,6 +2470,20 @@ */ #define DT_FOREACH_NODE(fn) DT_FOREACH_HELPER(fn) +/** + * @brief Invokes @p fn for every node in the tree with multiple arguments. + * + * The macro @p fn takes multiple arguments. The first should be the node + * identifier for the node. The remaining are passed-in by the caller. + * + * The macro is expanded once for each node in the tree. The order that nodes + * are visited in is not specified. + * + * @param fn macro to invoke + * @param ... variable number of arguments to pass to @p fn + */ +#define DT_FOREACH_NODE_VARGS(fn, ...) DT_FOREACH_VARGS_HELPER(fn, __VA_ARGS__) + /** * @brief Invokes @p fn for every status `okay` node in the tree. * @@ -2483,6 +2497,22 @@ */ #define DT_FOREACH_STATUS_OKAY_NODE(fn) DT_FOREACH_OKAY_HELPER(fn) +/** + * @brief Invokes @p fn for every status `okay` node in the tree with multiple + * arguments. + * + * The macro @p fn takes multiple arguments. The first should be the node + * identifier for the node. The remaining are passed-in by the caller. + * + * The macro is expanded once for each node in the tree with status `okay` (as + * usual, a missing status property is treated as status `okay`). The order + * that nodes are visited in is not specified. + * + * @param fn macro to invoke + * @param ... variable number of arguments to pass to @p fn + */ +#define DT_FOREACH_STATUS_OKAY_NODE_VARGS(fn, ...) DT_FOREACH_OKAY_VARGS_HELPER(fn, __VA_ARGS__) + /** * @brief Invokes @p fn for each child of @p node_id * diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index 2394e3a7d47..ed47d3ae151 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -921,6 +921,11 @@ def write_global_macros(edt): out_dt_define("FOREACH_OKAY_HELPER(fn)", " ".join(f"fn(DT_{node.z_path_id})" for node in edt.nodes if node.status == "okay")) + out_dt_define("FOREACH_VARGS_HELPER(fn, ...)", + " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)" for node in edt.nodes)) + out_dt_define("FOREACH_OKAY_VARGS_HELPER(fn, ...)", + " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)" for node in edt.nodes + if node.status == "okay")) n_okay_macros = {} for_each_macros = {} diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 587c56a3826..eb96de5a81d 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -1426,8 +1426,19 @@ ZTEST(devicetree_api, test_foreach) zassert_equal(1, DT_FOREACH_STATUS_OKAY_NODE(IS_ALIASES), ""); zassert_equal(0, DT_FOREACH_STATUS_OKAY_NODE(IS_DISABLED_GPIO), ""); +#define IS_ALIASES_VARGS(node_id, mul) + ((mul) * DT_SAME_NODE(DT_PATH(aliases), node_id)) +#define IS_DISABLED_GPIO_VARGS(node_id, mul) + ((mul) * \ + DT_SAME_NODE(DT_NODELABEL(disabled_gpio), node_id)) + zassert_equal(2, DT_FOREACH_NODE_VARGS(IS_ALIASES_VARGS, 2), ""); + zassert_equal(2, DT_FOREACH_NODE_VARGS(IS_DISABLED_GPIO_VARGS, 2), ""); + zassert_equal(2, DT_FOREACH_STATUS_OKAY_NODE_VARGS(IS_ALIASES_VARGS, 2), ""); + zassert_equal(0, DT_FOREACH_STATUS_OKAY_NODE_VARGS(IS_DISABLED_GPIO_VARGS, 2), ""); + + #undef IS_ALIASES #undef IS_DISABLED_GPIO +#undef IS_ALIASES_VARGS +#undef IS_DISABLED_GPIO_VARGS } #undef DT_DRV_COMPAT