FreeRTOS动态内存分配管理
jiang_2018 人气:0heap_5.c
heap5与heap4分配释放算法完全相同,只是heap5支持管理多块不连续的内存,本质是将多块不连续内存用链表串成一整块内存,再用heap4算法来分配释放。若使用heap5则在涉及到分配释放的函数调用时要先调用vPortDefineHeapRegions
把多块不连续内存串成一块初始化。
vPortDefineHeapRegions
此函数原型
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ),
参数在portable.h
中定义,如下
/* Used by heap_5.c. */ typedef struct HeapRegion { uint8_t *pucStartAddress;//指向内存块首地址 size_t xSizeInBytes;//此内存块大小 } HeapRegion_t;
比如有2块内存要用heap5管理,地址0x80000000,大小0x10000,地址0x90000000,大小0xa0000
,则如下定义该结构体数组
HeapRegion_t xHeapRegions[] = { { ( uint8_t * ) 0x80000000UL, 0x10000 }, { ( uint8_t * ) 0x90000000UL, 0xa0000 }, { NULL, 0 } };
注意地址顺序要从小到大,最后要以{NULL,0}结尾(源码是以0做判断结束循环)
下面看初始化源码
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 ) { 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. */ 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. */ 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 ); }
常见问题
比如有多块内存,一块是内部ram,其他是外部ram,外部的地址能写死确定,但是内部的会随着程序开发不停改变,怎么确定呢,下面是官网给的例子
/* Define the start address and size of the two RAM regions not used by the linker. */ #define RAM2_START_ADDRESS ( ( uint8_t * ) 0x00020000 ) #define RAM2_SIZE ( 32 * 1024 ) #define RAM3_START_ADDRESS ( ( uint8_t * ) 0x00030000 ) #define RAM3_SIZE ( 32 * 1024 ) /* Declare an array that will be part of the heap used by heap_5. The array will be placed in RAM1 by the linker. */ #define RAM1_HEAP_SIZE ( 30 * 1024 ) static uint8_t ucHeap[ RAM1_HEAP_SIZE ]; /* Create an array of HeapRegion_t definitions. Whereas in Listing 6 the first entry described all of RAM1, so heap_5 will have used all of RAM1, this time the first entry only describes the ucHeap array, so heap_5 will only use the part of RAM1 that contains the ucHeap array. The HeapRegion_t structures must still appear in start address order, with the structure that contains the lowest start address appearing first. */ const HeapRegion_t xHeapRegions[] = { { ucHeap, RAM1_HEAP_SIZE }, { RAM2_START_ADDRESS, RAM2_SIZE }, { RAM3_START_ADDRESS, RAM3_SIZE }, { NULL, 0 } /* Marks the end of the array. */ };
这样就不用老是修改第一块的起始地址。
加载全部内容