Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/build/dts/api/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,15 @@ and properties related to them.

.. doxygengroup:: devicetree-mbox

.. _devicetree-memory-attr-api:

Memory attributes
=================

These conveniences may be used for nodes with a memory attribute property.

.. doxygengroup:: devicetree-memory-attr

.. _devicetree-pinctrl-api:

Pinctrl (pin control)
Expand Down
20 changes: 20 additions & 0 deletions dts/bindings/base/zephyr,memory-attr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright (c) 2023, Carlo Caione <[email protected]>
# SPDX-License-Identifier: Apache-2.0

include: [base.yaml]

properties:
zephyr,memory-attr:
type: string
enum:
- "RAM"
- "RAM_NOCACHE"
- "FLASH"
- "PPB"
- "IO"
- "EXTMEM"
description: |
Attribute for the memory region.

reg:
required: true
8 changes: 8 additions & 0 deletions dts/bindings/test/vnd,memory-attr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2020 Linaro Ltd.
# SPDX-License-Identifier: Apache-2.0

description: Test memory and memory attributes

compatible: "vnd,memory-attr"

include: [base.yaml, "zephyr,memory-attr.yaml"]
1 change: 1 addition & 0 deletions include/zephyr/devicetree.h
Original file line number Diff line number Diff line change
Expand Up @@ -4286,5 +4286,6 @@
#include <zephyr/devicetree/can.h>
#include <zephyr/devicetree/reset.h>
#include <zephyr/devicetree/mbox.h>
#include <zephyr/devicetree/memory-attr.h>

#endif /* DEVICETREE_H */
163 changes: 163 additions & 0 deletions include/zephyr/devicetree/memory-attr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Copyright (c) 2023 Carlo Caione <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_MEMORY_ATTR_H_
#define ZEPHYR_INCLUDE_MEMORY_ATTR_H_

#include <zephyr/devicetree.h>
#include <zephyr/linker/devicetree_regions.h>
#include <zephyr/sys/util.h>

/**
* @file
* @brief Memory-attr helpers
*/

/**
* @defgroup devicetree-memory-attr Memory attributes
* @ingroup devicetree
* @{
*/

/** @cond INTERNAL_HIDDEN */

#define _DT_MEM_ATTR zephyr_memory_attr
#define _DT_ATTR(token) UTIL_CAT(UTIL_CAT(REGION_, token), _ATTR)

#define _UNPACK(node_id, fn) \
fn(COND_CODE_1(DT_NODE_HAS_PROP(node_id, zephyr_memory_region), \
(LINKER_DT_NODE_REGION_NAME(node_id)), \
(DT_NODE_FULL_NAME(node_id))), \
DT_REG_ADDR(node_id), \
DT_REG_SIZE(node_id), \
_DT_ATTR(DT_STRING_TOKEN(node_id, _DT_MEM_ATTR))),

#define _APPLY(node_id, fn) \
COND_CODE_1(DT_NODE_HAS_PROP(node_id, _DT_MEM_ATTR), \
(_UNPACK(node_id, fn)), \
())


#define _FILTER(node_id, fn) \
COND_CODE_1(DT_NODE_HAS_PROP(node_id, _DT_MEM_ATTR), \
(fn(node_id)), \
())

/** @endcond */

/**
* @brief Invokes @p fn for every node in the tree with property
* `zephyr,memory-attr`
*
* The macro @p fn must take one parameter, which will be a node identifier
* with the `zephyr,memory-attr` property. The macro is expanded once for each
* node in the tree. The order that nodes are visited in is not specified.
*
* @param fn macro to invoke
*/
#define DT_MEMORY_ATTR_FOREACH_NODE(fn) \
DT_FOREACH_STATUS_OKAY_NODE_VARGS(_FILTER, fn)

/**
* @brief Invokes @p fn for MPU/MMU regions generation from the device tree
* nodes with `zephyr,memory-attr` property.
*
* Helper macro to invoke a @p fn macro on all the memory regions declared
* using the `zephyr,memory-attr` property
*
* The macro @p fn must take the form:
*
* @code{.c}
* #define MPU_FN(name, base, size, attr) ...
* @endcode
*
* The @p name, @p base and @p size parameters are retrieved from the DT node.
* When the `zephyr,memory-region` property is present in the node, the @p name
* parameter is retrived from there, otherwise the full node name is used.
*
* The `zephyr,memory-attr` enum property is passed as an extended token
* to the @p fn macro using the @p attr parameter in the form of a macro
* REGION_{attr}_ATTR.
*
* The following enums are supported for the `zephyr,memory-attr` property (see
* `zephyr,memory-attr.yaml` for a complete list):
*
* - RAM
* - RAM_NOCACHE
* - FLASH
* - PPB
* - IO
* - EXTMEM
*
* This means that usually the user code would provide some macros or defines
* with the same name of the extended property, that is:
*
* - REGION_RAM_ATTR
* - REGION_RAM_NOCACHE_ATTR
* - REGION_FLASH_ATTR
* - REGION_PPB_ATTR
* - REGION_IO_ATTR
* - REGION_EXTMEM_ATTR
*
* Example devicetree fragment:
*
* @code{.dts}
* / {
* soc {
* res0: memory@20000000 {
* reg = <0x20000000 0x4000>;
* zephyr,memory-region = "MY_NAME";
* zephyr,memory-attr = "RAM_NOCACHE";
* };
*
* res1: memory@30000000 {
* reg = <0x30000000 0x2000>;
* zephyr,memory-attr = "RAM";
* };

* };
* };
* @endcode
*
* Example usage:
*
* @code{.c}
* #define REGION_RAM_NOCACHE_ATTR 0xAAAA
* #define REGION_RAM_ATTR 0xBBBB
* #define REGION_FLASH_ATTR 0xCCCC
*
* #define MPU_FN(p_name, p_base, p_size, p_attr) \
* { \
* .name = p_name, \
* .base = p_base, \
* .size = p_size, \
* .attr = p_attr, \
* }
*
* static const struct arm_mpu_region mpu_regions[] = {
* DT_MEMORY_ATTR_APPLY(MPU_FN)
* };
* @endcode
*
* This expands to:
*
* @code{.c}
* static const struct arm_mpu_region mpu_regions[] = {
* { "MY_NAME", 0x20000000, 0x4000, 0xAAAA },
* { "memory@30000000", 0x30000000, 0x2000, 0xBBBB },
* };
* @endcode
*
* @param fn macro to invoke
*/
#define DT_MEMORY_ATTR_APPLY(fn) \
DT_FOREACH_STATUS_OKAY_NODE_VARGS(_APPLY, fn)

/**
* @}
*/

#endif /* ZEPHYR_INCLUDE_MEMORY_ATTR_H_ */
13 changes: 13 additions & 0 deletions tests/lib/devicetree/api/app.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,19 @@
compatible = "vnd,string-array-unquoted";
val = "XA XPLUS XB", "XC XPLUS XD", "XA XMINUS XB", "XC XMINUS XD";
};

test_mem_ram: memory@aabbccdd {
compatible = "vnd,memory-attr";
reg = < 0xaabbccdd 0x4000 >;
zephyr,memory-attr = "RAM";
};

test_mem_ram_nocache: memory@44332211 {
compatible = "vnd,memory-attr";
reg = < 0x44332211 0x2000 >;
zephyr,memory-attr = "RAM_NOCACHE";
};

};

test_64 {
Expand Down
64 changes: 64 additions & 0 deletions tests/lib/devicetree/api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2667,6 +2667,70 @@ ZTEST(devicetree_api, test_mbox)
DT_NODELABEL(test_mbox_zero_cell)), "");
}

ZTEST(devicetree_api, test_memory_attr)
{
#define REGION_RAM_ATTR (0xDEDE)
#define REGION_RAM_NOCACHE_ATTR (0xCACA)

#define TEST_FUNC(p_name, p_base, p_size, p_attr) \
{ .name = (p_name), \
.base = (p_base), \
.size = (p_size), \
.attr = (p_attr), \
}

struct vnd_memory_binding {
char *name;
uintptr_t base;
size_t size;
unsigned int attr;
};

struct vnd_memory_binding val_apply[] = {
DT_MEMORY_ATTR_APPLY(TEST_FUNC)
};

zassert_true(!strcmp(val_apply[0].name, "memory@aabbccdd"), "");
zassert_equal(val_apply[0].base, 0xaabbccdd, "");
zassert_equal(val_apply[0].size, 0x4000, "");
zassert_equal(val_apply[0].attr, 0xDEDE, "");

zassert_true(!strcmp(val_apply[1].name, "memory@44332211"), "");
zassert_equal(val_apply[1].base, 0x44332211, "");
zassert_equal(val_apply[1].size, 0x2000, "");
zassert_equal(val_apply[1].attr, 0xCACA, "");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this 0xCACA be REGION_RAM_NOCACHE_ATTR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, maybe for readability but after all this is a test, so it doesn't really matter?


#undef TEST_FUNC
#undef REGION_RAM_ATTR
#undef REGION_RAM_NOCACHE_ATTR

#define TEST_FUNC(node_id) DT_NODE_FULL_NAME(node_id),

static const char * const val_func[] = {
DT_MEMORY_ATTR_FOREACH_NODE(TEST_FUNC)
};

zassert_true(!strcmp(val_func[0], "memory@aabbccdd"), "");
zassert_true(!strcmp(val_func[1], "memory@44332211"), "");

#undef TEST_FUNC

#define TEST_FUNC(node_id) \
COND_CODE_1(DT_ENUM_HAS_VALUE(node_id, \
zephyr_memory_attr, \
RAM_NOCACHE), \
(DT_REG_ADDR(node_id)), \
())

uintptr_t val_filt[] = {
DT_MEMORY_ATTR_FOREACH_NODE(TEST_FUNC)
};

zassert_equal(val_filt[0], 0x44332211, "");

#undef TEST_FUNC
}

ZTEST(devicetree_api, test_string_token)
{
#undef DT_DRV_COMPAT
Expand Down