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_developer_guide` for more details about MPU usage. 49 50The conventional and recommended way to deal and manage with memory regions 51marked with attributes is by using the provided ``mem-attr`` helper library by 52enabling :kconfig:option:`CONFIG_MEM_ATTR`. When this option is enabled the 53list of memory regions and their attributes are compiled in a user-accessible 54array and a set of functions is made available that can be used to query, probe 55and act on regions and attributes (see next section for more details). 56 57.. note:: 58 59 The ``zephyr,memory-attr`` property is only a descriptive property of the 60 capabilities of the associated memory region, but it does not result in any 61 actual setting for the memory to be set. The user, code or subsystem willing 62 to use this information to do some work (for example creating an MPU region 63 out of the property) must use either the provided ``mem-attr`` library or 64 the usual devicetree helpers to perform the required work / setting. 65 66A test for the ``mem-attr`` library and its usage is provided in 67``tests/subsys/mem_mgmt/mem_attr/``. 68 69Migration guide from `zephyr,memory-region-mpu` 70*********************************************** 71 72When the ``zephyr,memory-attr`` property was introduced, the 73``zephyr,memory-region-mpu`` property was removed and deprecated. 74 75The developers that are still using the deprecated property can move to the new 76one by renaming the property and changing its value according to the following list: 77 78.. code-block:: none 79 80 "RAM" -> <( DT_ARM_MPU(ATTR_MPU_RAM) )> 81 "RAM_NOCACHE" -> <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )> 82 "FLASH" -> <( DT_ARM_MPU(ATTR_MPU_FLASH) )> 83 "PPB" -> <( DT_ARM_MPU(ATTR_MPU_PPB) )> 84 "IO" -> <( DT_ARM_MPU(ATTR_MPU_IO) )> 85 "EXTMEM" -> <( DT_ARM_MPU(ATTR_MPU_EXTMEM) )> 86 87Memory Attributes Heap Allocator 88******************************** 89 90It is possible to leverage the memory attribute property ``zephyr,memory-attr`` 91to define and create a set of memory heaps from which the user can allocate 92memory from with certain attributes / capabilities. 93 94When the :kconfig:option:`CONFIG_MEM_ATTR_HEAP` is set, every region marked 95with one of the memory attributes listed in in 96:zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr-sw.h` is added 97to a pool of memory heaps used for dynamic allocation of memory buffers with 98certain attributes. 99 100Here a non exhaustive list of possible attributes: 101 102.. code-block:: none 103 104 DT_MEM_SW_ALLOC_CACHE 105 DT_MEM_SW_ALLOC_NON_CACHE 106 DT_MEM_SW_ALLOC_DMA 107 108For example we can define several memory regions with different attributes and 109use the appropriate attribute to indicate that it is possible to dynamically 110allocate memory from those regions: 111 112.. code-block:: devicetree 113 114 mem_cacheable: memory@10000000 { 115 compatible = "mmio-sram"; 116 reg = <0x10000000 0x1000>; 117 zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_SW_ALLOC_CACHE )>; 118 }; 119 120 mem_non_cacheable: memory@20000000 { 121 compatible = "mmio-sram"; 122 reg = <0x20000000 0x1000>; 123 zephyr,memory-attr = <( DT_MEM_NON_CACHEABLE | ATTR_SW_ALLOC_NON_CACHE )>; 124 }; 125 126 mem_cacheable_big: memory@30000000 { 127 compatible = "mmio-sram"; 128 reg = <0x30000000 0x10000>; 129 zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_OOO | DT_MEM_SW_ALLOC_CACHE )>; 130 }; 131 132 mem_cacheable_dma: memory@40000000 { 133 compatible = "mmio-sram"; 134 reg = <0x40000000 0x10000>; 135 zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_DMA | 136 DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA )>; 137 }; 138 139The user can then dynamically carve memory out of those regions using the 140provided functions, the library will take care of allocating memory from the 141correct heap depending on the provided attribute and size: 142 143.. code-block:: c 144 145 // Init the pool 146 mem_attr_heap_pool_init(); 147 148 // Allocate 0x100 bytes of cacheable memory from `mem_cacheable` 149 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100); 150 151 // Allocate 0x200 bytes of non-cacheable memory aligned to 32 bytes 152 // from `mem_non_cacheable` 153 block = mem_attr_heap_aligned_alloc(ATTR_SW_ALLOC_NON_CACHE, 0x100, 32); 154 155 // Allocate 0x100 bytes of cacheable and dma-able memory from `mem_cacheable_dma` 156 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA, 0x100); 157 158When several regions are marked with the same attributes, the memory is allocated: 159 1601. From the regions where the ``zephyr,memory-attr`` property has the requested 161 property (or properties). 162 1632. Among the regions as at point 1, from the smallest region if there is any 164 unallocated space left for the requested size 165 1663. If there is not enough space, from the next bigger region able to 167 accommodate the requested size 168 169The following example shows the point 3: 170 171.. code-block:: c 172 173 // This memory is allocated from `mem_non_cacheable` 174 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100); 175 176 // This memory is allocated from `mem_cacheable_big` 177 block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x5000); 178 179.. note:: 180 181 The framework is assuming that the memory regions used to create the heaps 182 are usable by the code and available at init time. The user must take of 183 initializing and setting the memory area before calling 184 :c:func:`mem_attr_heap_pool_init`. 185 186 That means that the region must be correctly configured in terms of MPU / 187 MMU (if needed) and that an actual heap can be created out of it, for 188 example by leveraging the ``zephyr,memory-region`` property to create a 189 proper linker section to accommodate the heap. 190 191API Reference 192************* 193 194.. doxygengroup:: memory_attr_interface 195.. doxygengroup:: memory_attr_heap 196