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.
*/
#include <stdlib.h>
#include <string.h>
/* 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
@ -83,9 +82,6 @@ task.h is included from an application 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. */
#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 )
/* Allocate the memory for the heap. */
//static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
static unsigned char *ucHeap;
static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
/* Define the linked list structure. This is used to link free blocks in order
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 );
/* 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 size_t xTotalHeapSize;
static const size_t xTotalHeapSize = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
/* Create a couple of list links to mark the start and end of the list. */
static xBlockLink xStart, *pxEnd = NULL;
/* Keeps track of the number of free bytes remaining, but says nothing about
fragmentation. */
//static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
static size_t xFreeBytesRemaining;
static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );
/* 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
@ -249,12 +242,8 @@ void *pvReturn = NULL;
}
#endif
// printf("%s %x %x\n", __func__, pvReturn, pxBlock);
return pvReturn;
}
void *malloc(size_t nbytes) __attribute__((alias("pvPortMalloc")));
/*-----------------------------------------------------------*/
void vPortFree( void *pv )
@ -262,8 +251,6 @@ void vPortFree( void *pv )
unsigned char *puc = ( unsigned char * ) pv;
xBlockLink *pxLink;
// printf("%s\n", __func__);
if( pv != NULL )
{
/* The memory being freed will have an xBlockLink structure immediately
@ -285,66 +272,17 @@ xBlockLink *pxLink;
allocated. */
pxLink->xBlockSize &= ~xBlockAllocatedBit;
// vTaskSuspendAll();
ETS_INTR_LOCK();
vTaskSuspendAll();
{
/* Add this block to the list of free blocks. */
xFreeBytesRemaining += pxLink->xBlockSize;
prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );
}
// xTaskResumeAll();
ETS_INTR_UNLOCK();
xTaskResumeAll();
}
}
}
// 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 )
@ -364,10 +302,6 @@ static void prvHeapInit( void )
xBlockLink *pxFirstFreeBlock;
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. */
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;
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 )
{
/* 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 configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 15 )
#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 configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0