Squeeze all SRAM memory into FreeRTOS heap in Keil5

Hi All,

I’m using Keil5 developing application on a Cortex-M0 platform with FreeRTOS example.

In FreeRTOS, there is a global buffer ucHeap[] doing the memory dynamic allocation and free, it also used as the heap for OS tasks stack.

I want to define the size of ucHeap as bigger as it can, until use up the whole SRAM memory.

So I want to realize a function in Keil5 to change the size of ucHeap everything time based on other RW/ZI usage.

For example,

i)The total SRAM is 20KB, other RW/ZI/STACK usage is already 10KB, the Keil5 can allocate 20-10=10KB for the ucHeap.

ii)The total SRAM is 20KB, other RW/ZI/STACK usage is already 8KB, the Keil5 can allocate 20-8=12KB for the ucHeap.

Currently I manually change the size of ucHeap everytime to use up the whole SRAM. I would like to have method to achieve this function automatically.

Thanks.

Best Regards.

The configAPPLICATION_ALLOCATED_HEAP constant enables the application to place ucHeap wherever it likes. You may be able to use a linker variable to automatically place ucHeap at the start of the free memory block, but I don’t think you can use linker variables to set the configTOTAL_HEAP_SIZE constant (partly because the constant is used before linking, so you would have a circular dependence).

Your other options would be to use heap_3.c, which just wraps the standard C library implementation of malloc() and free() to make them thread safe. Then you can place the heap to use up all the free memory as you would in a non-FreeRTOS application.

You can export 2 variables from your linker script: __free_ram_start__ and __free_ram_end__. It should then be possible to use heap_5:

configASSERT( __free_ram_start__ < __free_ram_end__ );

size_t heapSize = ( __free_ram_end__ - __free_ram_start__ );
unsigned char * heapStart = ( unsigned char * )__free_ram_start__;

HeapRegion_t xHeapRegions[] =
{
    { heapStart, heapSize) },
    { NULL,      0         }
};

vPortDefineHeapRegions( xHeapRegions );

You can find more documentation about heap_5 here: https://www.freertos.org/a00111.html#heap_5

Thanks.

Hi Aggarg,
I found this solution in heap5.c and implementation in .ld file using GCC compiler.
But I don’t know how to export 2 variables from scatter file in Keil5 using ARMCC compiler.
Could you point me out how to export free_ram_end and free_ram_start from scatter file.
Thanks a lot.
Best Regards.

Scatter files are not as flexible as GCC ld files. You can take a look here:

Thanks.

Hi Aggarg,
Thanks for quick response.
I follow the code example from your link. I can get the rest of SRAM by the variables from sct files.
Then I do the ucHeap initialization in my code as below,
ucHeap = (uint8_t *)(( uint32_t )(&( Image$$ER_IRAM_NS_UNPRIVILEGED_ALIGN$$Limit ) + 0x01));

But the code didn’t work correctly. From the map file,
Image$$ER_IRAM_NS_UNPRIVILEGED_ALIGN$$Limit 0x200020e0 Number 0 anon$$obj.o ABSOLUTE
__initial_sp 0x200020e0 Data 0 startup.o(STACK)

By the way, I’m using heap_4.c.

Thanks.
Best Regards.

As I mentioned in my previous response above, you need to use heap_5.c and call vPortDefineHeapRegions. I have shown an example above too.

Thanks.

Hi Aggarg,

I find the reason why it didn’t work since I change the array ucHeap[] to a global point uint8_t *ucHeap, but not changed in heap_4.c.
Actually for heap_4.c just need to know start address of heap and the length is enough. It both work for heap_4.c and heap_5.c as well.

Thanks for your help.
Best Regards.

The size of heap_4 is configured using a compile time macro configTOTAL_HEAP_SIZE. You need to ensure that it is set correctly to the size of free RAM available.

Heap_5 allows you set the size of memory region to be used as heap using vPortDefineHeapRegions.

Thanks.