Difference between linker script’s “HEAP SIZE” and BSP’s “TOTAL_HEAP_SIZE”

Hi, I’m new in the forum because I’m currently developing my fist FreeRTOS application; it runs on a Xilinx’s Microblaze over a Kintex FPGA and a custom board. SDK (eclipse environment for Xilinx) allows to change some kernel parameters in the BSP, such as TOTALHEAPSIZE. My application running over FreeRTOS needs a relative big heap which is allocated in 512Mbyte DDR3 RAM. I want to allocate 1Mbyte for heap, and the rest (511 MByte) for data buffers (mainly for DMAs). Where should I set the 1MByte value, in the linker script “HEAP SIZE” field or in the BSP property “TotalHeapSize”? According to FreeRTOS documentation, “TotalHeapSize” is the amount of memory FreeRTOS will use when allocating memory dinamically (malloc). So then, what’s “HEAP_SIZE” in linker script useful for? What’s the difference between both parameters? Thanks!

Difference between linker script’s “HEAP SIZE” and BSP’s “TOTAL_HEAP_SIZE”

Ok, I checked where variables are allocated in memory and figured out the answer:
  • TOTALHEAPSIZE is memory allocated to the FreeRTOS kernel, which is used internally to create semaphores, tasks, queues, etc. and can’t be user by the application. As it is statically created, it is allocated in bss section.
  • Linker script’s “Heap Size” is memory allocated to the application through malloc calls. In my application, that is DD3 RAM.
I got confused by figure 7 in book “Mastering the FreeRTOS RealTime Kernel – A Hands-On Tutorial Guide”, where you can see how user data is allocated into kernel’s heap, which still doesn’t make sense to me.

Difference between linker script’s “HEAP SIZE” and BSP’s “TOTAL_HEAP_SIZE”

With FreeRTOS, unless you are using heap3.c for FreeRTOS heap management, there are possibly two heaps in the system. One is the standard C heap, which is what the linker script setting controls, this will control the memory available by malloc() and famiy. The second is the heap managed by thr FreeRTOS heap function for the use of FreeRTOS, and any application the uses the calls to the FreeRTOS heap. That size is controlled by TOTALHEAPSIZE. If you application make use of malloc(), then I would suggest, using heap3 or a variant of it. One issue is that normally out of the box, malloc() isn’t thread safe, so either you need to in code guards around malloc() (in which case it might be easier just to call the FreeRTOS heap functions) or find the hooks within the implementation of malloc() and family (if available) that can make them thread safe. If you do the latter, then it make sense to use a variant of heap3 that just directly calls malloc and lets them do all the work and avoid the split heap.

Difference between linker script’s “HEAP SIZE” and BSP’s “TOTAL_HEAP_SIZE”

Xilinx’s SDK sets heap4.c as default heap manager, and don’t think if I can change that: when BSP is reloaded, default configuration is applied, so heap4.c is included again. If I call FreeRTOS mallocs, where is the memory allocated, standard C heap or FreeRTOS heap? I think it will be allocated in FreeRTOS heap, but just to be sure. Thanks for your answer.

Difference between linker script’s “HEAP SIZE” and BSP’s “TOTAL_HEAP_SIZE”

First, you most certainly can change it, if the SDK doesn’t provide an option for this, you can just manually delete heap4.c from the project and add in heap3.c, perhaps from a clean copy of FreeRTOS copied into your project. You may need to redo this every time you regenerate the project via the tool. If you call pvPortMalloc() you will get memory from the FreeRTOS heap, the amount of which is controlled by configAPPLICATIONALLOCATEDHEAP in FreeRTOSConfig.h, if you call malloc(), you will use the system provided malloc() function (which might not be thread safe) whose size is generally controlled by linker parameters. Only if pvPortMalloc() calls malloc() itself will these be the same heap. If the application has code that MUST call malloc (typically because some third party or using parts of the system library use it), it makes sense to try and make malloc thread safe and make everything use it. This requires some knowledge of the library structure. Some standard libraries provide a call back that can be used to make the heap functions thread safe, in other cases you may be able to replace malloc/free with thread safe version (perhaps calling pvPortMalloc, provided you don’t need realloc support), but for this you need to know if malloc defers to something deeper that perhaps parts of the library uses.

Difference between linker script’s “HEAP SIZE” and BSP’s “TOTAL_HEAP_SIZE”

Richard D – there are two ways of using FreeRTOS with the Xilinx SDK – the first is to use a FreeRTOS BSP and the second is to use a ‘standalone’ BSP. The latter case is what you are used to – you manually add the FreeRTOS files into the project as any other source file and the BSP only includes drivers. In the former case the FreeRTOS source files are added to the project automatically as part of the BSP along with the dirvers – in which case the files that are included are actually defined by a TCL script inside the Xilinx tools installation directory. Both FreeRTOS and the drivers are configured using a graphical wizard – as I recall the size of the malloc() (as opposed to the FreeRTOS pvPortMalloc()) heap is set in the tools options somewhere.

Difference between linker script’s “HEAP SIZE” and BSP’s “TOTAL_HEAP_SIZE”

Yes, you’re right. I use the former case, I use the tool-asisted FreeRTOS BSP, and I’m sure Xilinx’s SDK restores BSP files each time you re-generate the project (it does with driver files too). Unfortunately, re-generation must be done each time bitstream changes, and that happens often during developing phase. Furthermore, some defines such as configAPPLICATIONALLOCATEDHEAP can’t be changed in FreeRTOSConfig.h because it is back to its default value after regenerating. Thank you both for your help; I solved the initial problem by separating kernel’s heap into fast BRAM memory (allocated in BSS) and program heap into slower DDR3. I use malloc before creating any thread to allocate a big memory pool in DDR3, so I don’t have to pay attention to thread-safe implementation of malloc, as no reallocs have to be done on runtime.