1 /* 2 * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #pragma once 8 9 #include <stdint.h> 10 #include <stdlib.h> 11 #include "multi_heap.h" 12 #include <sdkconfig.h> 13 #include "esp_err.h" 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 /** 20 * @brief Flags to indicate the capabilities of the various memory systems 21 */ 22 #define MALLOC_CAP_EXEC (1<<0) ///< Memory must be able to run executable code 23 #define MALLOC_CAP_32BIT (1<<1) ///< Memory must allow for aligned 32-bit data accesses 24 #define MALLOC_CAP_8BIT (1<<2) ///< Memory must allow for 8/16/...-bit data accesses 25 #define MALLOC_CAP_DMA (1<<3) ///< Memory must be able to accessed by DMA 26 #define MALLOC_CAP_PID2 (1<<4) ///< Memory must be mapped to PID2 memory space (PIDs are not currently used) 27 #define MALLOC_CAP_PID3 (1<<5) ///< Memory must be mapped to PID3 memory space (PIDs are not currently used) 28 #define MALLOC_CAP_PID4 (1<<6) ///< Memory must be mapped to PID4 memory space (PIDs are not currently used) 29 #define MALLOC_CAP_PID5 (1<<7) ///< Memory must be mapped to PID5 memory space (PIDs are not currently used) 30 #define MALLOC_CAP_PID6 (1<<8) ///< Memory must be mapped to PID6 memory space (PIDs are not currently used) 31 #define MALLOC_CAP_PID7 (1<<9) ///< Memory must be mapped to PID7 memory space (PIDs are not currently used) 32 #define MALLOC_CAP_SPIRAM (1<<10) ///< Memory must be in SPI RAM 33 #define MALLOC_CAP_INTERNAL (1<<11) ///< Memory must be internal; specifically it should not disappear when flash/spiram cache is switched off 34 #define MALLOC_CAP_DEFAULT (1<<12) ///< Memory can be returned in a non-capability-specific memory allocation (e.g. malloc(), calloc()) call 35 #define MALLOC_CAP_IRAM_8BIT (1<<13) ///< Memory must be in IRAM and allow unaligned access 36 #define MALLOC_CAP_RETENTION (1<<14) 37 #define MALLOC_CAP_RTCRAM (1<<15) ///< Memory must be in RTC fast memory 38 39 #define MALLOC_CAP_INVALID (1<<31) ///< Memory can't be used / list end marker 40 41 /** 42 * @brief callback called when a allocation operation fails, if registered 43 * @param size in bytes of failed allocation 44 * @param caps capabillites requested of failed allocation 45 * @param function_name function which generated the failure 46 */ 47 typedef void (*esp_alloc_failed_hook_t) (size_t size, uint32_t caps, const char * function_name); 48 49 /** 50 * @brief registers a callback function to be invoked if a memory allocation operation fails 51 * @param callback caller defined callback to be invoked 52 * @return ESP_OK if callback was registered. 53 */ 54 esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callback); 55 56 /** 57 * @brief Allocate a chunk of memory which has the given capabilities 58 * 59 * Equivalent semantics to libc malloc(), for capability-aware memory. 60 * 61 * In IDF, ``malloc(p)`` is equivalent to ``heap_caps_malloc(p, MALLOC_CAP_8BIT)``. 62 * 63 * @param size Size, in bytes, of the amount of memory to allocate 64 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 65 * of memory to be returned 66 * 67 * @return A pointer to the memory allocated on success, NULL on failure 68 */ 69 void *heap_caps_malloc(size_t size, uint32_t caps); 70 71 72 /** 73 * @brief Free memory previously allocated via heap_caps_malloc() or heap_caps_realloc(). 74 * 75 * Equivalent semantics to libc free(), for capability-aware memory. 76 * 77 * In IDF, ``free(p)`` is equivalent to ``heap_caps_free(p)``. 78 * 79 * @param ptr Pointer to memory previously returned from heap_caps_malloc() or heap_caps_realloc(). Can be NULL. 80 */ 81 void heap_caps_free( void *ptr); 82 83 /** 84 * @brief Reallocate memory previously allocated via heap_caps_malloc() or heap_caps_realloc(). 85 * 86 * Equivalent semantics to libc realloc(), for capability-aware memory. 87 * 88 * In IDF, ``realloc(p, s)`` is equivalent to ``heap_caps_realloc(p, s, MALLOC_CAP_8BIT)``. 89 * 90 * 'caps' parameter can be different to the capabilities that any original 'ptr' was allocated with. In this way, 91 * realloc can be used to "move" a buffer if necessary to ensure it meets a new set of capabilities. 92 * 93 * @param ptr Pointer to previously allocated memory, or NULL for a new allocation. 94 * @param size Size of the new buffer requested, or 0 to free the buffer. 95 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 96 * of memory desired for the new allocation. 97 * 98 * @return Pointer to a new buffer of size 'size' with capabilities 'caps', or NULL if allocation failed. 99 */ 100 void *heap_caps_realloc( void *ptr, size_t size, uint32_t caps); 101 102 /** 103 * @brief Allocate a aligned chunk of memory which has the given capabilities 104 * 105 * Equivalent semantics to libc aligned_alloc(), for capability-aware memory. 106 * @param alignment How the pointer received needs to be aligned 107 * must be a power of two 108 * @param size Size, in bytes, of the amount of memory to allocate 109 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 110 * of memory to be returned 111 * 112 * @return A pointer to the memory allocated on success, NULL on failure 113 * 114 * 115 */ 116 void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps); 117 118 /** 119 * @brief Used to deallocate memory previously allocated with heap_caps_aligned_alloc 120 * 121 * @param ptr Pointer to the memory allocated 122 * @note This function is deprecated, plase consider using heap_caps_free() instead 123 */ 124 void __attribute__((deprecated)) heap_caps_aligned_free(void *ptr); 125 126 /** 127 * @brief Allocate a aligned chunk of memory which has the given capabilities. The initialized value in the memory is set to zero. 128 * 129 * @param alignment How the pointer received needs to be aligned 130 * must be a power of two 131 * @param n Number of continuing chunks of memory to allocate 132 * @param size Size, in bytes, of a chunk of memory to allocate 133 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 134 * of memory to be returned 135 * 136 * @return A pointer to the memory allocated on success, NULL on failure 137 * 138 */ 139 void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps); 140 141 142 /** 143 * @brief Allocate a chunk of memory which has the given capabilities. The initialized value in the memory is set to zero. 144 * 145 * Equivalent semantics to libc calloc(), for capability-aware memory. 146 * 147 * In IDF, ``calloc(p)`` is equivalent to ``heap_caps_calloc(p, MALLOC_CAP_8BIT)``. 148 * 149 * @param n Number of continuing chunks of memory to allocate 150 * @param size Size, in bytes, of a chunk of memory to allocate 151 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 152 * of memory to be returned 153 * 154 * @return A pointer to the memory allocated on success, NULL on failure 155 */ 156 void *heap_caps_calloc(size_t n, size_t size, uint32_t caps); 157 158 /** 159 * @brief Get the total size of all the regions that have the given capabilities 160 * 161 * This function takes all regions capable of having the given capabilities allocated in them 162 * and adds up the total space they have. 163 * 164 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 165 * of memory 166 * 167 * @return total size in bytes 168 */ 169 170 size_t heap_caps_get_total_size(uint32_t caps); 171 172 /** 173 * @brief Get the total free size of all the regions that have the given capabilities 174 * 175 * This function takes all regions capable of having the given capabilities allocated in them 176 * and adds up the free space they have. 177 * 178 * Note that because of heap fragmentation it is probably not possible to allocate a single block of memory 179 * of this size. Use heap_caps_get_largest_free_block() for this purpose. 180 181 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 182 * of memory 183 * 184 * @return Amount of free bytes in the regions 185 */ 186 size_t heap_caps_get_free_size( uint32_t caps ); 187 188 189 /** 190 * @brief Get the total minimum free memory of all regions with the given capabilities 191 * 192 * This adds all the low water marks of the regions capable of delivering the memory 193 * with the given capabilities. 194 * 195 * Note the result may be less than the global all-time minimum available heap of this kind, as "low water marks" are 196 * tracked per-region. Individual regions' heaps may have reached their "low water marks" at different points in time. However 197 * this result still gives a "worst case" indication for all-time minimum free heap. 198 * 199 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 200 * of memory 201 * 202 * @return Amount of free bytes in the regions 203 */ 204 size_t heap_caps_get_minimum_free_size( uint32_t caps ); 205 206 /** 207 * @brief Get the largest free block of memory able to be allocated with the given capabilities. 208 * 209 * Returns the largest value of ``s`` for which ``heap_caps_malloc(s, caps)`` will succeed. 210 * 211 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 212 * of memory 213 * 214 * @return Size of largest free block in bytes. 215 */ 216 size_t heap_caps_get_largest_free_block( uint32_t caps ); 217 218 219 /** 220 * @brief Get heap info for all regions with the given capabilities. 221 * 222 * Calls multi_heap_info() on all heaps which share the given capabilities. The information returned is an aggregate 223 * across all matching heaps. The meanings of fields are the same as defined for multi_heap_info_t, except that 224 * ``minimum_free_bytes`` has the same caveats described in heap_caps_get_minimum_free_size(). 225 * 226 * @param info Pointer to a structure which will be filled with relevant 227 * heap metadata. 228 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 229 * of memory 230 * 231 */ 232 void heap_caps_get_info( multi_heap_info_t *info, uint32_t caps ); 233 234 235 /** 236 * @brief Print a summary of all memory with the given capabilities. 237 * 238 * Calls multi_heap_info on all heaps which share the given capabilities, and 239 * prints a two-line summary for each, then a total summary. 240 * 241 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 242 * of memory 243 * 244 */ 245 void heap_caps_print_heap_info( uint32_t caps ); 246 247 /** 248 * @brief Check integrity of all heap memory in the system. 249 * 250 * Calls multi_heap_check on all heaps. Optionally print errors if heaps are corrupt. 251 * 252 * Calling this function is equivalent to calling heap_caps_check_integrity 253 * with the caps argument set to MALLOC_CAP_INVALID. 254 * 255 * @param print_errors Print specific errors if heap corruption is found. 256 * 257 * @return True if all heaps are valid, False if at least one heap is corrupt. 258 */ 259 bool heap_caps_check_integrity_all(bool print_errors); 260 261 /** 262 * @brief Check integrity of all heaps with the given capabilities. 263 * 264 * Calls multi_heap_check on all heaps which share the given capabilities. Optionally 265 * print errors if the heaps are corrupt. 266 * 267 * See also heap_caps_check_integrity_all to check all heap memory 268 * in the system and heap_caps_check_integrity_addr to check memory 269 * around a single address. 270 * 271 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 272 * of memory 273 * @param print_errors Print specific errors if heap corruption is found. 274 * 275 * @return True if all heaps are valid, False if at least one heap is corrupt. 276 */ 277 bool heap_caps_check_integrity(uint32_t caps, bool print_errors); 278 279 /** 280 * @brief Check integrity of heap memory around a given address. 281 * 282 * This function can be used to check the integrity of a single region of heap memory, 283 * which contains the given address. 284 * 285 * This can be useful if debugging heap integrity for corruption at a known address, 286 * as it has a lower overhead than checking all heap regions. Note that if the corrupt 287 * address moves around between runs (due to timing or other factors) then this approach 288 * won't work and you should call heap_caps_check_integrity or 289 * heap_caps_check_integrity_all instead. 290 * 291 * @note The entire heap region around the address is checked, not only the adjacent 292 * heap blocks. 293 * 294 * @param addr Address in memory. Check for corruption in region containing this address. 295 * @param print_errors Print specific errors if heap corruption is found. 296 * 297 * @return True if the heap containing the specified address is valid, 298 * False if at least one heap is corrupt or the address doesn't belong to a heap region. 299 */ 300 bool heap_caps_check_integrity_addr(intptr_t addr, bool print_errors); 301 302 /** 303 * @brief Enable malloc() in external memory and set limit below which 304 * malloc() attempts are placed in internal memory. 305 * 306 * When external memory is in use, the allocation strategy is to initially try to 307 * satisfy smaller allocation requests with internal memory and larger requests 308 * with external memory. This sets the limit between the two, as well as generally 309 * enabling allocation in external memory. 310 * 311 * @param limit Limit, in bytes. 312 */ 313 void heap_caps_malloc_extmem_enable(size_t limit); 314 315 /** 316 * @brief Allocate a chunk of memory as preference in decreasing order. 317 * 318 * @attention The variable parameters are bitwise OR of MALLOC_CAP_* flags indicating the type of memory. 319 * This API prefers to allocate memory with the first parameter. If failed, allocate memory with 320 * the next parameter. It will try in this order until allocating a chunk of memory successfully 321 * or fail to allocate memories with any of the parameters. 322 * 323 * @param size Size, in bytes, of the amount of memory to allocate 324 * @param num Number of variable paramters 325 * 326 * @return A pointer to the memory allocated on success, NULL on failure 327 */ 328 void *heap_caps_malloc_prefer( size_t size, size_t num, ... ); 329 330 /** 331 * @brief Allocate a chunk of memory as preference in decreasing order. 332 * 333 * @param ptr Pointer to previously allocated memory, or NULL for a new allocation. 334 * @param size Size of the new buffer requested, or 0 to free the buffer. 335 * @param num Number of variable paramters 336 * 337 * @return Pointer to a new buffer of size 'size', or NULL if allocation failed. 338 */ 339 void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... ); 340 341 /** 342 * @brief Allocate a chunk of memory as preference in decreasing order. 343 * 344 * @param n Number of continuing chunks of memory to allocate 345 * @param size Size, in bytes, of a chunk of memory to allocate 346 * @param num Number of variable paramters 347 * 348 * @return A pointer to the memory allocated on success, NULL on failure 349 */ 350 void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... ); 351 352 /** 353 * @brief Dump the full structure of all heaps with matching capabilities. 354 * 355 * Prints a large amount of output to serial (because of locking limitations, 356 * the output bypasses stdout/stderr). For each (variable sized) block 357 * in each matching heap, the following output is printed on a single line: 358 * 359 * - Block address (the data buffer returned by malloc is 4 bytes after this 360 * if heap debugging is set to Basic, or 8 bytes otherwise). 361 * - Data size (the data size may be larger than the size requested by malloc, 362 * either due to heap fragmentation or because of heap debugging level). 363 * - Address of next block in the heap. 364 * - If the block is free, the address of the next free block is also printed. 365 * 366 * @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type 367 * of memory 368 */ 369 void heap_caps_dump(uint32_t caps); 370 371 /** 372 * @brief Dump the full structure of all heaps. 373 * 374 * Covers all registered heaps. Prints a large amount of output to serial. 375 * 376 * Output is the same as for heap_caps_dump. 377 * 378 */ 379 void heap_caps_dump_all(void); 380 381 /** 382 * @brief Return the size that a particular pointer was allocated with. 383 * 384 * @param ptr Pointer to currently allocated heap memory. Must be a pointer value previously 385 * returned by heap_caps_malloc,malloc,calloc, etc. and not yet freed. 386 * 387 * @note The app will crash with an assertion failure if the pointer is not valid. 388 * 389 * @return Size of the memory allocated at this block. 390 * 391 */ 392 size_t heap_caps_get_allocated_size( void *ptr ); 393 394 #ifdef __cplusplus 395 } 396 #endif 397