diff --git a/doc/releases/release-notes-2.7.rst b/doc/releases/release-notes-2.7.rst index 302cadd062405..815226bae744a 100644 --- a/doc/releases/release-notes-2.7.rst +++ b/doc/releases/release-notes-2.7.rst @@ -27,6 +27,12 @@ interface and listing all issues with the `bug label API Changes *********** +Deprecated in this release + +* :c:macro:`DT_ENUM_TOKEN` and :c:macro:`DT_ENUM_UPPER_TOKEN`, + were deprecated in favor of utilizing + :c:macro:`DT_STRING_TOKEN` and :c:macro:`DT_STRING_UPPER_TOKEN` + Changes in this release ========================== diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index f1be80ad86103..3875d84ed62e0 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -46,7 +46,7 @@ BUILD_ASSERT(INST_0_SCK_FREQUENCY >= (NRF_QSPI_BASE_CLOCK_FREQ / 16), #define QSPI_PROP_LEN(prop) DT_PROP_LEN(QSPI_NODE, prop) #define INST_0_QER _CONCAT(JESD216_DW15_QER_, \ - DT_ENUM_TOKEN(DT_DRV_INST(0), \ + DT_STRING_TOKEN(DT_DRV_INST(0), \ quad_enable_requirements)) BUILD_ASSERT(((INST_0_QER == JESD216_DW15_QER_NONE) diff --git a/dts/bindings/reserved-memory/reserved-memory.yaml b/dts/bindings/reserved-memory/reserved-memory.yaml new file mode 100644 index 0000000000000..5b2d26aa0f39e --- /dev/null +++ b/dts/bindings/reserved-memory/reserved-memory.yaml @@ -0,0 +1,23 @@ +description: | + Reserved memory - Each child of the reserved-memory node specifies one or + more regions of reserved memory. Regions in the /reserved-memory node may be + referenced by other device nodes by adding a memory-region property to the + device node. + +compatible: "reserved-memory" + +include: + - name: base.yaml + property-allowlist: ['#address-cells', '#size-cells'] + +child-binding: + description: Regions + properties: + label: + type: string + required: false + description: Human readable string describing the device (used as device_get_binding() argument) + reg: + type: array + description: register space + required: true diff --git a/include/devicetree.h b/include/devicetree.h index c0ab455e29434..679d2158ba049 100644 --- a/include/devicetree.h +++ b/include/devicetree.h @@ -41,8 +41,9 @@ * * _ENUM_IDX: property's value as an index into bindings enum * _ENUM_TOKEN: property's value as a token into bindings enum (string - * enum values are identifiers) - * _ENUM_UPPER_TOKEN: like _ENUM_TOKEN, but uppercased + * enum values are identifiers) [deprecated, use _STRING_TOKEN] + * _ENUM_UPPER_TOKEN: like _ENUM_TOKEN, but uppercased [deprecated, use + * _STRING_UPPER_TOKEN] * _EXISTS: property is defined * _FOREACH_PROP_ELEM: helper for "iterating" over values in the property * _IDX_: logical index into property @@ -54,6 +55,8 @@ * _NAME__PH: phandle array's phandle by name * _NAME__VAL_: phandle array's property specifier by name * _NAME__VAL__EXISTS: cell value exists, by name + * _STRING_TOKEN: string property's value as a token + * _STRING_UPPER_TOKEN: like _STRING_TOKEN, but uppercased */ /** @@ -701,6 +704,113 @@ COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \ (DT_ENUM_IDX(node_id, prop)), (default_idx_value)) +/** + * @brief Get a string property's value as a token. + * + * This removes "the quotes" from string-valued properties, and converts + * non-alphanumeric characters to underscores. That can be useful, for example, + * when programmatically using the value to form a C variable or code. + * + * DT_STRING_TOKEN() can only be used for properties with string type. + * + * It is an error to use DT_STRING_TOKEN() in other circumstances. + * + * Example devicetree fragment: + * + * n1: node-1 { + * prop = "foo"; + * }; + * n2: node-2 { + * prop = "FOO"; + * } + * n3: node-3 { + * prop = "123 foo"; + * }; + * + * Example bindings fragment: + * + * properties: + * prop: + * type: string + * + * Example usage: + * + * DT_STRING_TOKEN(DT_NODELABEL(n1), prop) // foo + * DT_STRING_TOKEN(DT_NODELABEL(n2), prop) // FOO + * DT_STRING_TOKEN(DT_NODELABEL(n3), prop) // 123_foo + * + * Notice how: + * + * - Unlike C identifiers, the property values may begin with a + * number. It's the user's responsibility not to use such values as + * the name of a C identifier. + * + * - The uppercased "FOO" in the DTS remains @p FOO as a token. It is + * *not* converted to @p foo. + * + * - The whitespace in the DTS "123 foo" string is converted to @p + * 123_foo as a token. + * + * @param node_id node identifier + * @param prop lowercase-and-underscores property string name + * @return the value of @p prop as a token, i.e. without any quotes + * and with special characters converted to underscores + */ +#define DT_STRING_TOKEN(node_id, prop) \ + DT_CAT4(node_id, _P_, prop, _STRING_TOKEN) + +/** + * @brief Like DT_STRING_TOKEN(), but uppercased. + * + * This removes "the quotes and capitalize" from string-valued properties, and + * converts non-alphanumeric characters to underscores. That can be useful, for + * example, when programmatically using the value to form a C variable or code. + * + * DT_STRING_UPPER_TOKEN() can only be used for properties with string type. + * + * It is an error to use DT_STRING_UPPER_TOKEN() in other circumstances. + * + * Example devicetree fragment: + * + * n1: node-1 { + * prop = "foo"; + * }; + * n2: node-2 { + * prop = "123 foo"; + * }; + * + * Example bindings fragment: + * + * properties: + * prop: + * type: string + * + * Example usage: + * + * DT_STRING_UPPER_TOKEN(DT_NODELABEL(n1), prop) // FOO + * DT_STRING_UPPER_TOKEN(DT_NODELABEL(n2), prop) // 123_FOO + * + * Notice how: + * + * - Unlike C identifiers, the property values may begin with a + * number. It's the user's responsibility not to use such values as + * the name of a C identifier. + * + * - The lowercased "foo" in the DTS becomes @p FOO as a token, i.e. + * it is uppercased. + * + * - The whitespace in the DTS "123 foo" string is converted to @p + * 123_FOO as a token, i.e. it is uppercased and whitespace becomes + * an underscore. + * + * @param node_id node identifier + * @param prop lowercase-and-underscores property string name + * @return the value of @p prop as a token, i.e. without any quotes + * and with special characters converted to underscores + */ +#define DT_STRING_UPPER_TOKEN(node_id, prop) \ + DT_CAT4(node_id, _P_, prop, _STRING_UPPER_TOKEN) + /** * @brief Get an enumeration property's value as a token. * @@ -763,6 +873,7 @@ * and with special characters converted to underscores */ #define DT_ENUM_TOKEN(node_id, prop) \ + __DEPRECATED_MACRO \ DT_CAT4(node_id, _P_, prop, _ENUM_TOKEN) /** @@ -822,6 +933,7 @@ * underscores */ #define DT_ENUM_UPPER_TOKEN(node_id, prop) \ + __DEPRECATED_MACRO \ DT_CAT4(node_id, _P_, prop, _ENUM_UPPER_TOKEN) /* diff --git a/include/devicetree/memory.h b/include/devicetree/memory.h new file mode 100644 index 0000000000000..a6c173e652e20 --- /dev/null +++ b/include/devicetree/memory.h @@ -0,0 +1,139 @@ +/** + * @file + * @brief reserved-memory Devicetree macro public API header file. + */ + +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DEVICETREE_MEMORY_H_ +#define ZEPHYR_INCLUDE_DEVICETREE_MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup devicetree-reserved Devicetree reserved-memory API + * @ingroup devicetree + * @{ + */ + +/** + * @brief Get the pointer to the reserved-memory region + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * n: node { + * reg = <0x42000000 0x1000>; + * }; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_PTR(DT_NODELABEL(n)) // (uint8_t *) 0x42000000 + * + * @param node_id node identifier + * @return pointer to the beginning of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_PTR(node_id) _DT_RESERVED_START(node_id) + +/** + * @brief Get the size of the reserved-memory region + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * n: node { + * reg = <0x42000000 0x1000>; + * }; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_SIZE(DT_NODELABEL(n)) // 0x1000 + * + * @param node_id node identifier + * @return the size of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_SIZE(node_id) DT_REG_SIZE(node_id) + +/** + * @brief Get the pointer to the reserved-memory region from a memory-reserved + * phandle + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * res0: res { + * reg = <0x42000000 0x1000>; + * label = "res0"; + * }; + * }; + * + * n: node { + * memory-region = <&res0>; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_PTR_BY_PHANDLE(DT_NODELABEL(n), memory_region) // (uint8_t *) 0x42000000 + * + * @param node_id node identifier + * @param ph phandle to reserved-memory region + * + * @return pointer to the beginning of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_PTR_BY_PHANDLE(node_id, ph) \ + DT_RESERVED_MEM_GET_PTR(DT_PHANDLE(node_id, ph)) + +/** + * @brief Get the size of the reserved-memory region from a memory-reserved + * phandle + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * res0: res { + * reg = <0x42000000 0x1000>; + * label = "res0"; + * }; + * }; + * + * n: node { + * memory-region = <&res0>; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_SIZE_BY_PHANDLE(DT_NODELABEL(n), memory_region) // (uint8_t *) 0x42000000 + * + * @param node_id node identifier + * @param ph phandle to reserved-memory region + * + * @return size of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_SIZE_BY_PHANDLE(node_id, ph) \ + DT_RESERVED_MEM_GET_SIZE(DT_PHANDLE(node_id, ph)) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEVICETREE_MEMORY_H_ */ diff --git a/include/linker/devicetree_reserved.h b/include/linker/devicetree_reserved.h new file mode 100644 index 0000000000000..92797602be283 --- /dev/null +++ b/include/linker/devicetree_reserved.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + * + * Generate memory regions and sections from reserved-memory nodes. + */ + +#include + +/* Reserved memory node */ +#define _NODE_RESERVED DT_INST(0, reserved_memory) + +/* Unquoted region label */ +#define _DT_LABEL_TOKEN(res) DT_STRING_TOKEN(res, label) + +/* _start and _end section symbols */ +#define _DT_RESERVED_PREFIX(res) UTIL_CAT(__, _DT_LABEL_TOKEN(res)) +#define _DT_RESERVED_START(res) UTIL_CAT(_DT_RESERVED_PREFIX(res), _start) +#define _DT_RESERVED_END(res) UTIL_CAT(_DT_RESERVED_PREFIX(res), _end) + +/* Declare a reserved memory region */ +#define _RESERVED_REGION_DECLARE(res) DT_STRING_TOKEN(res, label) (rw) : \ + ORIGIN = DT_REG_ADDR(res), \ + LENGTH = DT_REG_SIZE(res) + +/* Declare a reserved memory section */ +#define _RESERVED_SECTION_DECLARE(res) SECTION_DATA_PROLOGUE(_DT_LABEL_TOKEN(res), ,) \ + { \ + _DT_RESERVED_START(res) = .; \ + KEEP(*(._DT_LABEL_TOKEN(res))) \ + KEEP(*(._DT_LABEL_TOKEN(res).*)) \ + _DT_RESERVED_END(res) = \ + _DT_RESERVED_START(res) + DT_REG_SIZE(res); \ + } GROUP_LINK_IN(_DT_LABEL_TOKEN(res)) + +/* Declare reserved memory linker symbols */ +#define _RESERVED_SYMBOL_DECLARE(res) extern char _DT_RESERVED_START(res)[]; \ + extern char _DT_RESERVED_END(res)[]; + +/* Apply a macro to a reserved memory region */ +#define _RESERVED_REGION_APPLY(f) \ + COND_CODE_1(IS_ENABLED(UTIL_CAT(_NODE_RESERVED, _EXISTS)), \ + (DT_FOREACH_CHILD(_NODE_RESERVED, f)), ()) + +/** + * @brief Generate region definitions for all the reserved memory regions + */ +#define DT_RESERVED_MEM_REGIONS() _RESERVED_REGION_APPLY(_RESERVED_REGION_DECLARE) + +/** + * @brief Generate section definitions for all the reserved memory regions + */ +#define DT_RESERVED_MEM_SECTIONS() _RESERVED_REGION_APPLY(_RESERVED_SECTION_DECLARE) + +/** + * @brief Generate linker script symbols for all the reserved memory regions + */ +#define DT_RESERVED_MEM_SYMBOLS() _RESERVED_REGION_APPLY(_RESERVED_SYMBOL_DECLARE) diff --git a/include/linker/linker-defs.h b/include/linker/linker-defs.h index 3ae8f27c5df06..4d2dee50d5f75 100644 --- a/include/linker/linker-defs.h +++ b/include/linker/linker-defs.h @@ -33,6 +33,7 @@ #ifdef ZTEST_UNITTEST #define DT_NODE_HAS_STATUS(node, status) 0 #else +#include #include #endif @@ -213,6 +214,10 @@ extern char _image_rodata_size[]; extern char _vector_start[]; extern char _vector_end[]; +#if DT_NODE_HAS_STATUS(_NODE_RESERVED, okay) +DT_RESERVED_MEM_SYMBOLS() +#endif + #ifdef CONFIG_SW_VECTOR_RELAY extern char __vector_relay_table[]; #endif diff --git a/samples/boards/qemu_cortex_a53/reserved_memory/CMakeLists.txt b/samples/boards/qemu_cortex_a53/reserved_memory/CMakeLists.txt new file mode 100644 index 0000000000000..5ab2764a3426d --- /dev/null +++ b/samples/boards/qemu_cortex_a53/reserved_memory/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(reserved_memory) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/qemu_cortex_a53/reserved_memory/boards/qemu_cortex_a53.overlay b/samples/boards/qemu_cortex_a53/reserved_memory/boards/qemu_cortex_a53.overlay new file mode 100644 index 0000000000000..feea737b51ae5 --- /dev/null +++ b/samples/boards/qemu_cortex_a53/reserved_memory/boards/qemu_cortex_a53.overlay @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + reserved-memory { + compatible = "reserved-memory"; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + ranges; + + res0: res0@42000000 { + reg = <0x42000000 0x1000>; + label = "res0"; + }; + + res1: res1@43000000 { + reg = <0x43000000 0x2000>; + compatible = "sample_driver"; + label = "res1"; + }; + }; + + + sample_driver_outer: sample_driver { + compatible = "sample_driver"; + label = "sample_driver_outer"; + memory-region = <&res0>; + }; +}; diff --git a/samples/boards/qemu_cortex_a53/reserved_memory/dts/bindings/sample_driver.yaml b/samples/boards/qemu_cortex_a53/reserved_memory/dts/bindings/sample_driver.yaml new file mode 100644 index 0000000000000..6784fcdefe2c4 --- /dev/null +++ b/samples/boards/qemu_cortex_a53/reserved_memory/dts/bindings/sample_driver.yaml @@ -0,0 +1,13 @@ +description: Sample Driver + +compatible: "sample_driver" + +include: + - name: base.yaml + property-allowlist: ['reg', 'label'] + +properties: + memory-region: + type: phandle + required: false + description: phandle to the reserved memory child node diff --git a/samples/boards/qemu_cortex_a53/reserved_memory/linker_arm64_reserved.ld b/samples/boards/qemu_cortex_a53/reserved_memory/linker_arm64_reserved.ld new file mode 100644 index 0000000000000..89929d7c0e177 --- /dev/null +++ b/samples/boards/qemu_cortex_a53/reserved_memory/linker_arm64_reserved.ld @@ -0,0 +1,24 @@ +/* + * Copyright (c) Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +MEMORY +{ + DT_RESERVED_MEM_REGIONS() +} + +SECTIONS +{ + DT_RESERVED_MEM_SECTIONS() +} + +#include diff --git a/samples/boards/qemu_cortex_a53/reserved_memory/prj.conf b/samples/boards/qemu_cortex_a53/reserved_memory/prj.conf new file mode 100644 index 0000000000000..233e67102b7e2 --- /dev/null +++ b/samples/boards/qemu_cortex_a53/reserved_memory/prj.conf @@ -0,0 +1,2 @@ +CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y +CONFIG_CUSTOM_LINKER_SCRIPT="linker_arm64_reserved.ld" diff --git a/samples/boards/qemu_cortex_a53/reserved_memory/sample.yaml b/samples/boards/qemu_cortex_a53/reserved_memory/sample.yaml new file mode 100644 index 0000000000000..bcda9530c083a --- /dev/null +++ b/samples/boards/qemu_cortex_a53/reserved_memory/sample.yaml @@ -0,0 +1,8 @@ +sample: + description: Reserved memory sample application + name: reserved memory +tests: + sample.board.qemu_cortex_a53.reserved_memory: + platform_allow: qemu_cortex_a53 + tags: sample board reserved_memory + build_only: true diff --git a/samples/boards/qemu_cortex_a53/reserved_memory/src/main.c b/samples/boards/qemu_cortex_a53/reserved_memory/src/main.c new file mode 100644 index 0000000000000..5370b3964a5b7 --- /dev/null +++ b/samples/boards/qemu_cortex_a53/reserved_memory/src/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* Variables placed in reserved sections */ +uint32_t var_in_res0 __attribute((__section__(".res0"))) = 0xaabbccdd; +uint32_t var_in_res1 __attribute((__section__(".res1"))) = 0xddccbbaa; + +void main(void) +{ + uint8_t *res_ptr_outer, *res_ptr_inner; + uint32_t res_size_outer, res_size_inner; + + res_ptr_outer = + DT_RESERVED_MEM_GET_PTR_BY_PHANDLE(DT_NODELABEL(sample_driver_outer), + memory_region); + res_size_outer = + DT_RESERVED_MEM_GET_SIZE_BY_PHANDLE(DT_NODELABEL(sample_driver_outer), + memory_region); + + printk("Reserved memory address for the outer driver: %p\n", res_ptr_outer); + printk("Reserved memory size for the outer driver: %d\n", res_size_outer); + + res_ptr_inner = DT_RESERVED_MEM_GET_PTR(DT_NODELABEL(res1)); + res_size_inner = DT_RESERVED_MEM_GET_SIZE(DT_NODELABEL(res1)); + + printk("Reserved memory address for the inner driver: %p\n", res_ptr_inner); + printk("Reserved memory size for the inner driver: %d\n", res_size_inner); + + printk("Address of var_in_res0: %p\n", &var_in_res0); + printk("Address of var_in_res1: %p\n", &var_in_res1); +} diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index 5ce841718ee8a..2e0c9ab36d599 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -516,6 +516,10 @@ def write_vanilla_props(node): # DT_N__P_ macro2val[macro] = val + if prop.spec.type == 'string': + macro2val[macro + "_STRING_TOKEN"] = prop.val_as_token + macro2val[macro + "_STRING_UPPER_TOKEN"] = prop.val_as_token.upper() + if prop.enum_index is not None: # DT_N__P__ENUM_IDX macro2val[macro + "_ENUM_IDX"] = prop.enum_index diff --git a/soc/arm/nuvoton_npcx/common/soc_dt.h b/soc/arm/nuvoton_npcx/common/soc_dt.h index 16b1656ef43de..72592e2d10987 100644 --- a/soc/arm/nuvoton_npcx/common/soc_dt.h +++ b/soc/arm/nuvoton_npcx/common/soc_dt.h @@ -23,7 +23,7 @@ */ #define NPCX_DT_PROP_ENUM_OR(node_id, prop, default_value) \ COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \ - (DT_ENUM_UPPER_TOKEN(node_id, prop)), (default_value)) + (DT_STRING_UPPER_TOKEN(node_id, prop)), (default_value)) /** * @brief Like DT_INST_PROP_OR(), but expand parameters with diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 81bc27d9bf00d..a99696e677de4 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -28,6 +28,8 @@ * - DT_INST_IO_CHANNELS_LABEL * - DT_INST_DMAS_LABEL_BY_IDX * - DT_INST_DMAS_LABEL_BY_NAME + * - DT_ENUM_TOKEN + * - DT_ENUM_UPPER_TOKEN */ #define __DEPRECATED_MACRO