Clean way to handle FreeRTOS and newlib

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.

Thank you @karahulx

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

#if ((configFRTOS_MEMORY_SCHEME > 5) || (configFRTOS_MEMORY_SCHEME < 1))
#error "Invalid configFRTOS_MEMORY_SCHEME setting!"
#endif

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).

configFRTOS_MEMORY_SCHEME is not a standard FreeRTOS macro - it is a vendor-specific feature from NXP.

Setting it to 5 (if supported in your distribution) may allow using a custom heap manager like heap_useNewlib_NXP.c.

For your application without modifying FreeRTOS source code:

  1. Exclude all heap_x.c Files
  2. Add heap_useNewlib_NXP.c in your build.
  3. Ensure it defines pvPortMalloc() and vPortFree()
  4. Ensure _malloc_lock() and _malloc_unlock() are defined for thread safety.

Since its a NXP specific configuration, I’d suggest to ask on NXP forums as well.

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.

Hi @karahulx
I tried defining FREERTOS_HEAP in my CMakeLists.txt as

SET(FREERTOS_HEAP ${ProjDirPath}/../heap_useNewlib_NXP.c)

but I notice that when I build my project heap_4.c is compiled.
Is there a specifi way to set this parameter?

@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.

1 Like