This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to configure minimum heap size on ARM

My project uses ARM Cortex M0+, with C++ and ArmClang 6.10.1. My ultimate goal is to set "Heap_Size EQU 0x0" in the startup.s file. My code builds fine, but when I run it in Keil simulator it crashes. Stepping through assembly instructions, it appears that the "_init_alloc" function exits with SIGRTMEM signal after comparing the 0x0 heap size to a "#0x10" immediate. To confirm, I set "Heap_Size EQU 0x10" and my program builds/runs as expected.

I've ensured that malloc+new are not used in my code (UNUSED according to the generated static call graph); I left free+delete alone since they are used in more places, but I don't think this matters since I'm not using malloc+new. After digging through the ARM info center, I used "IMPORT __ARM_use_no_argv" and an overridden "__aeabi_atexit" function to achieve this.

As a possibly related side-note, I can't use "IMPORT __use_no_heap_region" because the linker still finds references to malloc+free, resulting in "Error: L6915E: Library reports error: __use_no_heap was requested, but malloc was referenced". I'm not sure why entirely, but maybe because the linker can't remove them explicitly from the library (they still appear in the map file).

Conclusion:
Is there some typical minimum heap size, and/or how is the aforementioned "#0x10" immediate determined? Is it specific to C++ or ArmClang? In another project that uses ArmCC with RTX and C only, the "Heap_Size EQU 0x0" works as expected. Thanks for any help!

  • As I recall the run time library allocator wants to create a linked list, and that's the node size.

    Perhaps instead of setting the size of zero, comment out all the related symbols? __heap_base, __heap_limit

  • The first time I saw an issue with having a heap size of 0 was when I started using C++. I got to the same 16 byte minimum heap size you have found (this was more than 10 year ago). I just went with that. Eventually I found that overriding the __aeabi_atexit() allowed me to set the heap size to 0 again. I can also set #pragma import(__use_no_heap) and #pragma. The #pragma import (__use_no_heap) is very helpful as if you add any library function that uses malloc, the linker will give you an error (rather than having your code fail at run time because malloc failed and you scratch your head because you think you are not ever calling malloc in your code)

    I also found this reference on the forum -

    www.keil.com/.../

  • Westonsupermare Pier:
    I tried to comment out all heap-related variables in startup.s, as well as configure "__user_initial_stackheap" with no heap:

    LDR     R0, = Stack_Mem
    LDR     R2, = Stack_Mem
    


    according to Usage section of this page:
    infocenter.arm.com/.../index.jsp
    However, "_init_alloc" still failed in the same manner. I was also unable to override "_init_alloc" like I did "__aeabi_atexit" (maybe it's not a weak symbol), although I don't think I should be overriding library init functions anyway. The info at
    infocenter.arm.com/.../index.jsp is helpful but doesn't seem to indicate where the 0x10 heap size originates. Do you know of any resources on the "run time library allocator", or any other suggestions?

    Bob McNamara:
    Good to know someone has done this before. As I mentioned, overriding "__aeabi_atexit" did help by removing a malloc call in my code, but I still can't reduce heap size below 0x10. I would love to figure out how to enforce my code with "__use_no_heap", but the linker doesn't seem to be able to remove malloc/free references from included libraries, even though they are marked UNUSED. That seems like a separate issue though, so I'm focusing on getting heap size to 0x0 first and foremost. Any help on getting the linker to not see malloc/free references so I can use "__use_no_heap" is appreciated though.

  • _init_alloc should not be called if you are not using any malloc / free calls. When I have a call to malloc (say from __aeabi_atexit) it clearly shows up in the map file. When I override the __aeabi_atexit then the reference to malloc by __aeabi_atexit is not in the map file. So maybe you can find out what function(s) are referencing the heap by looking in the map file.

    #pragma import(__use_no_heap) does not actually cause the linker to do anything EXCEPT to generate an error if your code makes a reference to the heap. Remove the references to the heap and this error will go away. Make it so your code links with #pragma import(__use_no_heap) and you will be able to set the heap size to 0.

  • Oh okay, thanks for clarifying how the 2 issues are tied together. I understand that I need to enforce "__use_no_heap" to get the heap size to 0x0. So moving on with that goal...

    I'm going to dig through the map and static call graph to hunt down any less-than-explicit references. I can already see "__cxa_allocate_exception" is called by std::array::at() somewhere... I'll update my results after I finish or get stuck.

  • Throwing exceptions does make use of malloc.

    arm_exceptions_alloc.o(.text) refers to h1_alloc_mt.o(.text) for malloc
    

  • I removed all exception-related handling (and added -fno-exceptions flag). This removed all deeper malloc calls and allowed heap size of 0x0! Thank you for your guidance.

    However, the linker still reports: "__use_no_heap was requested, but free was referenced". The only references to free/delete are in generated default class destructors, such as "MyClass::~MyClass__deallocating". I'm not using new/malloc for these classes, so free/delete isn't needed. This may be getting outside the scope of this question and/or embedded environment and more into C++ realm, but is there a way to prevent this automatic delete? I'm so close to enabling "__use_no_heap_region".

  • Just to update for completeness, I finished resolving my issue by overloading the delete operator to prevent referencing free. Now I can enforce the "__use_no_heap_region" flag.