1 /* 2 * Copyright 2018, 2020 NXP 3 * All rights reserved. 4 * 5 * 6 * SPDX-License-Identifier: BSD-3-Clause 7 */ 8 9 #ifndef __MEM_MANAGER_H__ 10 #define __MEM_MANAGER_H__ 11 12 #ifndef SDK_COMPONENT_DEPENDENCY_FSL_COMMON 13 #define SDK_COMPONENT_DEPENDENCY_FSL_COMMON (1U) 14 #endif 15 #if (defined(SDK_COMPONENT_DEPENDENCY_FSL_COMMON) && (SDK_COMPONENT_DEPENDENCY_FSL_COMMON > 0U)) 16 #include "fsl_common.h" 17 #else 18 #endif 19 20 /*! 21 * @addtogroup MemManager 22 * @{ 23 */ 24 25 /***************************************************************************** 26 ****************************************************************************** 27 * Public macros 28 ****************************************************************************** 29 *****************************************************************************/ 30 31 /*! 32 * @brief Provide Minimal heap size for application to execute correctly. 33 * 34 * The application can define a minimal heap size for proper code exection at run time, 35 * This will issue a link error if the minimal heap size requirement is not fullfilled (not enough space in RAM) 36 * By Default, Minimal heap size is set to 4 bytes (unlikely enough to have application work correctly) 37 */ 38 #if !defined(MinimalHeapSize_c) 39 #define MinimalHeapSize_c (uint32_t)4 40 #endif 41 42 43 /*! 44 * @brief Configures the memory manager light enable. 45 */ 46 #ifndef gMemManagerLight 47 #define gMemManagerLight (1) 48 #endif 49 50 /*! 51 * @brief Configures the memory manager trace debug enable. 52 */ 53 #ifndef MEM_MANAGER_ENABLE_TRACE 54 #define MEM_MANAGER_ENABLE_TRACE (0) 55 #endif 56 57 /* 58 * @brief Configures the memory manager remove memory buffer. 59 */ 60 #ifndef MEM_MANAGER_BUFFER_REMOVE 61 #define MEM_MANAGER_BUFFER_REMOVE (0) 62 #endif 63 64 /*! 65 * @brief Configures the memory manager pre configure. 66 */ 67 #ifndef MEM_MANAGER_PRE_CONFIGURE 68 #define MEM_MANAGER_PRE_CONFIGURE (1) 69 #endif 70 71 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) 72 #ifndef MEM_POOL_SIZE 73 #define MEM_POOL_SIZE (32U) 74 #endif 75 #ifndef MEM_BLOCK_SIZE 76 #define MEM_BLOCK_SIZE (12U) 77 #endif 78 #else 79 #ifndef MEM_POOL_SIZE 80 #define MEM_POOL_SIZE (20U) 81 #endif 82 #ifndef MEM_BLOCK_SIZE 83 #define MEM_BLOCK_SIZE (4U) 84 #endif 85 #endif 86 87 #define MAX_POOL_ID 3U 88 89 /* Debug Macros - stub if not defined */ 90 #ifndef MEM_DBG_LOG 91 #define MEM_DBG_LOG(...) 92 #endif 93 94 /* Default memory allocator */ 95 #ifndef MEM_BufferAlloc 96 #define MEM_BufferAlloc(numBytes) MEM_BufferAllocWithId(numBytes, 0) 97 #endif 98 99 #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U)) 100 /* 101 * Defines pools by block size and number of blocks. Must be aligned to 4 bytes. 102 * Defines block as (blockSize ,numberOfBlocks, id), id must be keep here, 103 * even id is 0, will be _block_set_(64, 8, 0) _eol_ 104 * and _block_set_(64, 8) _eol_\ could not supported 105 */ 106 #ifndef PoolsDetails_c 107 #define PoolsDetails_c _block_set_(64, 8, 0) _eol_ _block_set_(128, 2, 1) _eol_ _block_set_(256, 6, 1) _eol_ 108 #endif /* PoolsDetails_c */ 109 110 #define MEM_BLOCK_DATA_BUFFER_NONAME_DEFINE(blockSize, numberOfBlocks, id) \ 111 uint32_t g_poolBuffer##blockSize##_##numberOfBlocks##_##id[(MEM_POOL_SIZE + (numberOfBlocks)*MEM_BLOCK_SIZE + \ 112 ((numberOfBlocks) * (blockSize)) + 3U) >> \ 113 2U]; 114 115 #define MEM_BLOCK_BUFFER_NONAME_DEFINE(blockSize, numberOfBlocks, id) \ 116 MEM_BLOCK_DATA_BUFFER_NONAME_DEFINE(blockSize, numberOfBlocks, id) \ 117 const static mem_config_t g_poolHeadBuffer##blockSize##_##numberOfBlocks##_##id = { \ 118 (blockSize), (numberOfBlocks), (id), (0), (uint8_t *)&g_poolBuffer##blockSize##_##numberOfBlocks##_##id[0]} 119 #define MEM_BLOCK_NONAME_BUFFER(blockSize, numberOfBlocks, id) \ 120 (uint8_t *)&g_poolHeadBuffer##blockSize##_##numberOfBlocks##_##id 121 #endif /* MEM_MANAGER_PRE_CONFIGURE */ 122 123 /*! 124 * @brief Defines the memory buffer 125 * 126 * This macro is used to define the shell memory buffer for memory manager. 127 * And then uses the macro MEM_BLOCK_BUFFER to get the memory buffer pointer. 128 * The macro should not be used in any function. 129 * 130 * This is a example, 131 * @code 132 * MEM_BLOCK_BUFFER_DEFINE(app64, 5, 64,0); 133 * MEM_BLOCK_BUFFER_DEFINE(app128, 6, 128,0); 134 * MEM_BLOCK_BUFFER_DEFINE(app256, 7, 256,0); 135 * @endcode 136 * 137 * @param name The name string of the memory buffer. 138 * @param numberOfBlocks The number Of Blocks. 139 * @param blockSize The memory block size. 140 * @param id The id Of memory buffer. 141 */ 142 #define MEM_BLOCK_DATA_BUFFER_DEFINE(name, numberOfBlocks, blockSize, id) \ 143 uint32_t \ 144 g_poolBuffer##name[(MEM_POOL_SIZE + numberOfBlocks * MEM_BLOCK_SIZE + numberOfBlocks * blockSize + 3U) >> 2U]; 145 146 #define MEM_BLOCK_BUFFER_DEFINE(name, numberOfBlocks, blockSize, id) \ 147 MEM_BLOCK_DATA_BUFFER_DEFINE(name, numberOfBlocks, blockSize, id) \ 148 mem_config_t g_poolHeadBuffer##name = {(blockSize), (numberOfBlocks), (id), (0), (uint8_t *)&g_poolBuffer##name[0]} 149 150 /*! \ 151 * @brief Gets the memory buffer pointer \ 152 * \ 153 * This macro is used to get the memory buffer pointer. The macro should \ 154 * not be used before the macro MEM_BLOCK_BUFFER_DEFINE is used. \ 155 * \ 156 * @param name The memory name string of the buffer. \ 157 */ 158 #define MEM_BLOCK_BUFFER(name) (uint8_t *)&g_poolHeadBuffer##name 159 160 /***************************************************************************** 161 ****************************************************************************** 162 * Public type definitions 163 ****************************************************************************** 164 *****************************************************************************/ 165 166 /**@brief Memory status. */ 167 #if (defined(SDK_COMPONENT_DEPENDENCY_FSL_COMMON) && (SDK_COMPONENT_DEPENDENCY_FSL_COMMON > 0U)) 168 typedef enum _mem_status 169 { 170 kStatus_MemSuccess = kStatus_Success, /* No error occurred */ 171 kStatus_MemInitError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 1), /* Memory initialization error */ 172 kStatus_MemAllocError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 2), /* Memory allocation error */ 173 kStatus_MemFreeError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 3), /* Memory free error */ 174 kStatus_MemUnknownError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 4), /* something bad has happened... */ 175 } mem_status_t; 176 #else 177 typedef enum _mem_status 178 { 179 kStatus_MemSuccess = 0, /* No error occurred */ 180 kStatus_MemInitError = 1, /* Memory initialization error */ 181 kStatus_MemAllocError = 2, /* Memory allocation error */ 182 kStatus_MemFreeError = 3, /* Memory free error */ 183 kStatus_MemUnknownError = 4, /* something bad has happened... */ 184 } mem_status_t; 185 186 #endif 187 188 /**@brief Memory user config. */ 189 typedef struct _mem_config 190 { 191 uint16_t blockSize; /*< The memory block size. */ 192 uint16_t numberOfBlocks; /*< The number Of Blocks. */ 193 uint16_t poolId; /*< The pool id Of Blocks. */ 194 uint16_t reserved; /*< reserved. */ 195 uint8_t *pbuffer; /*< buffer. */ 196 } mem_config_t; 197 198 #if defined(gFSCI_MemAllocTest_Enabled_d) && (gFSCI_MemAllocTest_Enabled_d) 199 /**@brief Memory status. */ 200 typedef enum mem_alloc_test_status 201 { 202 kStatus_AllocSuccess = kStatus_Success, /* Allow buffer to be allocated */ 203 kStatus_AllocBlock = kStatus_Busy, /* Block buffer to be allocated */ 204 } mem_alloc_test_status_t; 205 #endif 206 207 /***************************************************************************** 208 ****************************************************************************** 209 * Public memory declarations 210 ****************************************************************************** 211 *****************************************************************************/ 212 /***************************************************************************** 213 ****************************************************************************** 214 * Public prototypes 215 ****************************************************************************** 216 *****************************************************************************/ 217 218 #if defined(__cplusplus) 219 extern "C" { 220 #endif /* _cplusplus */ 221 #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U)) 222 /*! 223 * @brief Initialises the Memory Manager. 224 * 225 */ 226 mem_status_t MEM_Init(void); 227 228 #endif 229 230 #if !defined(gMemManagerLight) || (gMemManagerLight == 0) 231 /*! 232 * @brief Add memory buffer to memory manager buffer list. 233 * 234 * @note This API should be called when need add memory buffer to memory manager buffer list. First use 235 * MEM_BLOCK_BUFFER_DEFINE to 236 * define memory buffer, then call MEM_AddBuffer function with MEM_BLOCK_BUFFER Macro as the input parameter. 237 * @code 238 * MEM_BLOCK_BUFFER_DEFINE(app64, 5, 64,0); 239 * MEM_BLOCK_BUFFER_DEFINE(app128, 6, 128,0); 240 * MEM_BLOCK_BUFFER_DEFINE(app256, 7, 256,0); 241 * 242 * MEM_AddBuffer(MEM_BLOCK_BUFFER(app64)); 243 * MEM_AddBuffer(MEM_BLOCK_BUFFER(app128)); 244 * MEM_AddBuffer(MEM_BLOCK_BUFFER(app256)); 245 * @endcode 246 * 247 * @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter. 248 * 249 * @retval kStatus_MemSuccess Memory manager add buffer succeed. 250 * @retval kStatus_MemUnknownError Memory manager add buffer error occurred. 251 */ 252 mem_status_t MEM_AddBuffer(const uint8_t *buffer); 253 #endif /* gMemManagerLight */ 254 255 #if !defined(gMemManagerLight) || (gMemManagerLight == 0) 256 #if (defined(MEM_MANAGER_BUFFER_REMOVE) && (MEM_MANAGER_BUFFER_REMOVE > 0U)) 257 /*! 258 * @brief Remove memory buffer from memory manager buffer list. 259 * 260 * @note This API should be called when need remove memory buffer from memory manager buffer list. Use MEM_BLOCK_BUFFER 261 * Macro as the input parameter. 262 * 263 * @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter. 264 * 265 * @retval kStatus_MemSuccess Memory manager remove buffer succeed. 266 * @retval kStatus_MemUnknownError Memory manager remove buffer error occurred. 267 */ 268 mem_status_t MEM_RemoveBuffer(uint8_t *buffer); 269 #endif /* MEM_MANAGER_BUFFER_REMOVE */ 270 #endif /* gMemManagerLight */ 271 /*! 272 * @brief Allocate a block from the memory pools. The function uses the 273 * numBytes argument to look up a pool with adequate block sizes. 274 * 275 * @param numBytes The number of bytes will be allocated. 276 * @param poolId The ID of the pool where to search for a free buffer. 277 * @retval Memory buffer address when allocate success, NULL when allocate fail. 278 */ 279 void *MEM_BufferAllocWithId(uint32_t numBytes, uint8_t poolId); 280 281 /*! 282 * @brief Memory buffer free . 283 * 284 * @param buffer The memory buffer address will be free. 285 * @retval kStatus_MemSuccess Memory free succeed. 286 * @retval kStatus_MemFreeError Memory free error occurred. 287 */ 288 mem_status_t MEM_BufferFree(void *buffer); 289 290 /*! 291 * @brief Returns the size of a given buffer. 292 * 293 * @param buffer The memory buffer address will be get size. 294 * @retval The size of a given buffer. 295 */ 296 uint16_t MEM_BufferGetSize(void *buffer); 297 298 /*! 299 * @brief Frees all allocated blocks by selected source and in selected pool. 300 * 301 * @param poolId Selected pool Id (4 LSBs of poolId parameter) and selected 302 * source Id (4 MSBs of poolId parameter). 303 * @retval kStatus_MemSuccess Memory free succeed. 304 * @retval kStatus_MemFreeError Memory free error occurred. 305 */ 306 mem_status_t MEM_BufferFreeAllWithId(uint8_t poolId); 307 308 /*! 309 * @brief Memory buffer realloc. 310 * 311 * @param buffer The memory buffer address will be reallocated. 312 * @param new_size The number of bytes will be reallocated 313 * @retval kStatus_MemSuccess Memory free succeed. 314 * @retval kStatus_MemFreeError Memory free error occurred. 315 */ 316 void *MEM_BufferRealloc(void *buffer, uint32_t new_size); 317 318 /*! 319 * @brief Get the address after the last allocated block if MemManagerLight is used. 320 * 321 * @retval UpperLimit Return the address after the last allocated block if MemManagerLight is used. 322 * @retval 0 Return 0 in case of the legacy MemManager. 323 */ 324 uint32_t MEM_GetHeapUpperLimit(void); 325 326 /*! 327 * @brief Get the free space in the heap. 328 * 329 * @retval FreeHeapSize Return the free space in the heap if MemManagerLight is used. 330 * @retval 0 Return 0 in case of the legacy MemManager. 331 */ 332 uint32_t MEM_GetFreeHeapSize(void); 333 334 #if defined(gMemManagerLight) && (gMemManagerLight > 0) 335 /*! 336 * @brief Selective RAM bank reinit after low power, based on a requested address range 337 * Useful for ECC RAM banks 338 * Defined as weak and empty in fsl_component_mem_manager_light.c to be overloaded by user 339 * 340 * @param[in] startAddress Start address of the requested range 341 * @param[in] endAddress End address of the requested range 342 */ 343 void MEM_ReinitRamBank(uint32_t startAddress, uint32_t endAddress); 344 #endif /* gMemManagerLight */ 345 346 #if !defined(gMemManagerLight) || (gMemManagerLight == 0) 347 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) 348 /*! 349 * @brief Function to print statistics related to memory blocks managed by memory manager. Like bellow: 350 * allocationFailures: 241 freeFailures:0 351 * POOL: ID 0 status: 352 * numBlocks allocatedBlocks allocatedBlocksPeak poolFragmentWaste poolFragmentWastePeak poolFragmentMinWaste 353 * poolTotalFragmentWaste 354 * 5 5 5 59 63 59 305 355 * Currently pool meory block allocate status: 356 * Block 0 Allocated bytes: 1 357 * Block 1 Allocated bytes: 2 358 * Block 2 Allocated bytes: 3 359 * Block 3 Allocated bytes: 4 360 * Block 4 Allocated bytes: 5 361 * 362 * @details This API prints information with respects to each pool and block, including Allocated size, 363 * total block count, number of blocks in use at the time of printing, The API is intended to 364 * help developers tune the block sizes to make optimal use of memory for the application. 365 * 366 * @note This API should be disable by configure MEM_MANAGER_ENABLE_TRACE to 0 367 * 368 */ 369 void MEM_Trace(void); 370 371 #endif /* MEM_MANAGER_ENABLE_TRACE */ 372 #endif /* gMemManagerLight */ 373 374 #if defined(gMemManagerLight) && (gMemManagerLight == 1) 375 void *MEM_CallocAlt(size_t len, size_t val); 376 #endif /*gMemManagerLight == 1*/ 377 378 #if defined(__cplusplus) 379 } 380 #endif 381 /*! @}*/ 382 #endif /* #ifndef __MEM_MANAGER_H__ */ 383