Swap memory management to FreeRTOS-style, fixed heap size

This commit is contained in:
Angus Gratton 2015-05-06 18:44:20 +10:00
parent cd705f8b93
commit b3c674d89d
3 changed files with 88 additions and 73 deletions

View file

@ -71,7 +71,6 @@
* memory management pages of http://www.FreeRTOS.org for more information. * memory management pages of http://www.FreeRTOS.org for more information.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when all the API functions to use the MPU wrappers. That should only be done when
@ -83,9 +82,6 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
extern char _heap_start;
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x40000000 - (uint32_t)&_heap_start ) )
/* Block sizes must not get too small. */ /* Block sizes must not get too small. */
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) #define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
@ -96,8 +92,7 @@ extern char _heap_start;
#define heapADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) #define heapADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
/* Allocate the memory for the heap. */ /* Allocate the memory for the heap. */
//static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
static unsigned char *ucHeap;
/* Define the linked list structure. This is used to link free blocks in order /* Define the linked list structure. This is used to link free blocks in order
of their memory address. */ of their memory address. */
@ -130,16 +125,14 @@ block must by correctly byte aligned. */
static const unsigned short heapSTRUCT_SIZE = ( ( sizeof ( xBlockLink ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); static const unsigned short heapSTRUCT_SIZE = ( ( sizeof ( xBlockLink ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
/* Ensure the pxEnd pointer will end up on the correct byte alignment. */ /* Ensure the pxEnd pointer will end up on the correct byte alignment. */
//static const size_t xTotalHeapSize = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); static const size_t xTotalHeapSize = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
static size_t xTotalHeapSize;
/* Create a couple of list links to mark the start and end of the list. */ /* Create a couple of list links to mark the start and end of the list. */
static xBlockLink xStart, *pxEnd = NULL; static xBlockLink xStart, *pxEnd = NULL;
/* Keeps track of the number of free bytes remaining, but says nothing about /* Keeps track of the number of free bytes remaining, but says nothing about
fragmentation. */ fragmentation. */
//static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
static size_t xFreeBytesRemaining;
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize /* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
member of an xBlockLink structure is set then the block belongs to the member of an xBlockLink structure is set then the block belongs to the
@ -249,12 +242,8 @@ void *pvReturn = NULL;
} }
#endif #endif
// printf("%s %x %x\n", __func__, pvReturn, pxBlock);
return pvReturn; return pvReturn;
} }
void *malloc(size_t nbytes) __attribute__((alias("pvPortMalloc")));
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortFree( void *pv ) void vPortFree( void *pv )
@ -262,8 +251,6 @@ void vPortFree( void *pv )
unsigned char *puc = ( unsigned char * ) pv; unsigned char *puc = ( unsigned char * ) pv;
xBlockLink *pxLink; xBlockLink *pxLink;
// printf("%s\n", __func__);
if( pv != NULL ) if( pv != NULL )
{ {
/* The memory being freed will have an xBlockLink structure immediately /* The memory being freed will have an xBlockLink structure immediately
@ -285,66 +272,17 @@ xBlockLink *pxLink;
allocated. */ allocated. */
pxLink->xBlockSize &= ~xBlockAllocatedBit; pxLink->xBlockSize &= ~xBlockAllocatedBit;
// vTaskSuspendAll(); vTaskSuspendAll();
ETS_INTR_LOCK();
{ {
/* Add this block to the list of free blocks. */ /* Add this block to the list of free blocks. */
xFreeBytesRemaining += pxLink->xBlockSize; xFreeBytesRemaining += pxLink->xBlockSize;
prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );
} }
// xTaskResumeAll(); xTaskResumeAll();
ETS_INTR_UNLOCK();
} }
} }
} }
// printf("%s %x %d\n", __func__, pv, xFreeBytesRemaining);
} }
void free(void *ptr) __attribute__((alias("vPortFree")));
/*-----------------------------------------------------------*/
void *pvPortCalloc(size_t count, size_t size)
{
void *p;
/* allocate 'count' objects of size 'size' */
p = pvPortMalloc(count * size);
if (p) {
/* zero the memory */
memset(p, 0, count * size);
}
return p;
}
void *calloc(size_t count, size_t nbytes) __attribute__((alias("pvPortCalloc")));
/*-----------------------------------------------------------*/
void *pvPortZalloc(size_t size)
{
return pvPortCalloc(1, size);
}
void *zalloc(size_t nbytes) __attribute__((alias("pvPortZalloc")));
/*-----------------------------------------------------------*/
void *pvPortRealloc(void *mem, size_t newsize)
{
void *p;
p = pvPortMalloc(newsize);
if (p) {
/* zero the memory */
memcpy(p, mem, newsize);
vPortFree(mem);
}
return p;
}
void *realloc(void *ptr, size_t nbytes) __attribute__((alias("pvPortRealloc")));
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
size_t xPortGetFreeHeapSize( void ) size_t xPortGetFreeHeapSize( void )
@ -364,10 +302,6 @@ static void prvHeapInit( void )
xBlockLink *pxFirstFreeBlock; xBlockLink *pxFirstFreeBlock;
unsigned char *pucHeapEnd, *pucAlignedHeap; unsigned char *pucHeapEnd, *pucAlignedHeap;
xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
xTotalHeapSize = xFreeBytesRemaining ;
ucHeap = &_heap_start;
/* Ensure the heap starts on a correctly aligned boundary. */ /* Ensure the heap starts on a correctly aligned boundary. */
pucAlignedHeap = ( unsigned char * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); pucAlignedHeap = ( unsigned char * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
@ -404,7 +338,8 @@ static void prvInsertBlockIntoFreeList( xBlockLink *pxBlockToInsert )
xBlockLink *pxIterator; xBlockLink *pxIterator;
unsigned char *puc; unsigned char *puc;
/* Iterate through the list until a block is found that has a higher address than the block being inserted. */ /* Iterate through the list until a block is found that has a higher address
than the block being inserted. */
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
{ {
/* Nothing to do here, just iterate to the right position. */ /* Nothing to do here, just iterate to the right position. */

View file

@ -0,0 +1,80 @@
/* this file provides function aliasing/etc that are needed for
compatibility with other binary espressif libraries */
#include <stdlib.h>
#include <string.h>
#include "FreeRTOS.h"
/* Enable/Disable Interrupts
Called from many of the linked libraries to protect critical sections.
*/
/*
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
}
void vPortExitCritical( void )
{
portEXIT_CRITICAL();
}
*/
/* libc memory management functions.
Many of these are linked from the RTOS SDK blob libraries.
In esp_iot_rtos_sdk these are aliased to exception-safe versions of
the FreeRTOS functions. I think the rationale is that they're
sometimes called in exception contexts (ESPTODO: Verify this).
For now these are exception-safe wrappers to the FreeRTOS versions.
*/
void *malloc(size_t nbytes) {
void *res;
portENTER_CRITICAL();
res = pvPortMalloc(nbytes);
portEXIT_CRITICAL();
return res;
}
void *calloc(size_t count, size_t size) {
void *res;
size_t nbytes = count * size;
portENTER_CRITICAL();
res = pvPortMalloc(nbytes);
portEXIT_CRITICAL();
if(res) {
memset(res, 0, nbytes);
}
return res;
}
void *zalloc(size_t nbytes) {
return calloc(1, nbytes);
}
void *realloc(void *old, size_t newsize) {
void *new;
portENTER_CRITICAL();
if(newsize == 0) {
vPortFree(old);
return 0;
}
/* realloc implementation borrowed from esp_iot_rtos_sdk, could be better I think */
new = pvPortMalloc(newsize);
if (new) {
memcpy(new, old, newsize);
vPortFree(old);
}
portEXIT_CRITICAL();
return new;
}
void free(void *ptr) {
portENTER_CRITICAL();
vPortFree(ptr);
portEXIT_CRITICAL();
}

View file

@ -84,7 +84,7 @@
#define configTICK_RATE_HZ ( ( portTickType ) 100 ) #define configTICK_RATE_HZ ( ( portTickType ) 100 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 15 ) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 15 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short )156 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short )156 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 ) #define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0 #define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0 #define configUSE_STATS_FORMATTING_FUNCTIONS 0