diff --git a/doc/guides/dts/macros.bnf b/doc/guides/dts/macros.bnf index 6211198ab39..838cba05180 100644 --- a/doc/guides/dts/macros.bnf +++ b/doc/guides/dts/macros.bnf @@ -51,6 +51,9 @@ node-macro =/ %s"DT_N" path-id %s"_PARENT" ; These are used internally by DT_FOREACH_CHILD, which iterates over ; each child node. node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD" +; These are used internally by DT_FOREACH_CHILD_STATUS_OKAY, which iterates +; over each child node with status "okay". +node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD_STATUS_OKAY" ; The node's status macro; dt-name in this case is something like "okay" ; or "disabled". node-macro =/ %s"DT_N" path-id %s"_STATUS_" dt-name diff --git a/include/devicetree.h b/include/devicetree.h index c65546bc0d2..ba94826773e 100644 --- a/include/devicetree.h +++ b/include/devicetree.h @@ -1485,6 +1485,21 @@ #define DT_FOREACH_CHILD(node_id, fn) \ DT_CAT(node_id, _FOREACH_CHILD)(fn) +/** + * @brief Call "fn" on the child nodes with status "okay" + * + * The macro "fn" should take one argument, which is the node + * identifier for the child node. + * + * As usual, both a missing status and an "ok" status are + * treated as "okay". + * + * @param node_id node identifier + * @param fn macro to invoke + */ +#define DT_FOREACH_CHILD_STATUS_OKAY(node_id, fn) \ + DT_CAT(node_id, _FOREACH_CHILD_STATUS_OKAY)(fn) + /** * @brief Invokes "fn" for each element in the value of property "prop". * diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index 6ddde90934c..5ce841718ee 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -119,6 +119,7 @@ def main(): f"DT_{node.parent.z_path_id}") write_child_functions(node) + write_child_functions_status_okay(node) write_dep_info(node) write_idents_and_existence(node) write_bus(node) @@ -479,6 +480,18 @@ def write_child_functions(node): node.children.values())) +def write_child_functions_status_okay(node): + # Writes macro that are helpers that will call a macro/function + # for each child node with status "okay". + + functions = '' + for child in node.children.values(): + if child.status == "okay": + functions = functions + f"fn(DT_{child.z_path_id}) " + + out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY(fn)", functions) + + def write_status(node): out_dt_define(f"{node.z_path_id}_STATUS_{str2ident(node.status)}", 1) diff --git a/tests/lib/devicetree/api/app.overlay b/tests/lib/devicetree/api/app.overlay index f5ad07da58d..61560df5a8c 100644 --- a/tests/lib/devicetree/api/app.overlay +++ b/tests/lib/devicetree/api/app.overlay @@ -386,12 +386,15 @@ test_child_a: child-a { val = <0>; + status = "okay"; }; test_child_b: child-b { val = <1>; + status = "okay"; }; test_child_c: child-c { val = <2>; + status = "disabled"; }; }; diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 22ed662e4e4..db61051c946 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -1568,8 +1568,13 @@ static void test_child_nodes_list(void) DT_INST_FOREACH_CHILD(0, TEST_FUNC) }; + struct vnd_child_binding vals_status_okay[] = { + DT_FOREACH_CHILD_STATUS_OKAY(TEST_PARENT, TEST_FUNC) + }; + zassert_equal(ARRAY_SIZE(vals), 3, ""); zassert_equal(ARRAY_SIZE(vals_inst), 3, ""); + zassert_equal(ARRAY_SIZE(vals_status_okay), 2, ""); zassert_false(strlen(STRINGIFY(TEST_PARENT)) == 0, ""); @@ -1579,6 +1584,8 @@ static void test_child_nodes_list(void) zassert_equal(vals_inst[0].val, 0, ""); zassert_equal(vals_inst[1].val, 1, ""); zassert_equal(vals_inst[2].val, 2, ""); + zassert_equal(vals_status_okay[0].val, 0, ""); + zassert_equal(vals_status_okay[1].val, 1, ""); #undef TEST_PARENT #undef TEST_FUNC