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

Malloc returns NULL

Setup

Keil: uVision 5.17.0.0
ARM: LPC1768
A standard project with some UARTS and I2C
"Use memory Layout form target" is checked (using the standard scatter file)
"Use MicroLIB" is not checked

from startup_LPC17xx.s
Heap_Size EQU 0x00002000

AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit

Problem
Any call to malloc returns NULL, that is, the system can not allocate memory.

Why does not the mallco work, is my only options to
1) Use microLIB
2) Implement _init_alloc() and __rt_heap_extend() on my own

?

Regards Stefan

Parents
  • 1) Stop making any calls to _init_alloc.

    2) You should be getting a link error on TEST2, no compile error. See #4 below. This would only seem to be if you exported __heap_limit, __heap_base and __initial_sp. If you export these, it will compile and link fine using both microlib and standardlib, but will not actually work in standardlib mode. Did you somehow change the standard code in a way that these variables were exported when not using the microlib? You may notice in the map file that sys_stackheap_outer.o references a __user_inital_stackheap that resides in sys_stackheap_outer.o when these are exported. If you do not export these variables, it will reference the __user_initial_stackheap in YOUR startup.s file. This is why your __user_initial_stackheap is not being called. i.e. You are not using the "standard" code at all, you have modified it to not work and then complained about it not working.

    3) Look at your map file

    USING:__user_setup_stackheap,
    
    your map file should show __rtentry4.o referencing __user_setup_stackheap in your startup.s file.  There is no reference to __user_initial_stackheap.
    
    USING: __user_initial_stackheap
    
    your mapfile should show sys_stackheap_outer.o referenceing __user_initial_stackheap in your startup.s file.  You will also see __user_setup_stackheap referenceing sys_stackheap_outer.o
    

    4) I have never seen __heap_limit defined as a variable when not using the microlib. I think the "standard" startup code is very specific in NOT creating a __heap_limit or __heap_base variable when not using the microlib. Don't define this as a variable.

Reply
  • 1) Stop making any calls to _init_alloc.

    2) You should be getting a link error on TEST2, no compile error. See #4 below. This would only seem to be if you exported __heap_limit, __heap_base and __initial_sp. If you export these, it will compile and link fine using both microlib and standardlib, but will not actually work in standardlib mode. Did you somehow change the standard code in a way that these variables were exported when not using the microlib? You may notice in the map file that sys_stackheap_outer.o references a __user_inital_stackheap that resides in sys_stackheap_outer.o when these are exported. If you do not export these variables, it will reference the __user_initial_stackheap in YOUR startup.s file. This is why your __user_initial_stackheap is not being called. i.e. You are not using the "standard" code at all, you have modified it to not work and then complained about it not working.

    3) Look at your map file

    USING:__user_setup_stackheap,
    
    your map file should show __rtentry4.o referencing __user_setup_stackheap in your startup.s file.  There is no reference to __user_initial_stackheap.
    
    USING: __user_initial_stackheap
    
    your mapfile should show sys_stackheap_outer.o referenceing __user_initial_stackheap in your startup.s file.  You will also see __user_setup_stackheap referenceing sys_stackheap_outer.o
    

    4) I have never seen __heap_limit defined as a variable when not using the microlib. I think the "standard" startup code is very specific in NOT creating a __heap_limit or __heap_base variable when not using the microlib. Don't define this as a variable.

Children
  • It works now as expected, it was all related to one of all of the added lines at the top of startup_LPC..

                    EXPORT  __initial_sp
                    EXPORT  __heap_base
                    EXPORT  __heap_limit
    


    If any of them, even if the program only have "EXPORT __initial_sp" (and not the other two) the heap dont get initalized. If none of them are exported then the runtime library will call __user_initial_stackheap as expected.


    It is neccessary to export a new/seperate variabel if the stack top is going to be used
    somewhere else, like this

                    EXPORT  __initial_stack_top
    
    
    Stack_Size      EQU     0x00000800
    
                    AREA    STACK, NOINIT, READWRITE, ALIGN=3
    Stack_Mem       SPACE   Stack_Size
    __initial_sp
    __initial_stack_top
    


    One interesting observation was that if the program had

                    EXPORT  __initial_sp
                    EXPORT  __heap_base
                    EXPORT  __heap_limit
    
    The map file will contain
    __rtentry4.o(.ARM.Collect$$rtentry$$00000004) refers to sys_stackheap_outer.o(.text) for __user_setup_stackheap
    sys_stackheap_outer.o(.text) refers to startup_lpc17xx.o(.text) for __user_initial_stackheap
    
    But they was never called
    



    Conclusive:
    Dont export any of __initial_sp, __heap_base or __heap_limit form the startup_XXXX.s