Trouble configuring heap

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Trouble configuring heap

1,375 Views
scottm
Senior Contributor II

I've got a CodeWarrior 10.7 project for a K22F that needs more heap space.  I very rarely make any serious use of the heap in embedded projects so I haven't had cause to mess with it before and I'm a little confused.  I need to enlarge the heap and relocate it to SRAM_U but I'm not having much luck.

 

__heap_size is set properly in the linker .ld file.  Changing it has no effect.  Removing it has no effect.  I've relocated __heap_addr into SRAM_U and the map file shows the symbol is at the expected address above 0x2000 0000, but it's still allocating from SRAM_L.  As far as I can tell it seems to be starting at the .end symbol.  Putting a bit of padding before .end shifts it up by that amount.

 

I've been through the EWL docs.  I've rebuilt the libraries with _EMBEDDED_WARRIOR_MALLOC = 1, and it *looks* like it's using the expected allocator.  The EWL docs mention a few symbols required for the allocator, but they don't show up in my map file, which makes me suspect it's either not set up right or I'm looking at documentation for the wrong thing.

 

The __heap_size symbol only seems to affect the heap+stack reservation, which just throws an error if there's not enough space between .end and SP_INIT.

 

stack_safety also seems to be ignored, and I think that's causing my more immediate problem - I've got a malloc() call causing a hardfault rather than returning NULL and I think it's because the heap (which has failed to be relocated) and the stack are colliding.  This is not good.  I'm only making significant use of the heap for interactive functions where it's OK to fail and tell the user there's not enough memory, but I can't do that if malloc() isn't allowing for a minimum separation from the stack.  If I can get it into SRAM_U, with the stack in SRAM_L, then I won't have to worry about the two colliding and I can make sure that nothing is above the heap.  I just can't figure out how to relocate it.

 

What am I missing?

 

Thanks,

 

Scott

Labels (1)
7 Replies

996 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Scott

After looking into this issue, we have found the problem:

First of all, you need to defined your _estack as CW have it in default:

_estack = 0x20000000;    /* end of lower SRAM */
__SP_INIT = _estack;‍‍

Now, you need to defined the stack and heap separated,  one in m_data and the other onne in m_data_20000000, so you can define:

    ._user_stack :
  {
    . = ALIGN(4);
     . = . + __stack_size;
    . = ALIGN(4);
  } > m_data
  
  ._user_heap :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
         __heap_addr = .;
    . = . + __heap_size;
    . = ALIGN(4);
  } > m_data_20000000‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Now, the problem here is that malloc function uses sbrk fucntion, which verify that your heap is no bigger than stack, because it guess that you going to keep both in the same memory. So you need to redefine this function in your main.c file with your custom use, in this case I comment the lines that verify this:

void *sbrk ( uint32_t delta )
{
extern char _end; /* Defined by the linker */
static char *heap_end;
char *prev_heap_end;
 
  if (heap_end == 0) {
    heap_end = &_end;
  }
 
  prev_heap_end = heap_end;
  //if (prev_heap_end+delta > get_stack_pointer()) {
  //       return (void *) -1L;
  //}
  heap_end += delta;
  return (void *) prev_heap_end;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

And with all this change then you can realocate your heap in 20000000 and up, and keep your stack in 20000000 and down.


Hope this information helps you
Have a great day,
Jorge Alcala

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

996 Views
scottm
Senior Contributor II

Thanks, that's about what I came up with myself but I was thinking I must be missing something.  Any chance of getting the EWL documentation updated to reflect the current version?

Thanks,

Scott

0 Kudos

996 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi

Could you provide more information of how you are relocating heap address? your linker file or the code that you use?

__heap_size actually has a important part here, if you check the linker file it is used in

    ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
         __heap_addr = .;
    . = . + __heap_size;
    . = . + __stack_size;
    . = ALIGN(4);
  } > m_data‍‍‍‍‍‍‍‍‍‍

and m_data is defined in 0x1FFF0000, so even you defined heap address in 0x2000000, it can used 0x1FFF0000 and bigger. so you need to change m_data to m_data_20000000 if you want to use your heap in 0x200000000.

the compiler uses __SP_INIT to defined the address to stack and heap, so you need to change the limit of this address, because it is defined with a max of 0x20000000, so:

_estack = 0x20000000+192K;    /* end of lower SRAM. NOW is the end of upper SRAM */
__SP_INIT = _estack;‍‍


Hope this information helps you
Have a great day,
Jorge Alcala

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

996 Views
scottm
Senior Contributor II

Hi,

I'm still stuck on this problem.  The documentation doesn't seem to match the behavior of the allocator.  Is the documentation wrong, or am I missing a step?

Thanks,

Scott

0 Kudos

996 Views
scottm
Senior Contributor II

Hi,

I'd prefer to keep the stack and heap separated and not growing toward each other, if possible.  The EWL C Reference, rev 10.x, page 22, says the symbols HEAP_START, SP_INIT, stack_safety, and mem_limit must be defined for _EMBEDDED_WARRIOR_MALLOC.  As far as I can tell, that's the enabled malloc() function.  Is that not the proper documentation?  If not, where can I find the default allocator's behavior defined?

Thanks,

Scott

0 Kudos

996 Views
phantomgz
Contributor III

Hi Scott,

  As my guest, you are using Processor Export for your project. PE setting project's stack and heap in it's Cpu component, in Inspector of cpu component  there is a "Build options" tab, there is a entry name "Generate linker file"

pastedImage_1.png

If you want PE handle the ".ld" file, set "Generate linker file" = yes, and change setting for "Stack size" and "Heap size". every time Generate Precessor Code, PE will reflash the ".ld".

if =No, you can handle ".ld" by your self.

Regards,

Cai

0 Kudos

996 Views
scottm
Senior Contributor II

Hi Cai,

I must have deleted a paragraph out of my original question because I remember writing up an explanation that I'd done exactly this.  Changing the heap size setting in PEx does nothing more (as far as I can see) than changing __heap_size in the .ld file.  It doesn't seem to be enforcing separation between heap and stack, and it doesn't let me relocate the heap.

malloc() is sometimes failing with a hardfault and I believe this must be because it's colliding with the stack.  I want to put the heap in SRAM_U where there is nothing between the heap and the top of memory.

Thanks,

Scott

0 Kudos