目录
基于freertos的嵌入式系统开发(七)FreeRTOS的内存管理方法5
简介
freertos的内存管理方法5是最后一种内存管理方法,也是最复杂的一种,方法5在方法4的基础上,允许内存堆跨越多个不连续的内存段,这就为使用了扩展内存的处理器使用扩展ramm作为cpu的heap空间提供了可能,所以,在方法5中,首先需要定义heap内存段:例如:某处理器内部ram为128k,地址为0x8000开始,另外扩展了256k的ram,地址为0x100000开始,这些内存全部作为heap的内存块供freertos使用,则heap的内存段定义如下:
HeapRegion_t xHeapRegions[]=
{
{(uint8_t *)0x8000UL,0x20000}, //内部 RAM,内存起始地址 0x8000 大小128KB
{(uint8_t *)0x10000UL,0x40000},//外部SRAM,内存起始地址 0x68000000 大小1MB
{NULL,0} //数组结尾
};
最后,freertos的实际的heap大小是HeapRegion_t 定义的几个区间的总和,如下图:。
其中LEN0=128k,LEN1=256k。
内存申请函数void * pvPortMalloc( size_t xWantedSize )
该函数和方法4是一致的,详细请参考
基于freertos的嵌入式系统开发(六)FreeRTOS的内存管理方法4的文章:
链接: [link](https://blog.csdn.net/cyjbj/article/details/127031092?spm=1001.2014.3001.5501)
内存释放函数void vPortFree( void * pv )
该函数和方法4是一致的,详细请参考
基于freertos的嵌入式系统开发(六)FreeRTOS的内存管理方法4的文章:
链接: [link](https://blog.csdn.net/cyjbj/article/details/127031092?spm=1001.2014.3001.5501)
空闲内存块管理函数static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )该函数和方法4是一致的,详细请参考
基于freertos的嵌入式系统开发(六)FreeRTOS的内存管理方法4的文章:
链接: [link](https://blog.csdn.net/cyjbj/article/details/127031092?spm=1001.2014.3001.5501)
堆区域管理函数void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
该函数是方法5和方法4区别的地方,在方法4中,heap的BlockLink_t 链表是在一块连续的内存上,而在方法5中,BlockLink_t 链表是建立在HeapRegion_t定义的几块连续内存上的。方法4将多块不连续内存用链表串成一整块内存,再用方法4的pvPortMalloc和vPortFree来分配和释放内存。方法5需要vPortDefineHeapRegions把多块不连续内存串成一块初始化。
下面看代码:
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
{
BlockLink_t * pxFirstFreeBlockInRegion = NULL, * pxPreviousFreeBlock;
size_t xAlignedHeap;
size_t xTotalRegionSize, xTotalHeapSize = 0;
BaseType_t xDefinedRegions = 0;
size_t xAddress;
const HeapRegion_t * pxHeapRegion;
/* Can only call once!
强调必须被显式的调用,而且只能调用一次*/
configASSERT( pxEnd == NULL );
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
while( pxHeapRegion->xSizeInBytes > 0 )
/* 大于0说明是有效的内存区域定义,这就是 HeapRegion_t 中定义 {NULL,0} 为数组结尾 的原因*/
{
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
/* Ensure the heap region starts on a correctly aligned boundary.
确保内存起始地址按照字节对齐*/
xAddress = ( size_t ) pxHeapRegion->pucStartAddress;
if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
{
xAddress += ( portBYTE_ALIGNMENT - 1 );
xAddress &= ~portBYTE_ALIGNMENT_MASK; //内存已分配标识清零
/* Adjust the size for the bytes lost to alignment. */
xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress;
}
xAlignedHeap = xAddress;
/* Set xStart if it has not already been set.设置整体free内存块的起始标识 */
if( xDefinedRegions == 0 )
{
/* xStart is used to hold a pointer to the first item in the list of
* free blocks. The void cast is used to prevent compiler warnings. */
xStart.pxNextFreeBlock = ( BlockLink_t * ) xAlignedHeap;
xStart.xBlockSize = ( size_t ) 0;
}
else
{
/* Should only get here if one region has already been added to the
* heap. */
configASSERT( pxEnd != NULL );
/* Check blocks are passed in with increasing start addresses. */
configASSERT( xAddress > ( size_t ) pxEnd );
}
/* Remember the location of the end marker in the previous region, if
* any.
由于是多个region,因此,需要记录前一个rigion的end marker */
pxPreviousFreeBlock = pxEnd;
/* pxEnd is used to mark the end of the list of free blocks and is
* inserted at the end of the region space. */
xAddress = xAlignedHeap + xTotalRegionSize;
xAddress -= xHeapStructSize;
xAddress &= ~portBYTE_ALIGNMENT_MASK;
pxEnd = ( BlockLink_t * ) xAddress;
pxEnd->xBlockSize = 0;
pxEnd->pxNextFreeBlock = NULL;
/* To start with there is a single free block in this region that is
* sized to take up the entire heap region minus the space taken by the
* free block structure. */
pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap;
pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion;
pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
/* If this is not the first region that makes up the entire heap space
* then link the previous region to this region. */
if( pxPreviousFreeBlock != NULL )
{
pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;
}
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
/* Move onto the next HeapRegion_t structure. */
xDefinedRegions++;
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
}
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
xFreeBytesRemaining = xTotalHeapSize;
/* Check something was actually defined before it is accessed. */
configASSERT( xTotalHeapSize );
/* Work out the position of the top bit in a size_t variable. */
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
}