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