Skip to content

Commit fdea3c9

Browse files
gmarullcarlescufi
authored andcommitted
devicetree: add DT(_INST)_FOREACH_PROP_ELEM_SEP(_VARGS)
Add a new set of helpers for expanding property entries with a separator. These macros complement DT(_INST)FOREACH_PROP_ELEM(_VARGS) by adding the capability to expand with a custom separator between property entries. This allows, in some cases, to re-use existing macros (e.g. DT_PROP_BY_IDX) without creating an auxiliary macro that just appends a separator. Example: ```dts n: node { ... my-gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>, <&gpiob 1 GPIO_ACTIVE_HIGH>; }; ``` Before: ```c #define GPIO_DT_SPEC_BY_IDX_AND_COMMA(node_id, prop, idx) \ GPIO_DT_SPEC_BY_IDX(node_id, prop, idx), struct gpio_dt_spec specs[] = { DT_FOREACH_PROP_ELEM(DT_NODELABEL(n), my_gpios, GPIO_DT_SPEC_BY_IDX_AND_COMMA) }; ``` After: ```c struct gpio_dt_spec specs[] = { DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(n), my_gpios, GPIO_DT_SPEC_BY_IDX, (,)) }; ``` Signed-off-by: Gerard Marull-Paretas <[email protected]>
1 parent 1f98c24 commit fdea3c9

File tree

3 files changed

+120
-7
lines changed

3 files changed

+120
-7
lines changed

doc/build/dts/macros.bnf

+3-1
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ node-macro =/ %s"DT_N" path-id %s"_COMPAT_VENDOR_IDX_" DIGIT
6060
; Every non-root node gets one of these macros, which expands to the node
6161
; identifier for that node's parent in the devicetree.
6262
node-macro =/ %s"DT_N" path-id %s"_PARENT"
63-
; These are used internally by DT_FOREACH_PROP_ELEM(_VARGS), which
63+
; These are used internally by DT_FOREACH_PROP_ELEM(_SEP)(_VARGS), which
6464
; iterates over each property element.
6565
node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM"
66+
node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_SEP"
6667
node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_VARGS"
68+
node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_SEP_VARGS"
6769
; These are used internally by DT_FOREACH_CHILD, which iterates over
6870
; each child node.
6971
node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD"

include/zephyr/devicetree.h

+101-1
Original file line numberDiff line numberDiff line change
@@ -2507,6 +2507,53 @@
25072507
#define DT_FOREACH_PROP_ELEM(node_id, prop, fn) \
25082508
DT_CAT4(node_id, _P_, prop, _FOREACH_PROP_ELEM)(fn)
25092509

2510+
/**
2511+
* @brief Invokes @p fn for each element in the value of property @p prop with
2512+
* separator.
2513+
*
2514+
* Example devicetree fragment:
2515+
*
2516+
* @code{.dts}
2517+
* n: node {
2518+
* my-gpios = <&gpioa 0 GPIO_ACTICE_HIGH>,
2519+
* <&gpiob 1 GPIO_ACTIVE_HIGH>;
2520+
* };
2521+
* @endcode
2522+
*
2523+
* Example usage:
2524+
*
2525+
* @code{.c}
2526+
* struct gpio_dt_spec specs[] = {
2527+
* DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(n), my_gpios,
2528+
* GPIO_DT_SPEC_BY_IDX, (,))
2529+
* };
2530+
* @endcode
2531+
*
2532+
* This expands as a first step to:
2533+
*
2534+
* @code{.c}
2535+
* struct gpio_dt_spec specs[] = {
2536+
* struct gpio_dt_spec specs[] = {
2537+
* GPIO_DT_SPEC_BY_IDX(DT_NODELABEL(n), my_gpios, 0),
2538+
* GPIO_DT_SPEC_BY_IDX(DT_NODELABEL(n), my_gpios, 1)
2539+
* };
2540+
* @endcode
2541+
*
2542+
* The "prop" argument must refer to a property with type string,
2543+
* array, uint8-array, string-array, phandles, or phandle-array. It is
2544+
* an error to use this macro with properties of other types.
2545+
*
2546+
* @param node_id node identifier
2547+
* @param prop lowercase-and-underscores property name
2548+
* @param fn macro to invoke
2549+
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
2550+
* this is required to enable providing a comma as separator.
2551+
*
2552+
* @see DT_FOREACH_PROP_ELEM
2553+
*/
2554+
#define DT_FOREACH_PROP_ELEM_SEP(node_id, prop, fn, sep) \
2555+
DT_CAT4(node_id, _P_, prop, _FOREACH_PROP_ELEM_SEP)(fn, sep)
2556+
25102557
/**
25112558
* @brief Invokes @p fn for each element in the value of property @p prop with
25122559
* multiple arguments.
@@ -2527,6 +2574,23 @@
25272574
#define DT_FOREACH_PROP_ELEM_VARGS(node_id, prop, fn, ...) \
25282575
DT_CAT4(node_id, _P_, prop, _FOREACH_PROP_ELEM_VARGS)(fn, __VA_ARGS__)
25292576

2577+
/**
2578+
* @brief Invokes @p fn for each element in the value of property @p prop with
2579+
* multiple arguments and a separator.
2580+
*
2581+
* @param node_id node identifier
2582+
* @param prop lowercase-and-underscores property name
2583+
* @param fn macro to invoke
2584+
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
2585+
* this is required to enable providing a comma as separator.
2586+
* @param ... variable number of arguments to pass to fn
2587+
*
2588+
* @see DT_FOREACH_PROP_ELEM_VARGS
2589+
*/
2590+
#define DT_FOREACH_PROP_ELEM_SEP_VARGS(node_id, prop, fn, sep, ...) \
2591+
DT_CAT4(node_id, _P_, prop, _FOREACH_PROP_ELEM_SEP_VARGS)( \
2592+
fn, sep, __VA_ARGS__)
2593+
25302594
/**
25312595
* @brief Invokes @p fn for each status `okay` node of a compatible.
25322596
*
@@ -3592,6 +3656,21 @@
35923656
#define DT_INST_FOREACH_PROP_ELEM(inst, prop, fn) \
35933657
DT_FOREACH_PROP_ELEM(DT_DRV_INST(inst), prop, fn)
35943658

3659+
/**
3660+
* @brief Invokes @p fn for each element of property @p prop for
3661+
* a `DT_DRV_COMPAT` instance with a separator.
3662+
*
3663+
* Equivalent to DT_FOREACH_PROP_ELEM_SEP(DT_DRV_INST(inst), prop, fn, sep).
3664+
*
3665+
* @param inst instance number
3666+
* @param prop lowercase-and-underscores property name
3667+
* @param fn macro to invoke
3668+
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
3669+
* this is required to enable providing a comma as separator.
3670+
*/
3671+
#define DT_INST_FOREACH_PROP_ELEM_SEP(inst, prop, fn, sep) \
3672+
DT_FOREACH_PROP_ELEM_SEP(DT_DRV_INST(inst), prop, fn, sep)
3673+
35953674
/**
35963675
* @brief Invokes @p fn for each element of property @p prop for
35973676
* a `DT_DRV_COMPAT` instance with multiple arguments.
@@ -3610,7 +3689,28 @@
36103689
DT_FOREACH_PROP_ELEM_VARGS(DT_DRV_INST(inst), prop, fn, __VA_ARGS__)
36113690

36123691
/**
3613-
* @brief Does a `DT_DRV_COMPAT` instance have a property?
3692+
* @brief Invokes @p fn for each element of property @p prop for
3693+
* a `DT_DRV_COMPAT` instance with multiple arguments and a sepatator.
3694+
*
3695+
* Equivalent to
3696+
* DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_DRV_INST(inst), prop, fn, sep,
3697+
* __VA_ARGS__)
3698+
*
3699+
* @param inst instance number
3700+
* @param prop lowercase-and-underscores property name
3701+
* @param fn macro to invoke
3702+
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
3703+
* this is required to enable providing a comma as separator.
3704+
* @param ... variable number of arguments to pass to fn
3705+
*
3706+
* @see DT_INST_FOREACH_PROP_ELEM
3707+
*/
3708+
#define DT_INST_FOREACH_PROP_ELEM_SEP_VARGS(inst, prop, fn, sep, ...) \
3709+
DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_DRV_INST(inst), prop, fn, sep, \
3710+
__VA_ARGS__)
3711+
3712+
/**
3713+
* @brief Does a DT_DRV_COMPAT instance have a property?
36143714
* @param inst instance number
36153715
* @param prop lowercase-and-underscores property name
36163716
* @return 1 if the instance has the property, 0 otherwise.

scripts/dts/gen_defines.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -660,13 +660,24 @@ def write_vanilla_props(node):
660660
if prop.type in FOREACH_PROP_ELEM_TYPES:
661661
# DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM
662662
macro2val[f"{macro}_FOREACH_PROP_ELEM(fn)"] = \
663-
' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
664-
for i in range(len(prop.val)))
663+
' \\\n\t'.join(
664+
f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
665+
for i in range(len(prop.val)))
666+
667+
macro2val[f"{macro}_FOREACH_PROP_ELEM_SEP(fn, sep)"] = \
668+
' DT_DEBRACKET_INTERNAL sep \\\n\t'.join(
669+
f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
670+
for i in range(len(prop.val)))
665671

666672
macro2val[f"{macro}_FOREACH_PROP_ELEM_VARGS(fn, ...)"] = \
667-
' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {prop_id}, {i},'
668-
' __VA_ARGS__)'
669-
for i in range(len(prop.val)))
673+
' \\\n\t'.join(
674+
f'fn(DT_{node.z_path_id}, {prop_id}, {i}, __VA_ARGS__)'
675+
for i in range(len(prop.val)))
676+
677+
macro2val[f"{macro}_FOREACH_PROP_ELEM_SEP_VARGS(fn, sep, ...)"] = \
678+
' DT_DEBRACKET_INTERNAL sep \\\n\t'.join(
679+
f'fn(DT_{node.z_path_id}, {prop_id}, {i}, __VA_ARGS__)'
680+
for i in range(len(prop.val)))
670681

671682
plen = prop_len(prop)
672683
if plen is not None:

0 commit comments

Comments
 (0)