devicetree: better DT_PROP_BY_IDX()/DT_FOREACH_PROP_ELEM() support
Support use of these macros with properties of type phandle and string by allowing iterating over: - a phandle as if it were a phandles of length 1, for convenience and consistency with our ability to take its length (and getting 1) - the non-null characters in a string: we exclude the null for consistency with the return value of DT_PROP_LEN() on string properties, which, like strlen(), does not include the null With this and a previous patch expanding the usage of DT_PROP_LEN(), there is now a relationship between being able to take a property's logical length with DT_PROP_LEN() and being able to iterate over its logical elements with DT_FOREACH_PROP_ELEM(). Explain this in the documentation. Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
parent
8aa83f6ae8
commit
0c29e07e30
|
@ -725,16 +725,28 @@
|
|||
* It might help to read the argument order as being similar to
|
||||
* `node->property[index]`.
|
||||
*
|
||||
* When the property's binding has type array, string-array,
|
||||
* uint8-array, or phandles, this expands to the idx-th array element
|
||||
* as an integer, string literal, or node identifier respectively.
|
||||
* The return value depends on the property's type:
|
||||
*
|
||||
* - for types array, string-array, uint8-array, and phandles,
|
||||
* this expands to the idx-th array element as an
|
||||
* integer, string literal, integer, and node identifier
|
||||
* respectively
|
||||
*
|
||||
* - for type phandle, idx must be 0 and the expansion is a node
|
||||
* identifier (this treats phandle like a phandles of length 1)
|
||||
*
|
||||
* - for type string, idx must be 0 and the expansion is the the
|
||||
* entire string (this treats string like string-array of length 1)
|
||||
*
|
||||
* These properties are handled as special cases:
|
||||
*
|
||||
* - `reg` property: use DT_REG_ADDR_BY_IDX() or DT_REG_SIZE_BY_IDX() instead
|
||||
* - `interrupts` property: use DT_IRQ_BY_IDX() instead
|
||||
* - `reg`: use DT_REG_ADDR_BY_IDX() or DT_REG_SIZE_BY_IDX() instead
|
||||
* - `interrupts`: use DT_IRQ_BY_IDX()
|
||||
* - `ranges`: use DT_NUM_RANGES()
|
||||
* - `dma-ranges`: it is an error to use this property with
|
||||
* DT_PROP_BY_IDX()
|
||||
*
|
||||
* For non-array properties, behavior is undefined.
|
||||
* For properties of other types, behavior is undefined.
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @param prop lowercase-and-underscores property name
|
||||
|
@ -2653,6 +2665,9 @@
|
|||
* DT_FOREACH_PROP_ELEM(), and @p idx is the current index into the array.
|
||||
* The @p idx values are integer literals starting from 0.
|
||||
*
|
||||
* The @p prop argument must refer to a property that can be passed to
|
||||
* DT_PROP_LEN().
|
||||
*
|
||||
* Example devicetree fragment:
|
||||
*
|
||||
* @code{.dts}
|
||||
|
@ -2687,13 +2702,10 @@
|
|||
* where `n` is the number of elements in @p prop, as it would be
|
||||
* returned by `DT_PROP_LEN(node_id, prop)`.
|
||||
*
|
||||
* The @p prop argument must refer to a property with type `string`,
|
||||
* `array`, `uint8-array`, `string-array`, `phandles`, or `phandle-array`. It
|
||||
* is an error to use this macro with properties of other types.
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @param prop lowercase-and-underscores property name
|
||||
* @param fn macro to invoke
|
||||
* @see DT_PROP_LEN
|
||||
*/
|
||||
#define DT_FOREACH_PROP_ELEM(node_id, prop, fn) \
|
||||
DT_CAT4(node_id, _P_, prop, _FOREACH_PROP_ELEM)(fn)
|
||||
|
@ -2730,9 +2742,8 @@
|
|||
* };
|
||||
* @endcode
|
||||
*
|
||||
* The "prop" argument must refer to a property with type string,
|
||||
* array, uint8-array, string-array, phandles, or phandle-array. It is
|
||||
* an error to use this macro with properties of other types.
|
||||
* The @p prop parameter has the same restrictions as the same parameter
|
||||
* given to DT_FOREACH_PROP_ELEM().
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @param prop lowercase-and-underscores property name
|
||||
|
@ -2755,6 +2766,9 @@
|
|||
* the array. The @p idx values are integer literals starting from 0. The
|
||||
* remaining arguments are passed-in by the caller.
|
||||
*
|
||||
* The @p prop parameter has the same restrictions as the same parameter
|
||||
* given to DT_FOREACH_PROP_ELEM().
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @param prop lowercase-and-underscores property name
|
||||
* @param fn macro to invoke
|
||||
|
@ -2769,6 +2783,9 @@
|
|||
* @brief Invokes @p fn for each element in the value of property @p prop with
|
||||
* multiple arguments and a separator.
|
||||
*
|
||||
* The @p prop parameter has the same restrictions as the same parameter
|
||||
* given to DT_FOREACH_PROP_ELEM().
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @param prop lowercase-and-underscores property name
|
||||
* @param fn macro to invoke
|
||||
|
|
|
@ -32,12 +32,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'python-devicetree',
|
|||
|
||||
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.'''
|
||||
|
@ -651,6 +645,12 @@ def write_vanilla_props(node):
|
|||
macro2val[macro + "_STRING_TOKEN"] = prop.val_as_token
|
||||
# DT_N_<node-id>_P_<prop-id>_IDX_<i>_STRING_UPPER_TOKEN
|
||||
macro2val[macro + "_STRING_UPPER_TOKEN"] = prop.val_as_token.upper()
|
||||
# DT_N_<node-id>_P_<prop-id>_IDX_0:
|
||||
# DT_N_<node-id>_P_<prop-id>_IDX_0_EXISTS:
|
||||
# Allows treating the string like a degenerate case of a
|
||||
# string-array of length 1.
|
||||
macro2val[macro + "_IDX_0"] = quote_str(prop.val)
|
||||
macro2val[macro + "_IDX_0_EXISTS"] = 1
|
||||
|
||||
if prop.enum_index is not None:
|
||||
# DT_N_<node-id>_P_<prop-id>_ENUM_IDX
|
||||
|
@ -692,33 +692,32 @@ def write_vanilla_props(node):
|
|||
macro2val[macro + f"_IDX_{i}"] = subval
|
||||
macro2val[macro + f"_IDX_{i}_EXISTS"] = 1
|
||||
|
||||
if prop.type in FOREACH_PROP_ELEM_TYPES:
|
||||
plen = prop_len(prop)
|
||||
if plen is not None:
|
||||
# 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)))
|
||||
for i in range(plen))
|
||||
|
||||
# DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM_SEP
|
||||
macro2val[f"{macro}_FOREACH_PROP_ELEM_SEP(fn, sep)"] = \
|
||||
' DT_DEBRACKET_INTERNAL sep \\\n\t'.join(
|
||||
f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
|
||||
for i in range(len(prop.val)))
|
||||
for i in range(plen))
|
||||
|
||||
# DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM_VARGS
|
||||
macro2val[f"{macro}_FOREACH_PROP_ELEM_VARGS(fn, ...)"] = \
|
||||
' \\\n\t'.join(
|
||||
f'fn(DT_{node.z_path_id}, {prop_id}, {i}, __VA_ARGS__)'
|
||||
for i in range(len(prop.val)))
|
||||
for i in range(plen))
|
||||
|
||||
# DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM_SEP_VARGS
|
||||
macro2val[f"{macro}_FOREACH_PROP_ELEM_SEP_VARGS(fn, sep, ...)"] = \
|
||||
' DT_DEBRACKET_INTERNAL sep \\\n\t'.join(
|
||||
f'fn(DT_{node.z_path_id}, {prop_id}, {i}, __VA_ARGS__)'
|
||||
for i in range(len(prop.val)))
|
||||
for i in range(plen))
|
||||
|
||||
plen = prop_len(prop)
|
||||
if plen is not None:
|
||||
# DT_N_<node-id>_P_<prop-id>_LEN
|
||||
macro2val[macro + "_LEN"] = plen
|
||||
|
||||
|
@ -786,6 +785,11 @@ def prop_len(prop):
|
|||
# Returns the property's length if and only if we should generate
|
||||
# a _LEN macro for the property. Otherwise, returns None.
|
||||
#
|
||||
# The set of types handled here coincides with the allowable types
|
||||
# that can be used with DT_PROP_LEN(). If you change this set,
|
||||
# make sure to update the doxygen string for that macro, and make
|
||||
# sure that DT_FOREACH_PROP_ELEM() works for the new types too.
|
||||
#
|
||||
# This deliberately excludes ranges, dma-ranges, reg and interrupts.
|
||||
# While they have array type, their lengths as arrays are
|
||||
# basically nonsense semantically due to #address-cells and
|
||||
|
|
Loading…
Reference in a new issue