devicetree: add DT_FOREACH_PROP_ELEM(node_id, prop, fn)
It can be convenient to "iterate" over the elements of a property, in
the same way it is convenient to "iterate" over enabled instances.
Add a new macro for doing this, along with a DT_INST_FOREACH_PROP_ELEM
variant.
This is likely to be more convenient than UTIL_LISTIFY or FOR_EACH in
some situations because:
- it handles inputs of any length
- compiler error messages will be shorter and more self-contained
- it is easier to use with phandle-array type properties, which
require more complicated macro boilerplate when used with
util_macro.h APIs
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py
index aaddaf5..6ddde90 100755
--- a/scripts/dts/gen_defines.py
+++ b/scripts/dts/gen_defines.py
@@ -32,6 +32,12 @@
from devicetree import edtlib
+# The set of binding types whose values can be iterated over with
+# DT_FOREACH_PROP_ELEM(). If you change this, make sure to update the
+# doxygen string for that macro.
+FOREACH_PROP_ELEM_TYPES = set(['string', 'array', 'uint8-array', 'string-array',
+ 'phandles', 'phandle-array'])
+
class LogFormatter(logging.Formatter):
'''A log formatter that prints the level name in lower case,
for compatibility with earlier versions of edtlib.'''
@@ -490,7 +496,8 @@
macro2val = {}
for prop_name, prop in node.props.items():
- macro = f"{node.z_path_id}_P_{str2ident(prop_name)}"
+ prop_id = str2ident(prop_name)
+ macro = f"{node.z_path_id}_P_{prop_id}"
val = prop2value(prop)
if val is not None:
# DT_N_<node-id>_P_<prop-id>
@@ -523,6 +530,12 @@
macro2val[macro + f"_IDX_{i}"] = subval
macro2val[macro + f"_IDX_{i}_EXISTS"] = 1
+ if prop.type in FOREACH_PROP_ELEM_TYPES:
+ # DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM
+ macro2val[f"{macro}_FOREACH_PROP_ELEM(fn)"] = \
+ ' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
+ for i in range(len(prop.val)))
+
plen = prop_len(prop)
if plen is not None:
# DT_N_<node-id>_P_<prop-id>_LEN