1 /*
2 * Copyright 2018-2020 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_common.h"
10 #if defined(MEM_STATISTICS_INTERNAL) || defined(MEM_MANAGER_BENCH)
11 #include "fsl_component_timer_manager.h"
12 #include "fsl_component_mem_manager_internal.h"
13 #endif /* MEM_STATISTICS_INTERNAL MEM_MANAGER_BENCH*/
14 #include "fsl_component_mem_manager.h"
15 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
16 #include "fsl_debug_console.h"
17 #endif
18
19 #if defined(OSA_USED)
20 #include "fsl_os_abstraction.h"
21 #if (defined(USE_RTOS) && (USE_RTOS > 0U))
22 #define MEM_ENTER_CRITICAL() \
23 OSA_SR_ALLOC(); \
24 OSA_ENTER_CRITICAL()
25 #define MEM_EXIT_CRITICAL() OSA_EXIT_CRITICAL()
26 #else
27 #define MEM_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ();
28 #define MEM_EXIT_CRITICAL() EnableGlobalIRQ(regPrimask);
29 #endif
30 #else
31 #define MEM_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ();
32 #define MEM_EXIT_CRITICAL() EnableGlobalIRQ(regPrimask);
33 #endif
34 #if !defined(gMemManagerLight) || (gMemManagerLight == 0)
35 /*****************************************************************************
36 ******************************************************************************
37 * Private macros
38 ******************************************************************************
39 *****************************************************************************/
40 #if defined(__IAR_SYSTEMS_ICC__)
41 #define __mem_get_LR() __get_LR()
42 #elif defined(__GNUC__)
43 #define __mem_get_LR() __builtin_return_address(0)
44 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
45 #define __mem_get_LR() __return_address()
46 #endif
47
48 #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U))
49 #undef _block_set_
50 #undef _eol_
51
52 #define _eol_ ;
53 #define _block_set_ MEM_BLOCK_BUFFER_NONAME_DEFINE
54
55 PoolsDetails_c
56
57 #undef _block_set_
58 #undef _number_of_blocks_
59 #undef _eol_
60 #undef _pool_id_
61
62 #define _eol_ ,
63 #define _block_set_ MEM_BLOCK_NONAME_BUFFER
64
65 static uint8_t const *s_PoolList[] = {PoolsDetails_c};
66 #endif /*MEM_MANAGER_PRE_CONFIGURE*/
67
68 /*****************************************************************************
69 ******************************************************************************
70 * Private type definitions
71 ******************************************************************************
72 *****************************************************************************/
73 /*! @brief Buffer pools structure*/
74 typedef struct _mem_pool_structure
75 {
76 struct _mem_pool_structure *nextPool;
77 uint8_t *pHeap;
78 uint32_t heapSize;
79 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
80 uint16_t allocatedBlocksPeak;
81 uint16_t poolFragmentWaste;
82 uint16_t poolTotalFragmentWaste;
83 uint16_t poolFragmentWastePeak;
84 uint16_t poolFragmentMinWaste;
85 #endif /*MEM_MANAGER_ENABLE_TRACE*/
86 uint16_t poolId;
87 uint16_t blockSize;
88 uint16_t numBlocks;
89 uint16_t allocatedBlocks;
90 } mem_pool_structure_t;
91
92 /*! @brief Header description for buffers.*/
93 typedef struct _block_list_header
94 {
95 uint16_t allocated;
96 uint16_t blockSize;
97 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
98 uint32_t caller;
99 uint16_t allocatedBytes;
100 #endif /*MEM_MANAGER_ENABLE_TRACE*/
101 } block_list_header_t;
102
103 /*! @brief State structure for memory manager. */
104 typedef struct _mem_manager_info
105 {
106 mem_pool_structure_t *pHeadPool;
107 uint16_t poolNum;
108 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
109 uint16_t allocationFailures;
110 uint16_t freeFailures;
111 #endif /*MEM_MANAGER_ENABLE_TRACE*/
112 } mem_manager_info_t;
113
114 /*****************************************************************************
115 ******************************************************************************
116 * Public memory declarations
117 ******************************************************************************
118 *****************************************************************************/
119 /*****************************************************************************
120 *****************************************************************************
121 * Private prototypes
122 *****************************************************************************
123 *****************************************************************************/
124 /*****************************************************************************
125 *****************************************************************************
126 * Private memory definitions
127 *****************************************************************************
128 *****************************************************************************/
129 static mem_manager_info_t s_memmanager = {0};
130 #ifdef MEM_STATISTICS_INTERNAL
131 static mem_statis_t s_memStatis;
132 #endif /* MEM_STATISTICS_INTERNAL */
133
134 /*****************************************************************************
135 ******************************************************************************
136 * Private API macro define
137 ******************************************************************************
138 *****************************************************************************/
139 #define BLOCK_HDR_SIZE sizeof(block_list_header_t)
140 /*****************************************************************************
141 ******************************************************************************
142 * Private functions
143 ******************************************************************************
144 *****************************************************************************/
145 #ifdef MEM_STATISTICS_INTERNAL
MEM_BufferAllocates_memStatis(void * buffer,uint32_t time,uint32_t requestedSize)146 static void MEM_BufferAllocates_memStatis(void *buffer, uint32_t time, uint32_t requestedSize)
147 {
148 block_list_header_t *pBlock = (block_list_header_t *)buffer - 1;
149 /* existing block must have a BlockHdr and a next BlockHdr */
150 assert((pBlock != NULL));
151
152 s_memStatis.nb_alloc++;
153 /* Sort the buffers by size, based on defined thresholds */
154 if (requestedSize <= SMALL_BUFFER_SIZE)
155 {
156 s_memStatis.nb_small_buffer++;
157 UPDATE_PEAK(s_memStatis.nb_small_buffer, s_memStatis.peak_small_buffer);
158 }
159 else if (requestedSize <= LARGE_BUFFER_SIZE)
160 {
161 s_memStatis.nb_medium_buffer++;
162 UPDATE_PEAK(s_memStatis.nb_medium_buffer, s_memStatis.peak_medium_buffer);
163 }
164 else
165 {
166 s_memStatis.nb_large_buffer++;
167 UPDATE_PEAK(s_memStatis.nb_large_buffer, s_memStatis.peak_large_buffer);
168 }
169 /* the RAM allocated is the buffer size and the block header size*/
170 s_memStatis.ram_allocated += (uint16_t)(requestedSize + BLOCK_HDR_SIZE);
171 UPDATE_PEAK(s_memStatis.ram_allocated, s_memStatis.peak_ram_allocated);
172
173 uint32_t block_size = 0U;
174
175 block_size = pBlock->blockSize;
176
177 assert(block_size >= requestedSize);
178 /* ram lost is the difference between block size and buffer size */
179 s_memStatis.ram_lost += (uint16_t)(block_size - requestedSize);
180 UPDATE_PEAK(s_memStatis.ram_lost, s_memStatis.peak_ram_lost);
181
182 /* UPDATE_PEAK(((uint32_t)FreeBlockHdrList.tail + BLOCK_HDR_SIZE), s_memStatis.peak_upper_addr); */
183
184 #ifdef MEM_MANAGER_BENCH
185 if (time != 0U)
186 {
187 /* update mem stats used for benchmarking */
188 s_memStatis.last_alloc_block_size = (uint16_t)block_size;
189 s_memStatis.last_alloc_buff_size = (uint16_t)requestedSize;
190 s_memStatis.last_alloc_time = (uint16_t)time;
191 s_memStatis.total_alloc_time += time;
192 s_memStatis.average_alloc_time = (uint16_t)(s_memStatis.total_alloc_time / s_memStatis.nb_alloc);
193 UPDATE_PEAK((uint16_t)time, s_memStatis.peak_alloc_time);
194 }
195 else /* alloc time is not correct, we bypass this allocation's data */
196 {
197 s_memStatis.nb_alloc--;
198 }
199 #else
200 NOT_USED(time);
201 #endif /* MEM_MANAGER_BENCH */
202 }
203
MEM_BufferFrees_memStatis(void * buffer)204 static void MEM_BufferFrees_memStatis(void *buffer)
205 {
206 block_list_header_t *pBlock = (block_list_header_t *)buffer - 1;
207 s_memStatis.ram_allocated -= (uint16_t)(pBlock->allocatedBytes + BLOCK_HDR_SIZE);
208 /* Sort the buffers by size, based on defined thresholds */
209 if (pBlock->allocatedBytes <= SMALL_BUFFER_SIZE)
210 {
211 s_memStatis.nb_small_buffer--;
212 }
213 else if (pBlock->allocatedBytes <= LARGE_BUFFER_SIZE)
214 {
215 s_memStatis.nb_medium_buffer--;
216 }
217 else
218 {
219 s_memStatis.nb_large_buffer--;
220 }
221
222 uint16_t block_size = 0U;
223 block_size = pBlock->blockSize;
224
225 assert(block_size >= pBlock->allocatedBytes);
226 assert(s_memStatis.ram_lost >= (block_size - pBlock->allocatedBytes));
227
228 /* as the buffer is free, the ram is not "lost" anymore */
229 s_memStatis.ram_lost -= (block_size - pBlock->allocatedBytes);
230 }
231 #endif
232 #if defined(MEM_STATISTICS_INTERNAL)
MEM_Reports_memStatis(void)233 static void MEM_Reports_memStatis(void)
234 {
235 MEM_DBG_LOG("**************** MEM STATS REPORT **************");
236 MEM_DBG_LOG("Nb Alloc: %d\r\n", s_memStatis.nb_alloc);
237 MEM_DBG_LOG("Small buffers: %d\r\n", s_memStatis.nb_small_buffer);
238 MEM_DBG_LOG("Medium buffers: %d\r\n", s_memStatis.nb_medium_buffer);
239 MEM_DBG_LOG("Large buffers: %d\r\n", s_memStatis.nb_large_buffer);
240 MEM_DBG_LOG("Peak small: %d\r\n", s_memStatis.peak_small_buffer);
241 MEM_DBG_LOG("Peak medium: %d\r\n", s_memStatis.peak_medium_buffer);
242 MEM_DBG_LOG("Peak large: %d\r\n", s_memStatis.peak_large_buffer);
243 MEM_DBG_LOG("Current RAM allocated: %d bytes\r\n", s_memStatis.ram_allocated);
244 MEM_DBG_LOG("Peak RAM allocated: %d bytes\r\n", s_memStatis.peak_ram_allocated);
245 MEM_DBG_LOG("Current RAM lost: %d bytes\r\n", s_memStatis.ram_lost);
246 MEM_DBG_LOG("Peak RAM lost: %d bytes\r\n", s_memStatis.peak_ram_lost);
247 MEM_DBG_LOG("Peak Upper Address: %x\r\n", s_memStatis.peak_upper_addr);
248 #ifdef MEM_MANAGER_BENCH
249 MEM_DBG_LOG("************************************************\r\n");
250 MEM_DBG_LOG("********* MEM MANAGER BENCHMARK REPORT *********\r\n");
251 MEM_DBG_LOG("Last Alloc Time: %d us\r\n", s_memStatis.last_alloc_time);
252 MEM_DBG_LOG("Last Alloc Block Size: %d bytes\r\n", s_memStatis.last_alloc_block_size);
253 MEM_DBG_LOG("Last Alloc Buffer Size: %d bytes\r\n", s_memStatis.last_alloc_buff_size);
254 MEM_DBG_LOG("Average Alloc Time: %d us\r\n", s_memStatis.average_alloc_time);
255 MEM_DBG_LOG("Peak Alloc Time: %d us\r\n", s_memStatis.peak_alloc_time);
256 #endif /* MEM_MANAGER_BENCH */
257 MEM_DBG_LOG("************************************************");
258 }
259 #endif /* MEM_STATISTICS_INTERNAL */
260
261 /*****************************************************************************
262 ******************************************************************************
263 * Public functions
264 ******************************************************************************
265 *****************************************************************************/
266 /*!
267 * @brief Initialises the Memory Manager.
268 *
269 */
MEM_Init(void)270 mem_status_t MEM_Init(void)
271 {
272 static bool initialized = false;
273 assert(sizeof(mem_pool_structure_t) == MEM_POOL_SIZE);
274 assert(sizeof(block_list_header_t) == MEM_BLOCK_SIZE);
275 if (!initialized)
276 {
277 s_memmanager.pHeadPool = NULL;
278 s_memmanager.poolNum = 0;
279 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
280 s_memmanager.allocationFailures = 0;
281 s_memmanager.freeFailures = 0;
282 #endif /*MEM_MANAGER_ENABLE_TRACE*/
283 #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U))
284 for (uint8_t i = 0; i < (sizeof(s_PoolList) / sizeof(s_PoolList[0])); i++)
285 {
286 (void)MEM_AddBuffer(s_PoolList[i]);
287 }
288 #endif /*MEM_MANAGER_PRE_CONFIGURE*/
289 initialized = true;
290 }
291 return kStatus_MemSuccess;
292 }
293
294 /*!
295 * @brief Add memory buffer to memory manager buffer list.
296 *
297 * @note This API should be called when need add memory buffer to memory manager buffer list. First use
298 * MEM_BLOCK_BUFFER_DEFINE to
299 * define memory buffer, then call MEM_AddBuffer function with MEM_BLOCK_BUFFER Macro.
300 * @code
301 * MEM_BLOCK_BUFFER_DEFINE(app64, 5, 64,0);
302 * MEM_BLOCK_BUFFER_DEFINE(app128, 6, 128,0);
303 * MEM_BLOCK_BUFFER_DEFINE(app256, 7, 256,0);
304 *
305 * MEM_AddBuffer(MEM_BLOCK_BUFFER(app64));
306 * MEM_AddBuffer(MEM_BLOCK_BUFFER(app128));
307 * MEM_AddBuffer(MEM_BLOCK_BUFFER(app256));
308 * @endcode
309 *
310 * @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter.
311 *
312 * @retval kStatus_MemSuccess Memory manager add Buffer succeed.
313 * @retval kStatus_MemInitError Memory manager add Buffer error occurred.
314 */
MEM_AddBuffer(const uint8_t * buffer)315 mem_status_t MEM_AddBuffer(const uint8_t *buffer)
316 {
317 mem_config_t *memConfig = (mem_config_t *)(void *)buffer;
318 mem_pool_structure_t *pPool = (mem_pool_structure_t *)(void *)memConfig->pbuffer;
319 uint8_t *pHeap = &memConfig->pbuffer[sizeof(mem_pool_structure_t)];
320 mem_pool_structure_t *pPrevPool, *pTempPool;
321
322 assert(buffer);
323 assert(memConfig->numberOfBlocks);
324 assert(memConfig->blockSize);
325
326 MEM_ENTER_CRITICAL();
327 #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE == 0U))
328 (void)MEM_Init();
329 #endif
330 pPool->pHeap = pHeap;
331 pPool->numBlocks = memConfig->numberOfBlocks;
332 pPool->blockSize = memConfig->blockSize;
333 pPool->poolId = *(uint16_t *)(void *)(&buffer[4]);
334 pPool->heapSize =
335 (MEM_POOL_SIZE + (uint32_t)memConfig->numberOfBlocks * (MEM_BLOCK_SIZE + (uint32_t)memConfig->blockSize));
336 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
337 pPool->allocatedBlocksPeak = 0;
338 pPool->poolTotalFragmentWaste = 0;
339 pPool->poolFragmentWaste = 0;
340 pPool->poolFragmentWastePeak = 0;
341 pPool->poolFragmentMinWaste = 0xffff;
342 #endif /*MEM_MANAGER_ENABLE_TRACE*/
343 if (s_memmanager.pHeadPool == NULL)
344 {
345 s_memmanager.pHeadPool = pPool;
346 }
347 else
348 {
349 pTempPool = s_memmanager.pHeadPool;
350 pPrevPool = pTempPool;
351 while (NULL != pTempPool)
352 {
353 if (((pPool->blockSize >= pPrevPool->blockSize) && (pPool->blockSize <= pTempPool->blockSize)) ||
354 (pPool->blockSize <= pPrevPool->blockSize))
355 {
356 if (pTempPool == s_memmanager.pHeadPool)
357 {
358 s_memmanager.pHeadPool = pPool;
359 }
360 else
361 {
362 pPrevPool->nextPool = pPool;
363 }
364 pPool->nextPool = pTempPool;
365 break;
366 }
367 pPrevPool = pTempPool;
368 pTempPool = pTempPool->nextPool;
369 }
370 if (pPool->blockSize > pPrevPool->blockSize)
371 {
372 pPrevPool->nextPool = pPool;
373 }
374 }
375
376 s_memmanager.poolNum++;
377 MEM_EXIT_CRITICAL();
378 return kStatus_MemSuccess;
379 }
380
381 /*!
382 * @brief Remove memory buffer from memory manager buffer list.
383 *
384 * @note This API should be called when need remove memory buffer to memory manager buffer list. Use with
385 * MEM_BLOCK_BUFFER Macro as input parameter.
386 *
387 * @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter.
388 *
389 * @retval kStatus_MemSuccess Memory manager remove buffer succeed.
390 * @retval kStatus_MemUnknownError Memory manager remove buffer error occurred.
391 */
392 #if (defined(MEM_MANAGER_BUFFER_REMOVE) && (MEM_MANAGER_BUFFER_REMOVE > 0U))
MEM_RemoveBuffer(uint8_t * buffer)393 mem_status_t MEM_RemoveBuffer(uint8_t *buffer)
394 {
395 mem_config_t *memConfig = (mem_config_t *)(void *)buffer;
396 mem_pool_structure_t *pPool = (mem_pool_structure_t *)(void *)memConfig->pbuffer;
397 uint8_t *pHeap = &memConfig->pbuffer[sizeof(mem_pool_structure_t)];
398 mem_pool_structure_t *pPrevPool, *pTempPool;
399
400 assert(buffer);
401 assert(memConfig->numberOfBlocks > 0U);
402 assert(memConfig->blockSize > 0U);
403
404 MEM_ENTER_CRITICAL();
405 pTempPool = s_memmanager.pHeadPool;
406 pPrevPool = pTempPool;
407 while (NULL != pTempPool)
408 {
409 if (0U != pPool->allocatedBlocks)
410 {
411 break;
412 }
413 if (pTempPool->pHeap == pHeap)
414 {
415 if (pPool == s_memmanager.pHeadPool)
416 {
417 s_memmanager.pHeadPool = pPool->nextPool;
418 }
419 else
420 {
421 pPrevPool->nextPool = pPool->nextPool;
422 }
423 s_memmanager.poolNum--;
424 MEM_EXIT_CRITICAL();
425 return kStatus_MemSuccess;
426 }
427 pPrevPool = pTempPool;
428 pTempPool = pTempPool->nextPool;
429 }
430 MEM_EXIT_CRITICAL();
431 return kStatus_MemUnknownError;
432 }
433 #endif /* MEM_MANAGER_BUFFER_REMOVE */
434
435 /*!
436 * @brief Allocate a block from the memory pools. The function uses the
437 * numBytes argument to look up a pool with adequate block sizes.
438 *
439 * @param numBytes The number of bytes will be allocated.
440 * @param poolId The ID of the pool where to search for a free buffer.
441 * @retval Memory buffer address when allocate success, NULL when allocate fail.
442 */
MEM_BufferAllocWithId(uint32_t numBytes,uint8_t poolId)443 void *MEM_BufferAllocWithId(uint32_t numBytes, uint8_t poolId)
444 {
445 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
446 uint32_t fragmentWaste = 0;
447 #endif /*MEM_MANAGER_ENABLE_TRACE*/
448 mem_pool_structure_t *pPool = s_memmanager.pHeadPool;
449 block_list_header_t *pBlock;
450 void *buffer = NULL;
451
452 MEM_ENTER_CRITICAL();
453 #ifdef MEM_MANAGER_BENCH
454 uint32_t START_TIME = 0U, STOP_TIME = 0U, ALLOC_TIME = 0U;
455 START_TIME = TM_GetTimestamp();
456 #endif /* MEM_MANAGER_BENCH */
457
458 while (0U != numBytes)
459 {
460 if ((numBytes <= pPool->blockSize) && (pPool->poolId == poolId))
461 {
462 for (uint32_t i = 0; i < pPool->numBlocks; i++)
463 {
464 pBlock = (block_list_header_t *)(void *)(pPool->pHeap + i * ((uint32_t)pPool->blockSize +
465 (uint32_t)sizeof(block_list_header_t)));
466 if (0U == pBlock->allocated)
467 {
468 pBlock->allocated = 1;
469 pBlock->blockSize = pPool->blockSize;
470 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
471 pBlock->allocatedBytes = (uint16_t)numBytes;
472 pBlock->caller = (uint32_t)((uint32_t *)__mem_get_LR());
473 #endif /*MEM_MANAGER_ENABLE_TRACE*/
474 pBlock++;
475 pPool->allocatedBlocks++;
476 buffer = pBlock;
477 (void)memset(buffer, 0x0, pBlock->blockSize);
478 break;
479 }
480 }
481 }
482 if (NULL != buffer)
483 {
484 break;
485 }
486 /* Try next pool*/
487 pPool = pPool->nextPool;
488 if (NULL == pPool)
489 {
490 break;
491 }
492 }
493 #ifdef MEM_MANAGER_BENCH
494 STOP_TIME = TM_GetTimestamp();
495 ALLOC_TIME = STOP_TIME - START_TIME;
496 #endif /* MEM_MANAGER_BENCH */
497 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
498 if (NULL == buffer)
499 {
500 s_memmanager.allocationFailures++;
501 }
502 #endif /*MEM_MANAGER_ENABLE_TRACE*/
503
504 #ifdef MEM_STATISTICS_INTERNAL
505 #ifdef MEM_MANAGER_BENCH
506 MEM_BufferAllocates_memStatis(buffer, ALLOC_TIME, numBytes);
507 #else
508 MEM_BufferAllocates_memStatis(buffer, 0, numBytes);
509 #endif
510
511 if ((s_memStatis.nb_alloc % NB_ALLOC_REPORT_THRESHOLD) == 0U)
512 {
513 MEM_Reports_memStatis();
514 }
515 #endif /* MEM_STATISTICS_INTERNAL */
516 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
517 if (pPool->allocatedBlocks > pPool->allocatedBlocksPeak)
518 {
519 pPool->allocatedBlocksPeak = pPool->allocatedBlocks;
520 }
521 fragmentWaste = pPool->blockSize - numBytes;
522 if (fragmentWaste > pPool->poolFragmentWastePeak)
523 {
524 pPool->poolFragmentWastePeak = (uint16_t)fragmentWaste;
525 }
526 pPool->poolFragmentWaste = (uint16_t)fragmentWaste;
527 pPool->poolTotalFragmentWaste += (uint16_t)fragmentWaste;
528 if (fragmentWaste < pPool->poolFragmentMinWaste)
529 {
530 pPool->poolFragmentMinWaste = (uint16_t)fragmentWaste;
531 }
532 #endif /*MEM_MANAGER_ENABLE_TRACE*/
533 MEM_EXIT_CRITICAL();
534 return buffer;
535 }
536
537 /*!
538 * @brief Memory buffer free.
539 *
540 * @param buffer The memory buffer address will be free.
541 * @retval kStatus_MemSuccess Memory free succeed.
542 * @retval kStatus_MemFreeError Memory free error occurred.
543 */
MEM_BufferFree(void * buffer)544 mem_status_t MEM_BufferFree(void *buffer /* IN: Block of memory to free*/
545 )
546 {
547 block_list_header_t *pBlock;
548 mem_pool_structure_t *pPool = s_memmanager.pHeadPool;
549 MEM_ENTER_CRITICAL();
550
551 do
552 {
553 if (NULL == buffer)
554 {
555 break;
556 }
557 #if defined(MEM_STATISTICS_INTERNAL)
558 MEM_BufferFrees_memStatis(buffer);
559 #endif /* MEM_STATISTICS_INTERNAL */
560 pBlock = (block_list_header_t *)buffer - 1;
561 assert(pBlock);
562 if (1U == pBlock->allocated)
563 {
564 (void)memset(pBlock, 0x0, (sizeof(block_list_header_t) + (uint32_t)pBlock->blockSize));
565 MEM_EXIT_CRITICAL();
566 while (true)
567 {
568 if (((uint32_t)pPool->pHeap <= (uint32_t)pBlock) &&
569 ((uint32_t)pBlock <
570 (uint32_t)pPool->pHeap +
571 pPool->numBlocks * ((uint32_t)pPool->blockSize + (uint32_t)sizeof(block_list_header_t))))
572 {
573 pPool->allocatedBlocks--;
574 return kStatus_MemSuccess;
575 }
576 pPool = pPool->nextPool;
577 if (NULL == pPool)
578 {
579 return kStatus_MemFreeError;
580 }
581 }
582 }
583
584 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
585 s_memmanager.freeFailures++;
586 #endif /*MEM_MANAGER_ENABLE_TRACE*/
587
588 } while (false);
589
590 MEM_EXIT_CRITICAL();
591 return kStatus_MemFreeError;
592 }
593
594 /*!
595 * @brief Returns the size of a given buffer.
596 *
597 * @param buffer The memory buffer address will be free.
598 * @retval The size of a given buffer.
599 */
MEM_BufferGetSize(void * buffer)600 uint16_t MEM_BufferGetSize(void *buffer) /* IN: Block of memory to get size*/
601 {
602 block_list_header_t *pBlock;
603 assert(buffer);
604
605 pBlock = (block_list_header_t *)buffer - 1;
606 assert(pBlock);
607
608 return pBlock->blockSize;
609 }
610
611 /*!
612 * @brief Frees all allocated blocks by selected source and in selected pool.
613 *
614 * @param poolId Selected pool Id (4 LSBs of poolId parameter) and selected
615 * source Id (4 MSBs of poolId parameter).
616 * @retval kStatus_MemSuccess Memory free succeed.
617 * @retval kStatus_MemFreeError Memory free error occurred.
618 */
MEM_BufferFreeAllWithId(uint8_t poolId)619 mem_status_t MEM_BufferFreeAllWithId(uint8_t poolId)
620 {
621 mem_pool_structure_t *pPool = s_memmanager.pHeadPool;
622
623 MEM_ENTER_CRITICAL();
624
625 while (pPool != NULL)
626 {
627 if (pPool->poolId == poolId)
628 {
629 (void)memset(pPool->pHeap, 0x0,
630 ((sizeof(block_list_header_t) + (uint32_t)pPool->blockSize) * pPool->numBlocks));
631 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
632 pPool->allocatedBlocksPeak = 0;
633 pPool->poolTotalFragmentWaste = 0;
634 pPool->poolFragmentWaste = 0;
635 pPool->poolFragmentWastePeak = 0;
636 pPool->poolFragmentMinWaste = 0xffff;
637 #endif /*MEM_MANAGER_ENABLE_TRACE*/
638 pPool->allocatedBlocks = 0;
639 }
640 pPool = pPool->nextPool;
641 }
642
643 MEM_EXIT_CRITICAL();
644 return kStatus_MemSuccess;
645 }
646
647 /*!
648 * @brief Memory buffer realloc.
649 *
650 * @param buffer The memory buffer address will be reallocated.
651 * @param new_size The number of bytes will be reallocated
652 * @retval kStatus_MemSuccess Memory free succeed.
653 * @retval kStatus_MemFreeError Memory free error occurred.
654 */
MEM_BufferRealloc(void * buffer,uint32_t new_size)655 void *MEM_BufferRealloc(void *buffer, uint32_t new_size)
656 {
657 void *realloc_buffer = NULL;
658 uint16_t block_size = 0U;
659
660 if (new_size == 0U)
661 {
662 /* new requested size is 0, free old buffer */
663 (void)MEM_BufferFree(buffer);
664 realloc_buffer = NULL;
665 }
666 else if (buffer == NULL)
667 {
668 /* input buffer is NULL simply allocate a new buffer and return it */
669 realloc_buffer = MEM_BufferAllocWithId(new_size, 0U);
670 }
671 else
672 {
673 block_size = MEM_BufferGetSize(buffer);
674
675 if ((uint16_t)new_size <= block_size)
676 {
677 /* current buffer is large enough for the new requested size
678 we can still use it */
679 realloc_buffer = buffer;
680 }
681 else
682 {
683 /* not enough space in the current block, creating a new one */
684 realloc_buffer = MEM_BufferAllocWithId(new_size, 0U);
685
686 if (realloc_buffer != NULL)
687 {
688 /* copy input buffer data to new buffer */
689 (void)memcpy(realloc_buffer, buffer, (uint32_t)block_size);
690
691 /* free old buffer */
692 (void)MEM_BufferFree(buffer);
693 }
694 }
695 }
696
697 return realloc_buffer;
698 }
699
700 /*!
701 * @brief Get the address after the last allocated block if MemManagerLight is used.
702 *
703 * @retval 0 Return 0 in case of the legacy MemManager.
704 */
MEM_GetHeapUpperLimit(void)705 uint32_t MEM_GetHeapUpperLimit(void)
706 {
707 return 0U;
708 }
709
710 /*!
711 * @brief Get the free space in the heap.
712 *
713 * @retval 0 Return 0 in case of the legacy MemManager.
714 */
MEM_GetFreeHeapSize(void)715 uint32_t MEM_GetFreeHeapSize(void)
716 {
717 return 0U;
718 }
719
720 /*!
721 * @brief Trace memory manager all information to use debug.
722 *
723 */
724 #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
MEM_Trace(void)725 void MEM_Trace(void)
726 {
727 mem_pool_structure_t *pPool = s_memmanager.pHeadPool;
728 block_list_header_t *pBlock;
729 (void)PRINTF("MEM_Trace debug information, Pools Number:%d allocationFailures: %d freeFailures:%d\r\n",
730 s_memmanager.poolNum, s_memmanager.allocationFailures, s_memmanager.allocationFailures,
731 s_memmanager.freeFailures);
732 while (NULL != pPool)
733 {
734 (void)PRINTF("POOL: ID %d blockSize:%d status:\r\n", pPool->poolId, pPool->blockSize);
735 (void)PRINTF(
736 "numBlocks allocatedBlocks allocatedBlocksPeak poolFragmentWaste poolFragmentWastePeak "
737 "poolFragmentMinWaste poolTotalFragmentWaste\r\n");
738 (void)PRINTF(
739 " %d %d %d %d %d %d "
740 " %d\r\n",
741 pPool->numBlocks, pPool->allocatedBlocks, pPool->allocatedBlocksPeak, pPool->poolFragmentWaste,
742 pPool->poolFragmentWastePeak, pPool->poolFragmentMinWaste, pPool->poolTotalFragmentWaste);
743 (void)PRINTF("Currently pool meory block allocate status:\r\n");
744 for (uint32_t i = 0; i < pPool->numBlocks; i++)
745 {
746 pBlock = (block_list_header_t *)(void *)(pPool->pHeap +
747 i * ((uint32_t)pPool->blockSize + sizeof(block_list_header_t)));
748
749 (void)PRINTF("Block %d caller : 0x%x Allocated %d bytes: %d\r\n", i, pBlock->caller, pBlock->allocated,
750 pBlock->allocatedBytes);
751 }
752 /* Try next pool*/
753 pPool = pPool->nextPool;
754 }
755 }
756 #endif /*MEM_MANAGER_ENABLE_TRACE*/
757 #endif /*gMemManagerLight*/
758