=============================== 博客点滴积累,部分话语和知识点来源于网络,感谢网络资源的提供者======
heap5 与heap4 比较相似,也是实现了malloc和free,同时也可以进行碎片合并。有的区别是heap5 可以有多个堆区,static void prvHeapInit( void ) 被换成void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )这个函数。结构体HeapRegion_t(portable.h)如下:
const HeapRegion_t * const pxHeapRegions 结构体如下定义(portable.h):
/* Used by heap_5.c. */
typedef struct HeapRegion
{
uint8_t *pucStartAddress;
size_t xSizeInBytes;
} HeapRegion_t;
该函数前面有一段注释大概意思是:vPortDefineHeapRegions 一定要在使用pvPortMalloc之前使用,进行初始化栈区。创建任务,信号量,互斥锁,软件定时器,事件组等都调用pvPortMalloc。所以这个需要注意。
vPortDefineHeapRegions 函数的参数是一个结构体数组,数组的地址指针,必须从小到大排序,并且以空指针和0字节结尾
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
{
BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock;
uint8_t *pucAlignedHeap;
size_t xTotalRegionSize, xTotalHeapSize = 0;
BaseType_t xDefinedRegions = 0;
uint32_t ulAddress;
const HeapRegion_t *pxHeapRegion;
/* Can only call once! */
configASSERT( pxEnd == NULL );
//取数组的第一个元素
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
while( pxHeapRegion->xSizeInBytes > 0 )
{//xSizeInBytes 以 0 字节结尾
xTotalRegionSize = pxHeapRegion->xSizeInBytes;/* Ensure the heap region starts on a correctly aligned boundary. */ulAddress = ( uint32_t ) pxHeapRegion->pucStartAddress;if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 ){ulAddress += ( portBYTE_ALIGNMENT - 1 );ulAddress &= ~portBYTE_ALIGNMENT_MASK;/* 调整字节对齐 */xTotalRegionSize -= ulAddress - ( uint32_t ) pxHeapRegion->pucStartAddress;}pucAlignedHeap = ( uint8_t * ) ulAddress;/* Set xStart if it has not already been set. */if( xDefinedRegions == 0 ){//当是数据的第一个元素,是初始化链表的头指针,注意xStart是个结构体,结构体的pxNextFreeBlock 指针指向了pucAlignedHeap,即堆区的基地址,基地址存了什么呢?pxFirstFreeBlockInRegion 结构体,定义了heap的大小,以及下一个heap的地址
xStart.pxNextFreeBlock = ( BlockLink_t * ) pucAlignedHeap;xStart.xBlockSize = ( size_t ) 0;}else{configASSERT( pxEnd != NULL );configASSERT( ulAddress > ( uint32_t ) pxEnd );}pxPreviousFreeBlock = pxEnd;//pxEnd 是个指针。它存在heap地址的最后面ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalRegionSize;ulAddress -= uxHeapStructSize;ulAddress &= ~portBYTE_ALIGNMENT_MASK;pxEnd = ( BlockLink_t * ) ulAddress;//初始化heap最后的pxEnd 指针
pxEnd->xBlockSize = 0;
pxEnd->pxNextFreeBlock = NULL;
pxFirstFreeBlockInRegion = ( BlockLink_t * ) pucAlignedHeap;pxFirstFreeBlockInRegion->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlockInRegion;pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;if( pxPreviousFreeBlock != NULL ){//不是第一块,就插入链表pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;}xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;//统计heap大小/* 数组下标加1,获取下一个元素 */xDefinedRegions++;pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
}
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
xFreeBytesRemaining = xTotalHeapSize;
/* Check something was actually defined before it is accessed. */
configASSERT( xTotalHeapSize );
/* xBlockAllocatedBit 标记最高bit位,表示地址是否空闲 */xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
}