dts: Add _STRING_UNQUOTED string and string-array

This commit adds access to the string values without a quotes.

Signed-off-by: Radosław Koppel <r.koppel@k-el.com>
Co-authored-by: Marti Bolivar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Radosław Koppel 2022-05-13 13:40:34 +02:00 committed by Carles Cufí
parent e2546cdf1f
commit 14a1b2ffec
6 changed files with 348 additions and 3 deletions

View file

@ -0,0 +1,11 @@
# Copyright (c) 2023 Intel Corp.
# SPDX-License-Identifier: Apache-2.0
description: Test string array unquoted property container
compatible: "vnd,string-array-unquoted"
properties:
val:
type: string-array
required: true

View file

@ -0,0 +1,10 @@
# Copyright (c) 2023 Intel Corp.
# SPDX-License-Identifier: Apache-2.0
description: Test string unquoted property container
compatible: "vnd,string-unquoted"
properties:
val:
type: string

View file

@ -51,6 +51,7 @@
* _IDX_<i>_PH: phandle array's phandle by index (or phandle, phandles)
* _IDX_<i>_STRING_TOKEN: string array element value as a token
* _IDX_<i>_STRING_UPPER_TOKEN: string array element value as a uppercased token
* _IDX <i>_STRING_UNQUOTED: string array element value as a sequence of tokens, with no quotes
* _IDX_<i>_VAL_<val>: phandle array's specifier value by index
* _IDX_<i>_VAL_<val>_EXISTS: cell value exists, by index
* _LEN: property logical length
@ -59,6 +60,7 @@
* _NAME_<name>_VAL_<val>_EXISTS: cell value exists, by name
* _STRING_TOKEN: string property's value as a token
* _STRING_UPPER_TOKEN: like _STRING_TOKEN, but uppercased
* _STRING_UNQUOTED: string property's value as a sequence of tokens, with no quotes
*/
/**
@ -982,6 +984,67 @@
COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \
(DT_STRING_UPPER_TOKEN(node_id, prop)), (default_value))
/**
* @brief Get a string property's value as an unquoted sequence of tokens
*
* This removes "the quotes" from string-valued properties.
* That can be useful, for example,
* when defining floating point values as a string in devicetree
* that you would like to use to initialize a float or double variable in C.
*
* DT_STRING_UNQUOTED() can only be used for properties with string type.
*
* It is an error to use DT_STRING_UNQUOTED() in other circumstances.
*
* Example devicetree fragment:
*
* n1: node-1 {
* prop = "12.7";
* };
* n2: node-2 {
* prop = "0.5";
* }
* n3: node-3 {
* prop = "A B C";
* };
*
* Example bindings fragment:
*
* properties:
* prop:
* type: string
*
* Example usage:
*
* DT_STRING_UNQUOTED(DT_NODELABEL(n1), prop) // 12.7
* DT_STRING_UNQUOTED(DT_NODELABEL(n2), prop) // 0.5
* DT_STRING_UNQUOTED(DT_NODELABEL(n3), prop) // A B C
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @return the property's value as a sequence of tokens, with no quotes
*/
#define DT_STRING_UNQUOTED(node_id, prop) \
DT_CAT4(node_id, _P_, prop, _STRING_UNQUOTED)
/**
* @brief Like DT_STRING_UNQUOTED(), but with a fallback to @p default_value
*
* If the value exists, this expands to DT_STRING_UNQUOTED(node_id, prop).
* The @p default_value parameter is not expanded in this case.
*
* Otherwise, this expands to @p default_value.
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @param default_value a fallback value to expand to
* @return the property's value as a sequence of tokens, with no quotes,
* or @p default_value
*/
#define DT_STRING_UNQUOTED_OR(node_id, prop, default_value) \
COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \
(DT_STRING_UNQUOTED(node_id, prop)), (default_value))
/**
* @brief Get an element out of a string-array property as a token.
*
@ -1082,6 +1145,49 @@
#define DT_STRING_UPPER_TOKEN_BY_IDX(node_id, prop, idx) \
DT_CAT6(node_id, _P_, prop, _IDX_, idx, _STRING_UPPER_TOKEN)
/**
* @brief Get a string array item value as an unquoted sequence of tokens.
*
* This removes "the quotes" from string-valued item.
* That can be useful, for example,
* when defining floating point values as a string in devicetree
* that you would like to use to initialize a float or double variable in C.
*
* DT_STRING_UNQUOTED_BY_IDX() can only be used for properties with
* string-array type.
*
* It is an error to use DT_STRING_UNQUOTED_BY_IDX() in other circumstances.
*
* Example devicetree fragment:
*
* n1: node-1 {
* prop = "12.7", "34.1";
* };
* n2: node-2 {
* prop = "A B", "C D";
* }
*
* Example bindings fragment:
*
* properties:
* prop:
* type: string-array
*
* Example usage:
*
* DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(n1), prop, 0) // 12.7
* DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(n1), prop, 1) // 34.1
* DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(n2), prop, 0) // A B
* DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(n2), prop, 1) // C D
*
* @param node_id node identifier
* @param prop lowercase-and-underscores property name
* @param idx the index to get
* @return the property's value as a sequence of tokens, with no quotes
*/
#define DT_STRING_UNQUOTED_BY_IDX(node_id, prop, idx) \
DT_CAT4(node_id, _P_, prop##_IDX_##idx, _STRING_UNQUOTED)
/*
* phandle properties
*
@ -3302,7 +3408,7 @@
* token.
*
* @param inst instance number
* @param prop lowercase-and-underscores property string name
* @param prop lowercase-and-underscores property name
* @return the value of @p prop as a token, i.e. without any quotes
* and with special characters converted to underscores
*/
@ -3312,17 +3418,28 @@
/**
* @brief Like DT_INST_STRING_TOKEN(), but uppercased.
* @param inst instance number
* @param prop lowercase-and-underscores property string name
* @param prop lowercase-and-underscores property name
* @return the value of @p prop as an uppercased token, i.e. without
* any quotes and with special characters converted to underscores
*/
#define DT_INST_STRING_UPPER_TOKEN(inst, prop) \
DT_STRING_UPPER_TOKEN(DT_DRV_INST(inst), prop)
/**
* @brief Get a `DT_DRV_COMPAT` instance's string property's value as
* an unquoted sequence of tokens.
*
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @return the value of @p prop as a sequence of tokens, with no quotes
*/
#define DT_INST_STRING_UNQUOTED(inst, prop) \
DT_STRING_UNQUOTED(DT_DRV_INST(inst), prop)
/**
* @brief Get an element out of string-array property as a token.
* @param inst instance number
* @param prop lowercase-and-underscores property string name
* @param prop lowercase-and-underscores property name
* @param idx the index to get
* @return the element in @p prop at index @p idx as a token
*/
@ -3339,6 +3456,16 @@
#define DT_INST_STRING_UPPER_TOKEN_BY_IDX(inst, prop, idx) \
DT_STRING_UPPER_TOKEN_BY_IDX(DT_DRV_INST(inst), prop, idx)
/**
* @brief Get an element out of string-array property as an unquoted sequence of tokens.
* @param inst instance number
* @param prop lowercase-and-underscores property name
* @param idx the index to get
* @return the value of @p prop at index @p idx as a sequence of tokens, with no quotes
*/
#define DT_INST_STRING_UNQUOTED_BY_IDX(inst, prop, idx) \
DT_STRING_UNQUOTED_BY_IDX(DT_DRV_INST(inst), prop, idx)
/**
* @brief Get a `DT_DRV_COMPAT` instance's property value from a phandle's node
* @param inst instance number
@ -3607,6 +3734,17 @@
#define DT_INST_STRING_UPPER_TOKEN_OR(inst, name, default_value) \
DT_STRING_UPPER_TOKEN_OR(DT_DRV_INST(inst), name, default_value)
/**
* @brief Like DT_INST_STRING_UNQUOTED(), but with a fallback to
* @p default_value
* @param inst instance number
* @param name lowercase-and-underscores property name
* @param default_value a fallback value to expand to
* @return the property's value as a sequence of tokens, with no quotes, or @p default_value
*/
#define DT_INST_STRING_UNQUOTED_OR(inst, name, default_value) \
DT_STRING_UNQUOTED_OR(DT_DRV_INST(inst), name, default_value)
/**
* @brief Test if any `DT_DRV_COMPAT` node is on a bus of a given type
* and has status okay

View file

@ -645,6 +645,7 @@ def write_vanilla_props(node):
macro2val[macro] = val
if prop.spec.type == 'string':
macro2val[macro + "_STRING_UNQUOTED"] = prop.val
macro2val[macro + "_STRING_TOKEN"] = prop.val_as_token
macro2val[macro + "_STRING_UPPER_TOKEN"] = prop.val_as_token.upper()
@ -672,6 +673,7 @@ def write_vanilla_props(node):
if isinstance(subval, str):
macro2val[macro + f"_IDX_{i}"] = quote_str(subval)
subval_as_token = edtlib.str_as_token(subval)
macro2val[macro + f"_IDX_{i}_STRING_UNQUOTED"] = subval
macro2val[macro + f"_IDX_{i}_STRING_TOKEN"] = subval_as_token
macro2val[macro + f"_IDX_{i}_STRING_UPPER_TOKEN"] = subval_as_token.upper()
else:

View file

@ -566,5 +566,35 @@
"token_second_idx_two",
"token_second_idx_three";
};
test_str_unquoted_f0: string-unquoted-f0 {
compatible = "vnd,string-unquoted";
val = "0.1234";
};
test_str_unquoted_f1: string-unquoted-f1 {
compatible = "vnd,string-unquoted";
val = "0.9e-3";
};
test_str_unquoted_t: string-unquoted-t {
compatible = "vnd,string-unquoted";
val = "XA XPLUS XB";
};
test_stra_unquoted_f0: string-array-unquoted-f0 {
compatible = "vnd,string-array-unquoted";
val = "1.0e2", "2.0e2", "3.0e2", "4.0e2";
};
test_stra_unquoted_f1: string-array-unquoted-f1 {
compatible = "vnd,string-array-unquoted";
val = "0.01", "0.1", "1.0", "10.0";
};
test_stra_unquoted_t: string-array-unquoted-t {
compatible = "vnd,string-array-unquoted";
val = "XA XPLUS XB", "XC XPLUS XD", "XA XMINUS XB", "XC XMINUS XD";
};
};
};

View file

@ -2709,6 +2709,160 @@ ZTEST(devicetree_api, test_string_idx_token)
TOKEN_SECOND_IDX_TWO, "");
}
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT vnd_string_unquoted
ZTEST(devicetree_api, test_string_unquoted)
{
#define XA 12.0
#define XB 34.0
#define XPLUS +
const double f0_expected = 0.1234;
const double f1_expected = 0.9e-3;
const double delta = 0.1e-4;
/* Test DT_STRING_UNQUOTED */
zassert_within(DT_STRING_UNQUOTED(DT_NODELABEL(test_str_unquoted_f0), val),
f0_expected, delta, "");
zassert_within(DT_STRING_UNQUOTED(DT_NODELABEL(test_str_unquoted_f1), val),
f1_expected, delta, "");
zassert_within(DT_STRING_UNQUOTED(DT_NODELABEL(test_str_unquoted_t), val),
XA XPLUS XB, delta, "");
/* Test DT_STRING_UNQUOTED_OR */
zassert_within(DT_STRING_UNQUOTED_OR(DT_NODELABEL(test_str_unquoted_f0), val, (0.0)),
f0_expected, delta, "");
zassert_within(DT_STRING_UNQUOTED_OR(DT_NODELABEL(test_str_unquoted_f1), val, (0.0)),
f1_expected, delta, "");
zassert_within(DT_STRING_UNQUOTED_OR(DT_NODELABEL(test_str_unquoted_t), val, (0.0)),
XA XPLUS XB, delta, "");
zassert_within(DT_STRING_UNQUOTED_OR(DT_NODELABEL(test_str_unquoted_f0), nak, (0.0)),
0.0, delta, "");
zassert_within(DT_STRING_UNQUOTED_OR(DT_NODELABEL(test_str_unquoted_f1), nak, (0.0)),
0.0, delta, "");
zassert_within(DT_STRING_UNQUOTED_OR(DT_NODELABEL(test_str_unquoted_t), nak, (0.0)),
0.0, delta, "");
/* Test DT_INST_STRING_UNQUOTED */
#define STRING_UNQUOTED_VAR(node_id) _CONCAT(var_, node_id)
#define STRING_UNQUOTED_TEST_INST_EXPANSION(inst) \
double STRING_UNQUOTED_VAR(DT_DRV_INST(inst)) = DT_INST_STRING_UNQUOTED(inst, val);
DT_INST_FOREACH_STATUS_OKAY(STRING_UNQUOTED_TEST_INST_EXPANSION);
zassert_within(STRING_UNQUOTED_VAR(DT_NODELABEL(test_str_unquoted_f0)),
f0_expected, delta, "");
zassert_within(STRING_UNQUOTED_VAR(DT_NODELABEL(test_str_unquoted_f1)),
f1_expected, delta, "");
zassert_within(STRING_UNQUOTED_VAR(DT_NODELABEL(test_str_unquoted_t)), XA XPLUS XB,
delta, "");
/* Test DT_INST_STRING_UNQUOTED_OR */
#define STRING_UNQUOTED_OR_VAR(node_id) _CONCAT(var_or_, node_id)
#define STRING_UNQUOTED_OR_TEST_INST_EXPANSION(inst) \
double STRING_UNQUOTED_OR_VAR(DT_DRV_INST(inst))[2] = { \
DT_INST_STRING_UNQUOTED_OR(inst, val, (1.0e10)), \
DT_INST_STRING_UNQUOTED_OR(inst, dummy, (1.0e10)) \
};
DT_INST_FOREACH_STATUS_OKAY(STRING_UNQUOTED_OR_TEST_INST_EXPANSION);
zassert_within(STRING_UNQUOTED_OR_VAR(DT_NODELABEL(test_str_unquoted_f0))[0],
f0_expected, delta, "");
zassert_within(STRING_UNQUOTED_OR_VAR(DT_NODELABEL(test_str_unquoted_f1))[0],
f1_expected, delta, "");
zassert_within(STRING_UNQUOTED_OR_VAR(DT_NODELABEL(test_str_unquoted_t))[0],
XA XPLUS XB, delta, "");
zassert_within(STRING_UNQUOTED_OR_VAR(DT_NODELABEL(test_str_unquoted_f0))[1],
1.0e10, delta, "");
zassert_within(STRING_UNQUOTED_OR_VAR(DT_NODELABEL(test_str_unquoted_f1))[1],
1.0e10, delta, "");
zassert_within(STRING_UNQUOTED_OR_VAR(DT_NODELABEL(test_str_unquoted_t))[1],
1.0e10, delta, "");
#undef XA
#undef XB
#undef XPLUS
}
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT vnd_string_array_unquoted
ZTEST(devicetree_api, test_string_idx_unquoted)
{
#define XA 12.0
#define XB 34.0
#define XC 56.0
#define XD 78.0
#define XPLUS +
#define XMINUS -
const double delta = 0.1e-4;
/* DT_STRING_UNQUOTED_BY_IDX */
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f0), val, 0),
1.0e2, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f0), val, 1),
2.0e2, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f0), val, 2),
3.0e2, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f0), val, 3),
4.0e2, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f1), val, 0),
0.01, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f1), val, 1),
0.1, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f1), val, 2),
1.0, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_f1), val, 3),
10.0, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_t), val, 0),
XA XPLUS XB, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_t), val, 1),
XC XPLUS XD, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_t), val, 2),
XA XMINUS XB, delta, "");
zassert_within(DT_STRING_UNQUOTED_BY_IDX(DT_NODELABEL(test_stra_unquoted_t), val, 3),
XC XMINUS XD, delta, "");
#define STRING_UNQUOTED_BY_IDX_VAR(node_id) _CONCAT(var_, node_id)
#define STRING_UNQUOTED_BY_IDX_TEST_INST_EXPANSION(inst) \
double STRING_UNQUOTED_BY_IDX_VAR(DT_DRV_INST(inst))[] = { \
DT_INST_STRING_UNQUOTED_BY_IDX(inst, val, 0), \
DT_INST_STRING_UNQUOTED_BY_IDX(inst, val, 1), \
DT_INST_STRING_UNQUOTED_BY_IDX(inst, val, 2), \
DT_INST_STRING_UNQUOTED_BY_IDX(inst, val, 3), \
};
DT_INST_FOREACH_STATUS_OKAY(STRING_UNQUOTED_BY_IDX_TEST_INST_EXPANSION);
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f0))[0],
1.0e2, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f0))[1],
2.0e2, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f0))[2],
3.0e2, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f0))[3],
4.0e2, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f1))[0],
0.01, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f1))[1],
0.1, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f1))[2],
1.0, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_f1))[3],
10.0, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_t))[0],
XA XPLUS XB, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_t))[1],
XC XPLUS XD, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_t))[2],
XA XMINUS XB, delta, "");
zassert_within(STRING_UNQUOTED_BY_IDX_VAR(DT_NODELABEL(test_stra_unquoted_t))[3],
XC XMINUS XD, delta, "");
#undef XA
#undef XB
#undef XC
#undef XD
#undef XPLUS
#undef XMINUS
}
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT vnd_adc_temp_sensor
ZTEST(devicetree_api, test_reset)