1.. _mem_mgmt_api:
2
3Memory Attributes
4#################
5
6It is possible in the devicetree to mark the memory regions with attributes by
7using the ``zephyr,memory-attr`` property. This property and the related memory
8region can then be retrieved at run-time by leveraging a provided helper
9library.
10
11The set of general attributes that can be specified in the property are defined
12and explained in :zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr.h`.
13
14For example, to mark a memory region in the devicetree as non-volatile, cacheable,
15out-of-order:
16
17.. code-block:: devicetree
18
19   mem: memory@10000000 {
20       compatible = "mmio-sram";
21       reg = <0x10000000 0x1000>;
22       zephyr,memory-attr = <( DT_MEM_NON_VOLATILE | DT_MEM_CACHEABLE | DT_MEM_OOO )>;
23   };
24
25.. note::
26
27   The ``zephyr,memory-attr`` usage does not result in any memory region
28   actually created. When it is needed to create an actual section out of the
29   devicetree defined memory region, it is possible to use the compatible
30   :dtcompatible:`zephyr,memory-region` that will result (only when supported
31   by the architecture) in a new linker section and region.
32
33The ``zephyr,memory-attr`` property can also be used to set
34architecture-specific and software-specific custom attributes that can be
35interpreted at run time. This is leveraged, among other things, to create MPU
36regions out of devicetree defined memory regions, for example:
37
38.. code-block:: devicetree
39
40   mem: memory@10000000 {
41       compatible = "mmio-sram";
42       reg = <0x10000000 0x1000>;
43       zephyr,memory-region = "NOCACHE_REGION";
44       zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>;
45   };
46
47See :zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h` and
48:ref:`arm_cortex_m_mpu_considerations` in the :ref:`arm_cortex_m_developer_guide`
49for more details about MPU usage. Also see :ref:`cache_guide` for details on how
50Zephyr handles caching.
51
52The conventional and recommended way to deal and manage with memory regions
53marked with attributes is by using the provided ``mem-attr`` helper library by
54enabling :kconfig:option:`CONFIG_MEM_ATTR`. When this option is enabled the
55list of memory regions and their attributes are compiled in a user-accessible
56array and a set of functions is made available that can be used to query, probe
57and act on regions and attributes (see next section for more details).
58
59.. note::
60
61   The ``zephyr,memory-attr`` property is only a descriptive property of the
62   capabilities of the associated memory region, but it does not result in any
63   actual setting for the memory to be set. The user, code or subsystem willing
64   to use this information to do some work (for example creating an MPU region
65   out of the property) must use either the provided ``mem-attr`` library or
66   the usual devicetree helpers to perform the required work / setting. Note,
67   however, that for some architectures (such as ARM and ARM64) the MPU driver
68   uses this information to properly initialize caching at boot. See
69   :kconfig:option:`CONFIG_ARM_MPU`, :kconfig:option:`CONFIG_RISCV_PMP`, etc.
70
71A test for the ``mem-attr`` library and its usage is provided in
72``tests/subsys/mem_mgmt/mem_attr/``.
73
74Migration guide from ``zephyr,memory-region-mpu``
75*************************************************
76
77When the ``zephyr,memory-attr`` property was introduced, the
78``zephyr,memory-region-mpu`` property was removed and deprecated.
79
80The developers that are still using the deprecated property can move to the new
81one by renaming the property and changing its value according to the following list:
82
83.. code-block:: none
84
85   "RAM"         -> <( DT_ARM_MPU(ATTR_MPU_RAM) )>
86   "RAM_NOCACHE" -> <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )>
87   "FLASH"       -> <( DT_ARM_MPU(ATTR_MPU_FLASH) )>
88   "PPB"         -> <( DT_ARM_MPU(ATTR_MPU_PPB) )>
89   "IO"          -> <( DT_ARM_MPU(ATTR_MPU_IO) )>
90   "EXTMEM"      -> <( DT_ARM_MPU(ATTR_MPU_EXTMEM) )>
91
92Memory Attributes Heap Allocator
93********************************
94
95It is possible to leverage the memory attribute property ``zephyr,memory-attr``
96to define and create a set of memory heaps from which the user can allocate
97memory from with certain attributes / capabilities.
98
99When the :kconfig:option:`CONFIG_MEM_ATTR_HEAP` is set, every region marked
100with one of the memory attributes listed in
101:zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr-sw.h` is added
102to a pool of memory heaps used for dynamic allocation of memory buffers with
103certain attributes.
104
105Here a non exhaustive list of possible attributes:
106
107.. code-block:: none
108
109   DT_MEM_SW_ALLOC_CACHE
110   DT_MEM_SW_ALLOC_NON_CACHE
111   DT_MEM_SW_ALLOC_DMA
112
113For example we can define several memory regions with different attributes and
114use the appropriate attribute to indicate that it is possible to dynamically
115allocate memory from those regions:
116
117.. code-block:: devicetree
118
119   mem_cacheable: memory@10000000 {
120       compatible = "mmio-sram";
121       reg = <0x10000000 0x1000>;
122       zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_SW_ALLOC_CACHE )>;
123   };
124
125   mem_non_cacheable: memory@20000000 {
126       compatible = "mmio-sram";
127       reg = <0x20000000 0x1000>;
128       zephyr,memory-attr = <( DT_MEM_NON_CACHEABLE | ATTR_SW_ALLOC_NON_CACHE )>;
129   };
130
131   mem_cacheable_big: memory@30000000 {
132       compatible = "mmio-sram";
133       reg = <0x30000000 0x10000>;
134       zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_OOO | DT_MEM_SW_ALLOC_CACHE )>;
135   };
136
137   mem_cacheable_dma: memory@40000000 {
138       compatible = "mmio-sram";
139       reg = <0x40000000 0x10000>;
140       zephyr,memory-attr = <( DT_MEM_CACHEABLE      | DT_MEM_DMA |
141                               DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA )>;
142   };
143
144The user can then dynamically carve memory out of those regions using the
145provided functions, the library will take care of allocating memory from the
146correct heap depending on the provided attribute and size:
147
148.. code-block:: c
149
150   // Init the pool
151   mem_attr_heap_pool_init();
152
153   // Allocate 0x100 bytes of cacheable memory from `mem_cacheable`
154   block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100);
155
156   // Allocate 0x200 bytes of non-cacheable memory aligned to 32 bytes
157   // from `mem_non_cacheable`
158   block = mem_attr_heap_aligned_alloc(ATTR_SW_ALLOC_NON_CACHE, 0x100, 32);
159
160   // Allocate 0x100 bytes of cacheable and dma-able memory from `mem_cacheable_dma`
161   block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA, 0x100);
162
163When several regions are marked with the same attributes, the memory is allocated:
164
1651. From the regions where the ``zephyr,memory-attr`` property has the requested
166   property (or properties).
167
1682. Among the regions as at point 1, from the smallest region if there is any
169   unallocated space left for the requested size
170
1713. If there is not enough space, from the next bigger region able to
172   accommodate the requested size
173
174The following example shows the point 3:
175
176.. code-block:: c
177
178   // This memory is allocated from `mem_non_cacheable`
179   block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_NON_CACHE, 0x100);
180
181   // This memory is allocated from `mem_cacheable_big`
182   block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x5000);
183
184.. note::
185
186    The framework is assuming that the memory regions used to create the heaps
187    are usable by the code and available at init time. The user must take of
188    initializing and setting the memory area before calling
189    :c:func:`mem_attr_heap_pool_init`.
190
191    That means that the region must be correctly configured in terms of MPU /
192    MMU (if needed) and that an actual heap can be created out of it, for
193    example by leveraging the ``zephyr,memory-region`` property to create a
194    proper linker section to accommodate the heap.
195
196API Reference
197*************
198
199.. doxygengroup:: memory_attr_interface
200.. doxygengroup:: memory_attr_heap
201