Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of fsl_phy_mcr20a by
MemManager.c
00001 /*! 00002 * Copyright (c) 2015, Freescale Semiconductor, Inc. 00003 * All rights reserved. 00004 * 00005 * \file MemManager.c 00006 * This is the source file for the Memory Manager. 00007 * 00008 * Redistribution and use in source and binary forms, with or without modification, 00009 * are permitted provided that the following conditions are met: 00010 * 00011 * o Redistributions of source code must retain the above copyright notice, this list 00012 * of conditions and the following disclaimer. 00013 * 00014 * o Redistributions in binary form must reproduce the above copyright notice, this 00015 * list of conditions and the following disclaimer in the documentation and/or 00016 * other materials provided with the distribution. 00017 * 00018 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its 00019 * contributors may be used to endorse or promote products derived from this 00020 * software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00024 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00025 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00026 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00027 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00029 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00030 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 */ 00033 00034 00035 /*! ********************************************************************************* 00036 ************************************************************************************* 00037 * Include 00038 ************************************************************************************* 00039 ********************************************************************************** */ 00040 #include "EmbeddedTypes.h " 00041 #include "mbedAbstraction.h" 00042 #include "fsl_os_abstraction.h" 00043 #ifdef MEM_DEBUG 00044 #include "Panic.h" 00045 #endif 00046 #include "MemManager.h " 00047 00048 00049 /*! ********************************************************************************* 00050 ************************************************************************************* 00051 * Private memory declarations 00052 ************************************************************************************* 00053 ********************************************************************************** */ 00054 00055 #define _block_size_ { 00056 #define _number_of_blocks_ , 00057 #define _eol_ }, 00058 00059 poolInfo_t poolInfo[] = 00060 { 00061 PoolsDetails_c 00062 {0, 0} /*termination tag*/ 00063 }; 00064 00065 #undef _block_size_ 00066 #undef _number_of_blocks_ 00067 #undef _eol_ 00068 00069 #define _block_size_ (sizeof(listHeader_t)+ 00070 #define _number_of_blocks_ ) * 00071 #define _eol_ + 00072 00073 #define heapSize_c (PoolsDetails_c 0) 00074 00075 // Heap 00076 uint8_t memHeap[heapSize_c]; 00077 const uint32_t heapSize = heapSize_c; 00078 00079 #undef _block_size_ 00080 #undef _number_of_blocks_ 00081 #undef _eol_ 00082 00083 #define _block_size_ 0 * 00084 #define _number_of_blocks_ + 0 * 00085 #define _eol_ + 1 + 00086 00087 #define poolCount (PoolsDetails_c 0) 00088 00089 // Memory pool info and anchors. 00090 pools_t memPools[poolCount]; 00091 00092 #undef _block_size_ 00093 #undef _number_of_blocks_ 00094 #undef _eol_ 00095 00096 #ifdef MEM_TRACKING 00097 00098 #define _block_size_ 0* 00099 #define _number_of_blocks_ + 00100 #define _eol_ + 00101 00102 #define mTotalNoOfMsgs_d (PoolsDetails_c 0) 00103 static const uint16_t mTotalNoOfMsgs_c = mTotalNoOfMsgs_d; 00104 blockTracking_t memTrack[mTotalNoOfMsgs_d]; 00105 00106 #undef _block_size_ 00107 #undef _number_of_blocks_ 00108 #undef _eol_ 00109 00110 #endif /*MEM_TRACKING*/ 00111 00112 // Free messages counter. Not used by module. 00113 uint16_t gFreeMessagesCount; 00114 00115 /*! ********************************************************************************* 00116 ************************************************************************************* 00117 * Public functions 00118 ************************************************************************************* 00119 ********************************************************************************** */ 00120 00121 /*! ********************************************************************************* 00122 * \brief This function initializes the message module private variables. 00123 * Must be called at boot time, or if device is reset. 00124 * 00125 * \param[in] none 00126 * 00127 * \return MEM_SUCCESS_c if initialization is successful. (It's always successful). 00128 * 00129 ********************************************************************************** */ 00130 memStatus_t MEM_Init() 00131 { 00132 poolInfo_t *pPoolInfo = poolInfo; // IN: Memory layout information 00133 pools_t *pPools = memPools;// OUT: Will be initialized with requested memory pools. 00134 uint8_t *pHeap = memHeap;// IN: Memory heap. 00135 uint8_t poolN; 00136 #ifdef MEM_TRACKING 00137 uint16_t memTrackIndex = 0; 00138 #endif /*MEM_TRACKING*/ 00139 00140 gFreeMessagesCount = 0; 00141 00142 for(;;) 00143 { 00144 poolN = pPoolInfo->poolSize; 00145 ListInit((listHandle_t)&pPools->anchor, poolN); 00146 #ifdef MEM_STATISTICS 00147 pPools->poolStatistics.numBlocks = 0; 00148 pPools->poolStatistics.allocatedBlocks = 0; 00149 pPools->poolStatistics.allocatedBlocksPeak = 0; 00150 pPools->poolStatistics.allocationFailures = 0; 00151 pPools->poolStatistics.freeFailures = 0; 00152 #ifdef MEM_TRACKING 00153 pPools->poolStatistics.poolFragmentWaste = 0; 00154 pPools->poolStatistics.poolFragmentWastePeak = 0; 00155 #endif /*MEM_TRACKING*/ 00156 #endif /*MEM_STATISTICS*/ 00157 00158 while(poolN) 00159 { 00160 // Add block to list of free memory. 00161 ListAddTail((listHandle_t)&pPools->anchor, (listElementHandle_t)&((listHeader_t *)pHeap)->link); 00162 ((listHeader_t *)pHeap)->pParentPool = pPools; 00163 #ifdef MEM_STATISTICS 00164 pPools->poolStatistics.numBlocks++; 00165 #endif /*MEM_STATISTICS*/ 00166 00167 gFreeMessagesCount++; 00168 #ifdef MEM_TRACKING 00169 memTrack[memTrackIndex].blockAddr = (void *)(pHeap + sizeof(listHeader_t)); 00170 memTrack[memTrackIndex].blockSize = pPoolInfo->blockSize; 00171 memTrack[memTrackIndex].fragmentWaste = 0; 00172 memTrack[memTrackIndex].allocAddr = NULL; 00173 memTrack[memTrackIndex].allocCounter = 0; 00174 memTrack[memTrackIndex].allocStatus = MEM_TRACKING_FREE_c; 00175 memTrack[memTrackIndex].freeAddr = NULL; 00176 memTrack[memTrackIndex].freeCounter = 0; 00177 memTrackIndex++; 00178 #endif /*MEM_TRACKING*/ 00179 00180 // Add block size (without list header) 00181 pHeap += pPoolInfo->blockSize + sizeof(listHeader_t); 00182 poolN--; 00183 } 00184 00185 pPools->blockSize = pPoolInfo->blockSize; 00186 pPools->nextBlockSize = (pPoolInfo+1)->blockSize; 00187 if(pPools->nextBlockSize == 0) 00188 { 00189 break; 00190 } 00191 00192 pPools++; 00193 pPoolInfo++; 00194 } 00195 return MEM_SUCCESS_c; 00196 } 00197 00198 /*! ********************************************************************************* 00199 * \brief This function returns the number of available blocks greater or 00200 * equal to the given size. 00201 * 00202 * \param[in] size - Size of blocks to check for availability. 00203 * 00204 * \return Number of available blocks greater or equal to the given size. 00205 * 00206 * \pre Memory manager must be previously initialized. 00207 * 00208 ********************************************************************************** */ 00209 uint32_t MEM_GetAvailableBlocks 00210 ( 00211 uint32_t size 00212 ) 00213 { 00214 pools_t *pPools = memPools; 00215 uint32_t pTotalCount = 0; 00216 00217 for(;;) 00218 { 00219 if(size <= pPools->blockSize) 00220 { 00221 pTotalCount += ListGetSize((listHandle_t)&pPools->anchor); 00222 } 00223 00224 if(pPools->nextBlockSize == 0) 00225 { 00226 break; 00227 } 00228 00229 pPools++; 00230 } 00231 00232 return pTotalCount; 00233 } 00234 00235 /*! ********************************************************************************* 00236 * \brief Allocate a block from the memory pools. The function uses the 00237 * numBytes argument to look up a pool with adequate block sizes. 00238 * \param[in] numBytes - Size of buffer to allocate. 00239 * 00240 * \return Pointer to the allocated buffer, NULL if failed. 00241 * 00242 * \pre Memory manager must be previously initialized. 00243 * 00244 ********************************************************************************** */ 00245 void* MEM_BufferAlloc 00246 ( 00247 uint32_t numBytes // IN: Minimum number of bytes to allocate 00248 ) 00249 { 00250 #ifdef MEM_TRACKING 00251 00252 /* Save the Link Register */ 00253 volatile uint32_t savedLR; 00254 // __asm("str r14, [SP]"); 00255 __asm("push {r2} "); 00256 __asm("push {LR} "); 00257 __asm("pop {r2} "); 00258 __asm("str r2, [SP, #4]"); 00259 __asm("pop {r2}"); 00260 00261 #endif /*MEM_TRACKING*/ 00262 00263 pools_t *pPools = memPools; 00264 listHeader_t *pBlock; 00265 00266 #ifdef MEM_TRACKING 00267 uint16_t requestedSize = numBytes; 00268 #endif /*MEM_TRACKING*/ 00269 00270 OSA_EnterCritical(kCriticalDisableInt); 00271 00272 while(numBytes) 00273 { 00274 if(numBytes <= pPools->blockSize) 00275 { 00276 pBlock = (listHeader_t *)ListRemoveHead((listHandle_t)&pPools->anchor); 00277 00278 if(NULL != pBlock) 00279 { 00280 pBlock++; 00281 gFreeMessagesCount--; 00282 00283 #ifdef MEM_STATISTICS 00284 pPools->poolStatistics.allocatedBlocks++; 00285 if ( pPools->poolStatistics.allocatedBlocks > pPools->poolStatistics.allocatedBlocksPeak ) 00286 { 00287 pPools->poolStatistics.allocatedBlocksPeak = pPools->poolStatistics.allocatedBlocks; 00288 } 00289 MEM_ASSERT(pPools->poolStatistics.allocatedBlocks <= pPools->poolStatistics.numBlocks); 00290 #endif /*MEM_STATISTICS*/ 00291 00292 #ifdef MEM_TRACKING 00293 MEM_Track(pBlock, MEM_TRACKING_ALLOC_c, savedLR, requestedSize); 00294 #endif /*MEM_TRACKING*/ 00295 OSA_ExitCritical(kCriticalDisableInt); 00296 return pBlock; 00297 } 00298 else 00299 { 00300 if(numBytes > pPools->nextBlockSize) break; 00301 // No more blocks of that size, try next size. 00302 numBytes = pPools->nextBlockSize; 00303 } 00304 } 00305 // Try next pool 00306 if(pPools->nextBlockSize) 00307 pPools++; 00308 else 00309 break; 00310 } 00311 #ifdef MEM_STATISTICS 00312 pPools->poolStatistics.allocationFailures++; 00313 #endif /*MEM_STATISTICS*/ 00314 00315 #ifdef MEM_DEBUG 00316 panic( 0, (uint32_t)MEM_BufferAlloc, 0, 0); 00317 #endif 00318 00319 OSA_ExitCritical(kCriticalDisableInt); 00320 return NULL; 00321 } 00322 00323 /*! ********************************************************************************* 00324 * \brief Deallocate a memory block by putting it in the corresponding pool 00325 * of free blocks. 00326 * 00327 * \param[in] buffer - Pointer to buffer to deallocate. 00328 * 00329 * \return MEM_SUCCESS_c if deallocation was successful, MEM_FREE_ERROR_c if not. 00330 * 00331 * \pre Memory manager must be previously initialized. 00332 * 00333 * \remarks Never deallocate the same buffer twice. 00334 * 00335 ********************************************************************************** */ 00336 memStatus_t MEM_BufferFree 00337 ( 00338 void* buffer // IN: Block of memory to free 00339 ) 00340 { 00341 #ifdef MEM_TRACKING 00342 00343 /* Save the Link Register */ 00344 volatile uint32_t savedLR; 00345 // __asm("str r14, [SP]"); 00346 __asm("push {r1} "); 00347 __asm("push {LR} "); 00348 __asm("pop {r1} "); 00349 __asm("str r1, [SP, #4]"); 00350 __asm("pop {r1}"); 00351 #endif /*MEM_TRACKING*/ 00352 00353 if(buffer == NULL) 00354 { 00355 return MEM_FREE_ERROR_c; 00356 } 00357 00358 OSA_EnterCritical(kCriticalDisableInt); 00359 00360 listHeader_t *pHeader = (listHeader_t *)buffer-1; 00361 pools_t *pParentPool = (pools_t *)pHeader->pParentPool; 00362 00363 pools_t *pool = memPools; 00364 for(;;) 00365 { 00366 if (pParentPool == pool) 00367 break; 00368 if(pool->nextBlockSize == 0) 00369 { 00370 /* The parent pool was not found! This means that the memory buffer is corrupt or 00371 that the MEM_BufferFree() function was called with an invalid parameter */ 00372 #ifdef MEM_STATISTICS 00373 pParentPool->poolStatistics.freeFailures++; 00374 #endif /*MEM_STATISTICS*/ 00375 OSA_ExitCritical(kCriticalDisableInt); 00376 return MEM_FREE_ERROR_c; 00377 } 00378 pool++; 00379 } 00380 00381 if( pHeader->link.list != NULL ) 00382 { 00383 /* The memory buffer appears to be enqueued in a linked list. 00384 This list may be the free memory buffers pool, or another list. */ 00385 #ifdef MEM_STATISTICS 00386 pParentPool->poolStatistics.freeFailures++; 00387 #endif /*MEM_STATISTICS*/ 00388 OSA_ExitCritical(kCriticalDisableInt); 00389 return MEM_FREE_ERROR_c; 00390 } 00391 00392 gFreeMessagesCount++; 00393 00394 ListAddTail((listHandle_t)&pParentPool->anchor, (listElementHandle_t)&pHeader->link); 00395 00396 #ifdef MEM_STATISTICS 00397 MEM_ASSERT(pParentPool->poolStatistics.allocatedBlocks > 0); 00398 pParentPool->poolStatistics.allocatedBlocks--; 00399 #endif /*MEM_STATISTICS*/ 00400 00401 #ifdef MEM_TRACKING 00402 MEM_Track(buffer, MEM_TRACKING_FREE_c, savedLR, 0); 00403 #endif /*MEM_TRACKING*/ 00404 OSA_ExitCritical(kCriticalDisableInt); 00405 return MEM_SUCCESS_c; 00406 } 00407 00408 /*! ********************************************************************************* 00409 * \brief Determines the size of a memory block 00410 * 00411 * \param[in] buffer - Pointer to buffer. 00412 * 00413 * \return size of memory block 00414 * 00415 * \pre Memory manager must be previously initialized. 00416 * 00417 ********************************************************************************** */ 00418 uint16_t MEM_BufferGetSize 00419 ( 00420 void* buffer // IN: Block of memory to free 00421 ) 00422 { 00423 if( buffer ) 00424 { 00425 return ((pools_t *)((listHeader_t *)buffer-1)->pParentPool)->blockSize; 00426 } 00427 00428 return 0; 00429 } 00430 00431 /*! ********************************************************************************* 00432 ************************************************************************************* 00433 * Private functions 00434 ************************************************************************************* 00435 ********************************************************************************** */ 00436 /*! ********************************************************************************* 00437 * \brief This function updates the tracking array element corresponding to the given 00438 * block. 00439 * 00440 * \param[in] block - Pointer to the block. 00441 * \param[in] alloc - Indicates whether an allocation or free operation was performed 00442 * \param[in] address - Address where MEM_BufferAlloc or MEM_BufferFree was called 00443 * \param[in] requestedSize - Indicates the requested buffer size passed to MEM_BufferAlloc. 00444 * Has no use if a free operation was performed. 00445 * 00446 * \return Returns TRUE if correct allocation or dealocation was performed, FALSE if a 00447 * buffer was allocated or freed twice. 00448 * 00449 ********************************************************************************** */ 00450 #ifdef MEM_TRACKING 00451 uint8_t MEM_Track(listHeader_t *block, memTrackingStatus_t alloc, uint32_t address, uint16_t requestedSize) 00452 { 00453 uint16_t i; 00454 blockTracking_t *pTrack = NULL; 00455 #ifdef MEM_STATISTICS 00456 poolStat_t * poolStatistics = (poolStat_t *)&((pools_t *)( (listElementHandle_t)(block-1)->pParentPool ))->poolStatistics; 00457 #endif 00458 00459 for( i=0; i<mTotalNoOfMsgs_c; i++ ) 00460 { 00461 if( block == memTrack[i].blockAddr ) 00462 { 00463 pTrack = &memTrack[i]; 00464 break; 00465 } 00466 } 00467 00468 if( !pTrack || pTrack->allocStatus == alloc) 00469 { 00470 #ifdef MEM_DEBUG 00471 panic( 0, (uint32_t)MEM_Track, 0, 0); 00472 #endif 00473 return FALSE; 00474 } 00475 00476 pTrack->allocStatus = alloc; 00477 00478 if(alloc == MEM_TRACKING_ALLOC_c) 00479 { 00480 pTrack->fragmentWaste = pTrack->blockSize - requestedSize; 00481 pTrack->allocCounter++; 00482 pTrack->allocAddr = (void *)address; 00483 #ifdef MEM_STATISTICS 00484 00485 poolStatistics->poolFragmentWaste += pTrack->fragmentWaste; 00486 if(poolStatistics->poolFragmentWaste > poolStatistics->poolFragmentWastePeak) 00487 poolStatistics->poolFragmentWastePeak = poolStatistics->poolFragmentWaste; 00488 #endif /*MEM_STATISTICS*/ 00489 } 00490 else 00491 { 00492 #ifdef MEM_STATISTICS 00493 poolStatistics->poolFragmentWaste -= pTrack->fragmentWaste; 00494 #endif /*MEM_STATISTICS*/ 00495 pTrack->fragmentWaste = 0; 00496 pTrack->freeCounter++; 00497 pTrack->freeAddr = (void *)address; 00498 } 00499 00500 return TRUE; 00501 } 00502 00503 /*! ********************************************************************************* 00504 * \brief This function checks for buffer overflow when copying multiple bytes 00505 * 00506 * \param[in] p - pointer to destination. 00507 * \param[in] size - number of bytes to copy 00508 * 00509 * \return 1 if overflow detected, else 0 00510 * 00511 ********************************************************************************** */ 00512 uint8_t MEM_BufferCheck(uint8_t *p, uint32_t size) 00513 { 00514 uint32_t i; 00515 00516 if( (p < (uint8_t*)memHeap) || (p > ((uint8_t*)memHeap + sizeof(memHeap))) ) 00517 return 0; 00518 00519 for(i=0; i<mTotalNoOfMsgs_c-1; i++) 00520 { 00521 if( p > (uint8_t*)memTrack[i].blockAddr && 00522 p < (uint8_t*)memTrack[i+1].blockAddr ) 00523 { 00524 if( (p+size) > ((uint8_t*)memTrack[i+1].blockAddr - sizeof(listHeader_t)) ) 00525 { 00526 #ifdef MEM_DEBUG 00527 panic(0,0,0,0); 00528 #endif 00529 return 1; 00530 } 00531 00532 break; 00533 } 00534 } 00535 return 0; 00536 } 00537 #endif /*MEM_TRACKING*/ 00538 00539 /*! ********************************************************************************* 00540 * \brief Performs a write-read-verify test for every byte in all memory pools. 00541 * 00542 * \return Returns MEM_SUCCESS_c if test was successful, MEM_ALLOC_ERROR_c if a 00543 * buffer was not allocated successufuly, MEM_FREE_ERROR_c if a 00544 * buffer was not freed successufuly or MEM_UNKNOWN_ERROR_c if a verify error, 00545 * heap overflow or data corruption occurred. 00546 * 00547 ********************************************************************************** */ 00548 uint32_t MEM_WriteReadTest(void) 00549 { 00550 uint8_t *data, count = 1; 00551 uint32_t idx1,idx2,idx3; 00552 uint32_t freeMsgs; 00553 00554 /*memory write test*/ 00555 freeMsgs = MEM_GetAvailableBlocks(0); 00556 00557 for(idx1=0; poolInfo[idx1].blockSize != 0; idx1++) 00558 { 00559 for(idx2=0; idx2 < poolInfo[idx1].poolSize; idx2++) 00560 { 00561 data = (uint8_t *)MEM_BufferAlloc(poolInfo[idx1].blockSize); 00562 00563 if(data == NULL) 00564 { 00565 return MEM_ALLOC_ERROR_c; 00566 } 00567 00568 for(idx3=0; idx3 < poolInfo[idx1].blockSize; idx3++) 00569 { 00570 if(data > memHeap + heapSize) 00571 { 00572 return MEM_UNKNOWN_ERROR_c; 00573 } 00574 *data = count & 0xff; 00575 data++; 00576 } 00577 count++; 00578 } 00579 } 00580 00581 count = 1; 00582 data = memHeap; 00583 /*memory read test*/ 00584 for(idx1=0; poolInfo[idx1].blockSize != 0; idx1++) 00585 { 00586 for(idx2=0; idx2 < poolInfo[idx1].poolSize; idx2++) 00587 { 00588 /*New block; jump over list header*/ 00589 data = data + sizeof(listHeader_t); 00590 for(idx3=0; idx3<poolInfo[idx1].blockSize; idx3++) 00591 { 00592 if(*data == count) 00593 { 00594 data++; 00595 } 00596 else 00597 { 00598 return MEM_UNKNOWN_ERROR_c; 00599 } 00600 } 00601 if(MEM_BufferFree( data - poolInfo[idx1].blockSize) != MEM_SUCCESS_c) 00602 { 00603 return MEM_FREE_ERROR_c; 00604 } 00605 count++; 00606 } 00607 } 00608 if(MEM_GetAvailableBlocks(0) != freeMsgs) 00609 { 00610 return MEM_UNKNOWN_ERROR_c; 00611 } 00612 #ifdef MEM_STATISTICS 00613 for(idx1 = 0; poolInfo[idx1].blockSize != 0; idx1++) 00614 { 00615 memPools[idx1].poolStatistics.allocatedBlocksPeak = 0; 00616 } 00617 #endif /*MEM_STATISTICS*/ 00618 00619 return MEM_SUCCESS_c; 00620 }
Generated on Fri Jul 15 2022 21:41:17 by
