基于freertos的嵌入式系统开发(七)FreeRTOS的内存管理方法5

34 篇文章 2 订阅
33 篇文章 2 订阅

基于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 );

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cyjbj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值