修改自FreeRTOS heap5的内存管理

2019-07-21 06:52发布

头文件
[mw_shl_code=c,true]#ifndef __bsp_Malloc_H
#define __bsp_Malloc_H


#include <stdlib.h>
#include "stm32f1xx_hal.h"


#define  Ram1Addr      (0x68000000UL)
#define  Ram1Size      (960*1024)




#define  configMAX_INTERRUPT_PRIORITY     2


#ifndef TEST_MARKER
        #define TEST_MARKER()
#endif

#ifndef myFORCE_INLINE
        #define myFORCE_INLINE __forceinline
#endif

  



typedef struct myHeapRegion
{
        uint8_t *pucStartAddress;  //指向一个地址
        size_t xSizeInBytes;       //此内存块的大小
} myHeapRegion_t;

extern myHeapRegion_t xHeapRegions[];




void *myMalloc( size_t xWantedSize );

void myFree( void *pv );

size_t myGetFreeHeapSize( void );

size_t myGetMinimumEverFreeHeapSize( void );

void myDefineHeapRegions( const myHeapRegion_t * const pxHeapRegions );

#endif


[/mw_shl_code]



源文件
[mw_shl_code=c,true]#include "bsp_Malloc.h"


typedef long BaseType_t;

#define  configUSE_MALLOC_FAILED_HOOK    0

#define  heapMINIMUM_BLOCK_SIZE        ( ( size_t ) ( xHeapStructSize << 1 ) )
#define  heapBITS_PER_BYTE                ( ( size_t ) 8 )

#define  portBYTE_ALIGNMENT              8
#define  portBYTE_ALIGNMENT_MASK        (portBYTE_ALIGNMENT - 1)


#define  MallocInterruptMask( )        vPortSetBASEPRI( )
#define  MallocInterruptRelease( )     vPortRaiseBASEPRI( )
#define  mallocASSERT( x ) if ((x) == 0) { for( ;; );}


typedef struct A_BLOCK_LINK
{
        struct A_BLOCK_LINK *pxNextFreeBlock;        /*<< The next free block in the list. */
        size_t xBlockSize;                                                /*<< The size of the free block. */
} BlockLink_t;



myHeapRegion_t xHeapRegions[] =
{
          { ( uint8_t * ) Ram1Addr, Ram1Size },
          { NULL, 0 }               
};



/*-----------------------------------------------------------*/

static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );

/*-----------------------------------------------------------*/
static const size_t xHeapStructSize        = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );

static BlockLink_t xStart, *pxEnd = NULL;

static size_t xFreeBytesRemaining = 0U;

static size_t xMinimumEverFreeBytesRemaining = 0U;

static size_t xBlockAllocatedBit = 0;

/*-----------------------------------------------------------*/

// 开中断
// 向basepri中写入0就表示开中断
static myFORCE_INLINE void vPortSetBASEPRI( void )
{
    __asm
    {
        msr basepri, 0
    }
}
// 关中断
// 向basepri中写入configMAX_INTERRUPT_PRIORITY,
// 表明优先级低于configMAX_INTERRUPT_PRIORITY的中断都会被屏蔽
static myFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_INTERRUPT_PRIORITY;

    __asm
    {
        msr basepri, ulNewBASEPRI
        dsb
        isb
    }
}


void *myMalloc( size_t xWantedSize )
{
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
void *pvReturn = NULL;
       
        mallocASSERT( pxEnd );
        MallocInterruptMask();
        {

                if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
                {
                       
                        if( xWantedSize > 0 )
                        {
                                xWantedSize += xHeapStructSize;
                       
                                if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
                                {
                                        xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
                                }
                                else
                                {
                                        TEST_MARKER();
                                }
                        }
                        else
                        {
                                TEST_MARKER();
                        }


                        if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
                        {
                                pxPreviousBlock = &xStart;
                                pxBlock = xStart.pxNextFreeBlock;
                                while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
                                {
                                        pxPreviousBlock = pxBlock;
                                        pxBlock = pxBlock->pxNextFreeBlock;
                                }
                       
                                if( pxBlock != pxEnd )
                                {
                                        pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
                                       
                                        pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;

                                        if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
                                        {
                                                pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );


                                                pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;

                                                pxBlock->xBlockSize = xWantedSize;

                                                prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
                                        }
                                        else
                                        {
                                                TEST_MARKER();
                                        }

                                        xFreeBytesRemaining -= pxBlock->xBlockSize;

                                        if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
                                        {
                                                xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
                                        }
                                        else
                                        {
                                                TEST_MARKER();
                                        }

                                        pxBlock->xBlockSize |= xBlockAllocatedBit;
                                       
                                        pxBlock->pxNextFreeBlock = NULL;
                                }
                                else
                                {
                                        TEST_MARKER();
                                }
                        }
                        else
                        {
                                TEST_MARKER();
                        }
                }
                else
                {
                        TEST_MARKER();
                }

        }
         MallocInterruptRelease();

        #if( configUSE_MALLOC_FAILED_HOOK == 1 )
        {
                if( pvReturn == NULL )
                {
                        extern void vApplicationMallocFailedHook( void );
                        vApplicationMallocFailedHook();
                }
                else
                {
                        TEST_MARKER();
                }
        }
        #endif

        return pvReturn;
}
/*-----------------------------------------------------------*/

void myFree( void *pv )
{
uint8_t *puc = ( uint8_t * ) pv;
BlockLink_t *pxLink;

        if( pv != NULL )
        {
                puc -= xHeapStructSize;

                pxLink = ( void * ) puc;

                mallocASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
                mallocASSERT( pxLink->pxNextFreeBlock == NULL );

                if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
                {
                        if( pxLink->pxNextFreeBlock == NULL )
                        {
                                pxLink->xBlockSize &= ~xBlockAllocatedBit;

                                MallocInterruptMask();
                                {
                                        xFreeBytesRemaining += pxLink->xBlockSize;
                                        prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
                                }
                                 MallocInterruptRelease();
                        }
                        else
                        {
                                TEST_MARKER();
                        }
                }
                else
                {
                        TEST_MARKER();
                }
        }
}
/*-----------------------------------------------------------*/

size_t myGetFreeHeapSize( void )
{
        return xFreeBytesRemaining;
}
/*-----------------------------------------------------------*/

size_t myGetMinimumEverFreeHeapSize( void )
{
        return xMinimumEverFreeBytesRemaining;
}
/*-----------------------------------------------------------*/

static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
{
BlockLink_t *pxIterator;
uint8_t *puc;

        for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
        {
                /* Nothing to do here, just iterate to the right position. */
        }

        puc = ( uint8_t * ) pxIterator;
        if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
        {
                pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
                pxBlockToInsert = pxIterator;
        }
        else
        {
                TEST_MARKER();
        }

        puc = ( uint8_t * ) pxBlockToInsert;
        if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
        {
                if( pxIterator->pxNextFreeBlock != pxEnd )
                {
                        pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
                        pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
                }
                else
                {
                        pxBlockToInsert->pxNextFreeBlock = pxEnd;
                }
        }
        else
        {
                pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
        }

        if( pxIterator != pxBlockToInsert )
        {
                pxIterator->pxNextFreeBlock = pxBlockToInsert;
        }
        else
        {
                TEST_MARKER();
        }
}
/*-----------------------------------------------------------*/
void myDefineHeapRegions( const myHeapRegion_t * const pxHeapRegions )
{
BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock;

size_t xAlignedHeap;

size_t xTotalRegionSize, xTotalHeapSize = 0;

BaseType_t xDefinedRegions = 0;

size_t xAddress;

const myHeapRegion_t *pxHeapRegion;

        mallocASSERT( pxEnd == NULL );

        pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );

        while( pxHeapRegion->xSizeInBytes > 0 )
        {
                xTotalRegionSize = pxHeapRegion->xSizeInBytes;

                xAddress = ( size_t ) pxHeapRegion->pucStartAddress;
               
                if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
                {
                        xAddress += ( portBYTE_ALIGNMENT - 1 );
                        xAddress &= ~portBYTE_ALIGNMENT_MASK;

                        xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress;
                }

                xAlignedHeap = xAddress;

                if( xDefinedRegions == 0 )
                {
                        xStart.pxNextFreeBlock = ( BlockLink_t * ) xAlignedHeap;
                        xStart.xBlockSize = ( size_t ) 0;
                }
                else
                {       
                        mallocASSERT( pxEnd != NULL );
                        mallocASSERT( xAddress > ( size_t ) pxEnd );
                }
       
                pxPreviousFreeBlock = pxEnd;

                xAddress = xAlignedHeap + xTotalRegionSize;
                xAddress -= xHeapStructSize;
                xAddress &= ~portBYTE_ALIGNMENT_MASK;
                pxEnd = ( BlockLink_t * ) xAddress;
                pxEnd->xBlockSize = 0;
                pxEnd->pxNextFreeBlock = NULL;

                pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap;
                pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion;
                pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;

                if( pxPreviousFreeBlock != NULL )
                {
                        pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;
                }

                xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;

                xDefinedRegions++;
                pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
        }

        xMinimumEverFreeBytesRemaining = xTotalHeapSize;
        xFreeBytesRemaining = xTotalHeapSize;

        mallocASSERT( xTotalHeapSize );

        xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
}

[/mw_shl_code]



测试过可以在战舰V3使用


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
a3748622
1楼-- · 2019-07-21 08:14
 精彩回答 2  元偷偷看……
hpdell
2楼-- · 2019-07-21 12:22
本帖最后由 hpdell 于 2018-9-27 14:21 编辑
a3748622 发表于 2018-8-6 18:24
不过,heap5中任务的挂起和恢复,我用以下代码实现,在实际应用中,不知道可行与否。
了解的大神可以指教 ...

如果使用了系统,就使用系统提供的 任务挂起、恢复函数,

如果没有使用系统,就使用关总中断,开总中断的方法
貌似有人吧 heap4 改成了内存管理,而且可以管理很多个内存段,
http://www.openedv.com/forum.php ... 5026&highlight=heap
不过貌似这个里面的,如果使用 FreeRTOS 与 这个内存同时使用的话,貌似有些函数及相关的名称冲突,需要做相应的更改




a3748622
3楼-- · 2019-07-21 13:02
hpdell 发表于 2018-9-27 14:17
如果使用了系统,就使用系统提供的 任务挂起、恢复函数,

如果没有使用系统,就使用关总中断,开总中 ...

是的,所以我把一些变量以及函数名修改了。
开关总中断的方法可以指教一下吗?

这个没怎么研究
hpdell
4楼-- · 2019-07-21 18:02
a3748622 发表于 2018-9-29 09:07
是的,所以我把一些变量以及函数名修改了。
开关总中断的方法可以指教一下吗?

总中断就是关闭所以的中断吧
aoteman
5楼-- · 2019-07-21 20:03
a3748622 发表于 2018-9-29 09:07
是的,所以我把一些变量以及函数名修改了。
开关总中断的方法可以指教一下吗?

能发一下工程吗
a3748622
6楼-- · 2019-07-21 20:50
 精彩回答 2  元偷偷看……

一周热门 更多>