diff --git a/portable/MemMang/heap_5.c b/portable/MemMang/heap_5.c index 4e872f6..eae4f2f 100644 --- a/portable/MemMang/heap_5.c +++ b/portable/MemMang/heap_5.c @@ -78,6 +78,12 @@ #include "FreeRTOS.h" #include "task.h" +#include "platform_opts.h" + + +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#include "section_config.h" +#endif #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE @@ -184,6 +190,12 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEG /*-----------------------------------------------------------*/ +/* Platform-specific definitions */ +#if defined(CONFIG_PLATFORM_8195A) +#define SRAM_START_ADDRESS 0x10000000 +#define SDRAM_START_ADDRESS 0x30000000 +#endif + /* The size of the structure placed at the beginning of each allocated memory * block must by correctly byte aligned. */ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); @@ -198,6 +210,10 @@ PRIVILEGED_DATA static size_t xFreeBytesRemaining = ( size_t ) 0U; PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = ( size_t ) 0U; PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = ( size_t ) 0U; PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = ( size_t ) 0U; +#if defined(CONFIG_PLATFORM_8195A) +PRIVILEGED_DATA static size_t xSRAMFreeBytesRemaining = ( size_t ) 0U; +PRIVILEGED_DATA static size_t xSDRAMFreeBytesRemaining = ( size_t ) 0U; +#endif #if ( configENABLE_HEAP_PROTECTOR == 1 ) @@ -212,8 +228,67 @@ PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = ( size_t ) 0U; /*-----------------------------------------------------------*/ +/* External memory management support */ +static void (*ext_free)(void *p) = NULL; +static uint32_t ext_upper = 0; +static uint32_t ext_lower = 0; + +/* Platform-specific heap definitions */ +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +SRAM_BF_DATA_SECTION static uint8_t ucHeap[configTOTAL_HEAP_SIZE]; + +#if defined(CONFIG_PLATFORM_8195A) +HeapRegion_t xHeapRegions[] = { + { (uint8_t*)0x10002300, 0x3D00 }, /* Image1 recycle heap */ + { ucHeap, sizeof(ucHeap) }, /* Main heap */ + { NULL, 0 } /* Terminator */ +}; +#elif defined(CONFIG_PLATFORM_8711B) +#include "rtl8710b_boot.h" +extern BOOT_EXPORT_SYMB_TABLE boot_export_symbol; + +HeapRegion_t xHeapRegions[] = { + { 0, 0 }, /* Image1 reserved */ + { ucHeap, sizeof(ucHeap) }, /* Main heap */ + { 0, 0 }, /* RDP reserved */ + { NULL, 0 } /* Terminator */ +}; +#endif +#endif + +/* Debug support function */ +#if configENABLE_HEAP_DEBUG +void vPortDumpMemBlockList(void) { + BlockLink_t *pxBlock = &xStart; + int count = 0; + + configPRINTF(("Memory Block List:\n")); + while(pxBlock->pxNextFreeBlock != NULL) { + configPRINTF(("[%d]=0x%p, %d\n", count++, pxBlock, pxBlock->xBlockSize)); + pxBlock = pxBlock->pxNextFreeBlock; + } +} +#endif + +/* Modified pvPortMalloc */ void * pvPortMalloc( size_t xWantedSize ) { + /* Initialize heap regions if needed */ + #if defined(CONFIG_PLATFORM_8711B) + if(pxEnd == NULL) { + /* Configure platform-specific regions */ + xHeapRegions[0].xSizeInBytes = (uint32_t)((uint8_t*)0x10005000 - (uint8_t*)boot_export_symbol.boot_ram_end); + xHeapRegions[0].pucStartAddress = (uint8_t*)boot_export_symbol.boot_ram_end; + + if(!IsRDPenabled()) { + xHeapRegions[2].xSizeInBytes = 0x1000; + xHeapRegions[2].pucStartAddress = (uint8_t*)0x1003f000; + } + + vPortDefineHeapRegions(xHeapRegions); + } + #endif + BlockLink_t * pxBlock; BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; @@ -328,7 +403,14 @@ void * pvPortMalloc( size_t xWantedSize ) } xFreeBytesRemaining -= pxBlock->xBlockSize; - + #if defined(CONFIG_PLATFORM_8195A) + /* Update region-specific statistics */ + if(((uint32_t)pxBlock >= SRAM_START_ADDRESS) && ((uint32_t)pxBlock < SDRAM_START_ADDRESS)) { + xSRAMFreeBytesRemaining -= pxBlock->xBlockSize; + } else if((uint32_t)pxBlock >= SDRAM_START_ADDRESS) { + xSDRAMFreeBytesRemaining -= pxBlock->xBlockSize; + } + #endif if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) { xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; @@ -386,7 +468,7 @@ void * pvPortMalloc( size_t xWantedSize ) } /*-----------------------------------------------------------*/ -void vPortFree( void * pv ) +void __vPortFree( void * pv ) { uint8_t * puc = ( uint8_t * ) pv; BlockLink_t * pxLink; @@ -426,6 +508,12 @@ void vPortFree( void * pv ) { /* Add this block to the list of free blocks. */ xFreeBytesRemaining += pxLink->xBlockSize; + #if defined CONFIG_PLATFORM_8195A + if(((uint32_t) pxLink >= SRAM_START_ADDRESS) && ((uint32_t) pxLink < SDRAM_START_ADDRESS)) + xSRAMFreeBytesRemaining += pxLink->xBlockSize; + else if((uint32_t) pxLink >= SDRAM_START_ADDRESS) + xSDRAMFreeBytesRemaining += pxLink->xBlockSize; + #endif traceFREE( pv, pxLink->xBlockSize ); prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); xNumberOfSuccessfulFrees++; @@ -443,12 +531,41 @@ void vPortFree( void * pv ) } } } + +/* Modified vPortFree with external free support */ +void vPortFree(void *pv) { + if(((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper)) { + if(ext_free) ext_free(pv); + return; + } + + /* Original vPortFree implementation */ + __vPortFree(pv); +} + +void vPortSetExtFree(void (*free)(void *p), uint32_t upper, uint32_t lower) { + ext_free = free; + ext_upper = upper; + ext_lower = lower; +} + /*-----------------------------------------------------------*/ size_t xPortGetFreeHeapSize( void ) { return xFreeBytesRemaining; } + +#if defined(CONFIG_PLATFORM_8195A) +size_t xPortGetSRAMFreeHeapSize(void) { + return xSRAMFreeBytesRemaining; +} + +size_t xPortGetSDRAMFreeHeapSize(void) { + return xSDRAMFreeBytesRemaining; +} +#endif + /*-----------------------------------------------------------*/ size_t xPortGetMinimumEverFreeHeapSize( void ) @@ -556,6 +673,9 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) /* PRIVI BlockLink_t * pxPreviousFreeBlock; portPOINTER_SIZE_TYPE xAlignedHeap; size_t xTotalRegionSize, xTotalHeapSize = 0; + #if defined CONFIG_PLATFORM_8195A + size_t xSRAMTotalHeapSize = 0, xSDRAMTotalHeapSize = 0; + #endif BaseType_t xDefinedRegions = 0; portPOINTER_SIZE_TYPE xAddress; const HeapRegion_t * pxHeapRegion; @@ -646,6 +766,13 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) /* PRIVI xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; + #if defined CONFIG_PLATFORM_8195A + if(((uint32_t) pxFirstFreeBlockInRegion >= SRAM_START_ADDRESS) && ((uint32_t) pxFirstFreeBlockInRegion < SDRAM_START_ADDRESS)) + xSRAMTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; + else if((uint32_t) pxFirstFreeBlockInRegion >= SDRAM_START_ADDRESS) + xSDRAMTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; + #endif + #if ( configENABLE_HEAP_PROTECTOR == 1 ) { if( ( pucHeapHighAddress == NULL ) || @@ -663,6 +790,10 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) /* PRIVI xMinimumEverFreeBytesRemaining = xTotalHeapSize; xFreeBytesRemaining = xTotalHeapSize; + #if defined CONFIG_PLATFORM_8195A + xSRAMFreeBytesRemaining = xSRAMTotalHeapSize; + xSDRAMFreeBytesRemaining = xSDRAMTotalHeapSize; + #endif /* Check something was actually defined before it is accessed. */ configASSERT( xTotalHeapSize ); @@ -747,3 +878,73 @@ void vPortHeapResetState( void ) #endif /* #if ( configENABLE_HEAP_PROTECTOR == 1 ) */ } /*-----------------------------------------------------------*/ +/* + * Reallocates a memory block to a new size while preserving its contents. + * + * @param pv Pointer to existing memory block, or NULL for new allocation + * @param xWantedSize Desired size in bytes, or 0 to free the memory + * @return Pointer to new memory block, or NULL if allocation failed + */ +void* pvPortReAlloc(void *pv, size_t xWantedSize) { + // handle external memory region if applicable + if (pv && ((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper)) { + if (ext_free) { + ext_free(pv); + } + pv = NULL; + } + + // handle NULL pointer with wanted size (simple malloc) + if (!pv && xWantedSize) { + return pvPortMalloc(xWantedSize); + } + + // handle zero size (simple free) + if (xWantedSize == 0) { + vPortFree(pv); + return NULL; + } + + // at this point, we have a valid pointer and non-zero wanted size + BlockLink_t *pxLink; + unsigned char *puc = (unsigned char *)pv; + + puc -= xHeapStructSize; + pxLink = (BlockLink_t *)puc; + size_t oldSize = (pxLink->xBlockSize & ~heapBLOCK_ALLOCATED_BITMASK) - xHeapStructSize; + + if (xWantedSize <= oldSize) { + // TODO: could potentially split the block here if difference is significant + return pv; + } + + // allocate new block + void *newArea = pvPortMalloc(xWantedSize); + if (!newArea) { + return NULL; + } + + memcpy(newArea, pv, oldSize); + + vTaskSuspendAll(); + { + // mark block as free and update free bytes counter + heapFREE_BLOCK(pxLink); + xFreeBytesRemaining += pxLink->xBlockSize; + + #if defined CONFIG_PLATFORM_8195A + if (((uint32_t)pxLink >= SRAM_START_ADDRESS) && ((uint32_t)pxLink < SDRAM_START_ADDRESS)) { + xSRAMFreeBytesRemaining += pxLink->xBlockSize; + } else if ((uint32_t)pxLink >= SDRAM_START_ADDRESS) { + xSDRAMFreeBytesRemaining += pxLink->xBlockSize; + } + #endif + + // insert freed block into free list + prvInsertBlockIntoFreeList(pxLink); + } + xTaskResumeAll(); + + return newArea; +} +/*-----------------------------------------------------------*/