千家信息网

FreeRTOS动态内存分配怎么管理heap5

发表于:2025-02-06 作者:千家信息网编辑
千家信息网最后更新 2025年02月06日,今天小编给大家分享一下FreeRTOS动态内存分配怎么管理heap5的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收
千家信息网最后更新 2025年02月06日FreeRTOS动态内存分配怎么管理heap5

今天小编给大家分享一下FreeRTOS动态内存分配怎么管理heap5的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

heap_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. */};

这样就不用老是修改第一块的起始地址。

以上就是"FreeRTOS动态内存分配怎么管理heap5"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

0