The usage of newlib with FreeRTOS is a important, but difficult, topic.
You can find some topics in the community and some documentation around the web, but I think that the key point is the one by nadler (sorry, as a new user I can put link).
As far as I understand, there are two (different? / complementary? / alternative?) approaches:
do not use any FreeRTOS heap management (_1, _2, _3, _4), heap_useNewlib_NXP.c (by nadler) + do not use “simplified” sbrk implementation
define locks __malloc_lock/__malloc_unlock as described in topic with title [REENTRANT] malloc function in libc sprintf type functions in this community
My question is:
are both of them necessary? Or can I chose one of them?
Hi @escherstair
Welcome to the FreeRTOS Community Forums !
It seems both steps are required to ensure that newlib’s memory management works correctly in a FreeRTOS-based system.
If you implement only one (e.g., heap_useNewlib_NXP.c without locks), you’ll still have thread safety issues. If you define only __malloc_lock / __malloc_unlock but use FreeRTOS’s heap (heap_1.c, etc.), newlib’s memory allocation will still be problematic, because newlib relies on sbrk for dynamic memory allocation.
So, the only complete solution is to use heap_useNewlib_NXP.c that contains both __malloc_lock / __malloc_unlock implementation and sbrk() implementation too.
All the other solutions are partial or suitable for specific scenarios:
locks not necessary for single thread
sbrk() reimplementation not necessary if the newlib functions that use memory allocation are not called
I know that FreeRTOS provide the macro configFRTOS_MEMORY_SCHEME to opt-in for one of the heap management (heap_1 / heap_2 / heap_3 / heap_4).
I see
and so I see that 5 is a valid value.
Is “setting to 5” the expected way to opt-in for a custom heap management (as an example heap_useNewlib_NXP.c)?
I would like using this heap management in a clean way (without having to manually change FreeRTOS source code, because this is an approach that doesn’t work weel in the long term period).
Thank you.
Now I see that the FreeRTOS-way to handle heap is documented on github for the CMakeLists.txt of FreeRTOS-Kernal repo:
# User can choose which heap implementation to use (either the implementations
# included with FreeRTOS [1..5] or a custom implementation) by providing the
# option FREERTOS_HEAP. When dynamic allocation is used, the user must specify a
# heap implementation. If the option is not set, the cmake will use no heap
# implementation (e.g. when only static allocation is used).
...
if (DEFINED FREERTOS_HEAP )
# User specified a heap implementation add heap implementation to freertos_kernel.
target_sources(freertos_kernel PRIVATE
# If FREERTOS_HEAP is digit between 1 .. 5 - it is heap number, otherwise - it is path to custom heap source file
$<IF:$<BOOL:$<FILTER:${FREERTOS_HEAP},EXCLUDE,^[1-5]$>>,${FREERTOS_HEAP},portable/MemMang/heap_${FREERTOS_HEAP}.c>
)
endif()
I was wrong, and heap_5 is one of the FreeRTOS heap models.
A custom model can be configured setting FREERTOS_HEAPto the path to custom heap source file.
I’ll ask to NXP how their SDK is supposed to handle this.
@escherstair
You can try forcing the change SET(FREERTOS_HEAP "${ProjDirPath}/../heap_useNewlib_NXP.c" CACHE STRING "" FORCE)
FORCE ensures that the value is overwritten even if the variable is already defined in the cache. Without FORCE, CMake would not update the value if it was previously set.