Author: Felipe MartÃnez <felipe@pipe01.net>
Use all free RAM for FreeRTOS heap * Use all free RAM for FreeRTOS heap * Wrap newlib malloc and related functions * Implement calloc
src/CMakeLists.txt | 4 ++ src/FreeRTOS/heap_4_infinitime.c | 28 +++++++++------- src/FreeRTOS/portmacro_cmsis.h | 1 src/FreeRTOSConfig.h | 1 src/displayapp/screens/SystemInfo.cpp | 3 + src/libs/lfs_config.h | 49 +++++++++++++++++++++++++++++ src/stdlib.c | 36 +++++++++++++++++---
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0a97a0158b2f9af46d4ef4a073906e25ea5481e8..e2b69b8b027b11952f8396817ba606c825f39882 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -788,6 +788,10 @@ add_definitions(-DFREERTOS) add_definitions(-D__STACK_SIZE=1024) add_definitions(-D__HEAP_SIZE=0) add_definitions(-DMYNEWT_VAL_BLE_LL_RFMGMT_ENABLE_TIME=1500) +add_definitions(-DLFS_CONFIG=libs/lfs_config.h) + +# _sbrk is purposefully not implemented so that builds fail when it is used +add_link_options(-Wl,-wrap=malloc -Wl,-wrap=free -Wl,-wrap=calloc -Wl,-wrap=realloc -Wl,-wrap=_malloc_r -Wl,-wrap=_sbrk) # Note: Only use this for debugging # Derive the low frequency clock from the main clock (SYNT) diff --git a/src/FreeRTOS/heap_4_infinitime.c b/src/FreeRTOS/heap_4_infinitime.c index 1470847114fc75f08ab0f00d3dd480cd7290a0cd..bf6492545ad410050624bd0b14e8719e1bcfa1f8 100644 --- a/src/FreeRTOS/heap_4_infinitime.c +++ b/src/FreeRTOS/heap_4_infinitime.c @@ -60,15 +60,6 @@ /* Assumes 8bit bytes! */ #define heapBITS_PER_BYTE ( ( size_t ) 8 ) -/* Allocate the memory for the heap. */ -#if( configAPPLICATION_ALLOCATED_HEAP == 1 ) -/* The application writer has already defined the array used for the RTOS -heap - probably so it can be placed in a special segment or address. */ -extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -#else -static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -#endif /* configAPPLICATION_ALLOCATED_HEAP */ - /* Define the linked list structure. This is used to link free blocks in order of their memory address. */ typedef struct A_BLOCK_LINK @@ -112,6 +103,8 @@ member of an BlockLink_t structure is set then the block belongs to the application. When the bit is free the block is still part of the free heap space. */ static size_t xBlockAllocatedBit = 0; + +static size_t xHeapSize = 0; /*-----------------------------------------------------------*/ @@ -332,27 +325,38 @@ return xMinimumEverFreeBytesRemaining; } /*-----------------------------------------------------------*/ +size_t xPortGetHeapSize( void ) +{ + return xHeapSize; +} +/*-----------------------------------------------------------*/ + void vPortInitialiseBlocks( void ) { /* This just exists to keep the linker quiet. */ } /*-----------------------------------------------------------*/ +extern uint8_t *__HeapLimit; // Defined by nrf_common.ld + static void prvHeapInit( void ) { BlockLink_t *pxFirstFreeBlock; uint8_t *pucAlignedHeap; size_t uxAddress; - size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; + size_t xTotalHeapSize = ( size_t ) &__StackLimit - ( size_t ) &__HeapLimit; + uint8_t *pucHeap = ( uint8_t * ) &__HeapLimit; + + xHeapSize = xTotalHeapSize; /* Ensure the heap starts on a correctly aligned boundary. */ - uxAddress = ( size_t ) ucHeap; + uxAddress = ( size_t ) pucHeap; if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) { uxAddress += ( portBYTE_ALIGNMENT - 1 ); uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); - xTotalHeapSize -= uxAddress - ( size_t ) ucHeap; + xTotalHeapSize -= uxAddress - ( size_t ) pucHeap; } pucAlignedHeap = ( uint8_t * ) uxAddress; diff --git a/src/FreeRTOS/portmacro_cmsis.h b/src/FreeRTOS/portmacro_cmsis.h index e6e09158a7bd7bc3deeeb4a24ed9e71df0971c53..d165d171357a2f07ce0fd5e02d8471038eb552b3 100644 --- a/src/FreeRTOS/portmacro_cmsis.h +++ b/src/FreeRTOS/portmacro_cmsis.h @@ -180,6 +180,7 @@ } /*-----------------------------------------------------------*/ +size_t xPortGetHeapSize(void); #ifdef __cplusplus } diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 67c33a34cc9124c7ab0bef81e905daf82d82cfb9..d877705a704fc416b3a0df35a17d4627646808f1 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -62,7 +62,6 @@ #define configCPU_CLOCK_HZ (SystemCoreClock) #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES (3) #define configMINIMAL_STACK_SIZE (120) -#define configTOTAL_HEAP_SIZE (1024 * 40) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index d265fddd5bb20f64a9c2cc71f65e308ff132a0b4..886dacb6c6f5056aa3e93b0cb60a2a7772fe1548 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -195,7 +195,7 @@ "\n" "#808080 SPI Flash# %02x-%02x-%02x\n" "\n" "#808080 Memory heap#\n" - " #808080 Free# %d\n" + " #808080 Free# %d/%d\n" " #808080 Min free# %d\n" " #808080 Alloc err# %d\n" " #808080 Ovrfl err# %d\n", @@ -209,6 +209,7 @@ spiFlashId.manufacturer, spiFlashId.type, spiFlashId.density, xPortGetFreeHeapSize(), + xPortGetHeapSize(), xPortGetMinimumEverFreeHeapSize(), mallocFailedCount, stackOverflowCount); diff --git a/src/libs/lfs_config.h b/src/libs/lfs_config.h new file mode 100644 index 0000000000000000000000000000000000000000..eaeede0e6350c0f5e5c5eccf6e7c257d09ec5b8c --- /dev/null +++ b/src/libs/lfs_config.h @@ -0,0 +1,49 @@ +#pragma once + +#include <libraries/log/nrf_log.h> + +#ifndef LFS_TRACE +#ifdef LFS_YES_TRACE +#define LFS_TRACE_(fmt, ...) \ + NRF_LOG_DEBUG("[LFS] %s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) +#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "") +#else +#define LFS_TRACE(...) +#endif +#endif + +#ifndef LFS_DEBUG +#ifndef LFS_NO_DEBUG +#define LFS_DEBUG_(fmt, ...) \ + NRF_LOG_DEBUG("[LFS] %s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) +#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "") +#else +#define LFS_DEBUG(...) +#endif +#endif + +#ifndef LFS_WARN +#ifndef LFS_NO_WARN +#define LFS_WARN_(fmt, ...) \ + NRF_LOG_WARNING("[LFS] %s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) +#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "") +#else +#define LFS_WARN(...) +#endif +#endif + +#ifndef LFS_ERROR +#ifndef LFS_NO_ERROR +#define LFS_ERROR_(fmt, ...) \ + NRF_LOG_ERROR("[LFS] %s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) +#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "") +#else +#define LFS_ERROR(...) +#endif +#endif + +// This is required in order for the CRC implementation in littlefs/lfs_util.c to be compiled +#undef LFS_CONFIG + +#undef LFS_UTIL_H +#include <littlefs/lfs_util.h> diff --git a/src/stdlib.c b/src/stdlib.c index 3ad66b378116ef2150a419140d192c10dcd0f9bc..21b506a8432e438a84a099c8265826cb5c166db8 100644 --- a/src/stdlib.c +++ b/src/stdlib.c @@ -1,4 +1,5 @@ #include <stdlib.h> +#include <string.h> #include <FreeRTOS.h> // Override malloc() and free() to use the memory manager from FreeRTOS. @@ -10,18 +11,41 @@ void* malloc(size_t size) { return pvPortMalloc(size); } +void* __wrap_malloc(size_t size) { + return malloc(size); +} + +void* __wrap__malloc_r(struct _reent* reent, size_t size) { + (void) reent; + return malloc(size); +} + void free(void* ptr) { vPortFree(ptr); +} + +void __wrap_free(void* ptr) { + free(ptr); } void* calloc(size_t num, size_t size) { - (void)(num); - (void)(size); - // Not supported - return NULL; + void *ptr = malloc(num * size); + if (ptr) { + memset(ptr, 0, num * size); + } + return ptr; } -void *pvPortRealloc(void *ptr, size_t xWantedSize); -void* realloc( void *ptr, size_t newSize) { +void* __wrap_calloc(size_t num, size_t size) { + return calloc(num, size); +} + +void* pvPortRealloc(void* ptr, size_t xWantedSize); + +void* realloc(void* ptr, size_t newSize) { return pvPortRealloc(ptr, newSize); } + +void* __wrap_realloc(void* ptr, size_t newSize) { + return realloc(ptr, newSize); +}