Memory Attributes

It is possible in the devicetree to mark the memory regions with attributes by using the zephyr,memory-attr property. This property and the related memory region can then be retrieved at run-time by leveraging a provided helper library.

The set of general attributes that can be specified in the property are defined and explained in include/zephyr/dt-bindings/memory-attr/memory-attr.h.

For example, to mark a memory region in the devicetree as non-volatile, cacheable, out-of-order:

mem: memory@10000000 {
    compatible = "mmio-sram";
    reg = <0x10000000 0x1000>;
    zephyr,memory-attr = <( DT_MEM_NON_VOLATILE | DT_MEM_CACHEABLE | DT_MEM_OOO )>;
};

Note

The zephyr,memory-attr usage does not result in any memory region actually created. When it is needed to create an actual section out of the devicetree defined memory region, it is possible to use the compatible zephyr,memory-region that will result (only when supported by the architecture) in a new linker section and region.

The zephyr,memory-attr property can also be used to set architecture-specific and software-specific custom attributes that can be interpreted at run time. This is leveraged, among other things, to create MPU regions out of devicetree defined memory regions, for example:

mem: memory@10000000 {
    compatible = "mmio-sram";
    reg = <0x10000000 0x1000>;
    zephyr,memory-region = "NOCACHE_REGION";
    zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>;
};

See include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h and Arm Cortex-M Developer Guide for more details about MPU usage.

The conventional and recommended way to deal and manage with memory regions marked with attributes is by using the provided mem-attr helper library by enabling CONFIG_MEM_ATTR. When this option is enabled the list of memory regions and their attributes are compiled in a user-accessible array and a set of functions is made available that can be used to query, probe and act on regions and attributes (see next section for more details).

Note

The zephyr,memory-attr property is only a descriptive property of the capabilities of the associated memory region, but it does not result in any actual setting for the memory to be set. The user, code or subsystem willing to use this information to do some work (for example creating an MPU region out of the property) must use either the provided mem-attr library or the usual devicetree helpers to perform the required work / setting.

A test for the mem-attr library and its usage is provided in tests/subsys/mem_mgmt/mem_attr/.

Migration guide from zephyr,memory-region-mpu

When the zephyr,memory-attr property was introduced, the zephyr,memory-region-mpu property was removed and deprecated.

The developers that are still using the deprecated property can move to the new one by renaming the property and changing its value according to the following list:

"RAM"         -> <( DT_ARM_MPU(ATTR_MPU_RAM) )>
"RAM_NOCACHE" -> <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )>
"FLASH"       -> <( DT_ARM_MPU(ATTR_MPU_FLASH) )>
"PPB"         -> <( DT_ARM_MPU(ATTR_MPU_PPB) )>
"IO"          -> <( DT_ARM_MPU(ATTR_MPU_IO) )>
"EXTMEM"      -> <( DT_ARM_MPU(ATTR_MPU_EXTMEM) )>

API Reference

group memory_attr_interface

Memory-Attr Interface.

Defines

DT_MEMORY_ATTR_FOREACH_STATUS_OKAY_NODE(fn)

Invokes fn for every status okay node in the tree with property zephyr,memory-attr

The macro 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 with status okay. The order that nodes are visited in is not specified.

Parameters:
  • fn – macro to invoke

Functions

size_t mem_attr_get_regions(const struct mem_attr_region_t **region)

Get the list of memory regions.

Get the list of enabled memory regions with their memory-attribute as gathered by DT.

Parameters:
  • region – Pointer to pointer to the list of memory regions.

Return values:

Number – of memory regions returned in the parameter.

int mem_attr_check_buf(void *addr, size_t size, uint32_t attr)

Check if a buffer has correct size and attributes.

This function is used to check if a given buffer with a given set of attributes fully match a memory region in terms of size and attributes.

This is usually used to verify that a buffer has the expected attributes (for example the buffer is cacheable / non-cacheable or belongs to RAM / FLASH, etc…) and it has been correctly allocated.

The expected set of attributes for the buffer is and-matched against the full set of attributes for the memory region it belongs to (bitmask). So the buffer is considered matching when at least that set of attributes are valid for the memory region (but the region can be marked also with other attributes besides the one passed as parameter).

Parameters:
  • addr – Virtual address of the user buffer.

  • size – Size of the user buffer.

  • attr – Expected / desired attribute for the buffer.

Return values:
  • 0 – if the buffer has the correct size and attribute.

  • -ENOSYS – if the operation is not supported (for example if the MMU is enabled).

  • -ENOTSUP – if the wrong parameters were passed.

  • -EINVAL – if the buffer has the wrong set of attributes.

  • -ENOSPC – if the buffer is too big for the region it belongs to.

  • -ENOBUFS – if the buffer is entirely allocated outside a memory region.

struct mem_attr_region_t
#include <mem_attr.h>

memory-attr region structure.

This structure represents the data gathered from DT about a memory-region marked with memory attributes.

Public Members

const char *dt_name

Memory node full name.

uintptr_t dt_addr

Memory region physical address.

size_t dt_size

Memory region size.

uint32_t dt_attr

Memory region attributes.