Central heap required for functions called from within tasks that use malloc

Hi

I was reading up on the use of the stack and heap of the startup files on the FreeRTOS website and it was implied that these two memory areas were only used by the main.c program. Anything done in a task used the task stack and FreeRTOS heap.

I am using Simple Dynamic Strings (SDS).

So I set my heap to 0 in the startup file and bang! Hard fault. The thing crashed in the sds string function sdslen because the function tried to address 0x00000000 - 1. Bad idea.

I made my startup heap 4k and it worked.

Am I going about this the correct way or should I be calling a different malloc from within sds.

sds has an allocator for memory management:


/* SDS allocator selection.
 *
 * This file is used in order to change the SDS allocator at compile time.
 * Just define the following defines to what you want to use. Also add
 * the include of your alternate allocator if needed (not needed in order
 * to use the default libc allocator). */

#define s_malloc malloc
#define s_realloc realloc
#define s_free free

Should I be fiddling with this or should I just use the startup heap? I only use sds in one task, but I may wish to use it in another.

I’m happy with the way it works, but there might be some nasty side effects I’m unaware of.

I also don’t quite get the difference between the startup heap and the heap set in FreeRTOS config.

I have read the stuff on the web site, but the penny hasn’t dropped. If I create a variable using malloc in a task, which heap is it using, the startup heap, the one defined in FreeRTOSConfig or the task heap itself? Can I create a variable by calling pvPortMalloc(). Which heap would this use?

Also I would think that all interrupts use the startup stack as the startup code sets the stack pointer to the address assigned in startup viz:

Reset_Handler:
 ldr   sp, =_estack

_estack if defined in the GCC linker script:

/* Highest address of the user mode stack */
_estack = ORIGIN(DTC_STACK) + LENGTH(DTC_STACK);	/* end of "RAM" Ram type memory */

_Min_Heap_Size  = 0x1000 ;	/* required amount of heap  */
_Min_Stack_Size = 0x1000 ;	/* required amount of stack */

/* Memories definition */
MEMORY
{
  FIR_FILT_DW    		(xrw)    : ORIGIN = 0x20000000,   LENGTH =     4K	
  DTCM_MISC				(xrw)    : ORIGIN = 0x20001000,   LENGTH =   116K	
    
  DTC_STACK    			(xrw)    : ORIGIN = 0x20010000,   LENGTH =     8K
  

It’s all a bit mysterious.

Best regards
Rob

If you create FreeRTOS objects using dynamically allocated memory (for example, if you call xTaskCreate() rather than xTaskCreateStatic()) then FreeRTOS needs to allocate memory. It does that by calling pvPortMalloc() rather than a direct call to malloc(). You can implement pvPortMalloc() to do whatever you want. FreeRTOS comes with five different implementations you can opt to use. If you opt to use heap_3, then pvPortMalloc() basically maps to the standard C library malloc() function (with a bit of housekeeping to ensure it is thread safe). If you use any other of the provided heap implementations then FreeRTOS does not use the standard C library malloc(). If nothing else in your application uses the standard C library malloc() - then you can set to heap defined by your linker script to be 0 bytes long. If anything else in your application does use the standard C library malloc() then you have two options - either ensure the heap defined by your linker script is large enough for anything in your application that calls malloc() directly (FreeRTOS calls portMalloc(), so doesn’t call malloc() unless you use heap_3), or map the C library’s malloc() to pvPortMalloc() (and likewise free() to vPortFree()). In your case it looks like you can do the latter by #define’ing s_malloc to pvPortMalloc.

Thanks Richard,

I get it now.

I think I will stick with using the standard C defined malloc in this project and keep my startup defined heap as it’s tested and working. I have yet to optimize the heap and stacks for this project so I will be able to reduce the size of my FreeRTOs heap accordingly.

I just had a thought, the standard malloc wouldn’t be thread safe, so if I uses sds with malloc in two different tasks I could end up with big trouble. Is that a good reason for using the FreeRTOS heap which is thread safe?

I am using heap_4 as this is required for ST’s TouchGFX if my memory serves me correctly

Best Regards
Rob

That sounds right. Heap_3 is a wrapper around standard malloc and is thread-safe.

You might use std malloc in a multi-tasking application if your C-library (newlib) supports it.
See e.g. this posts here in the forum for the details:

There are a few more regarding this topic.