Using __user_heap_base doesn't change the map file

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

Using __user_heap_base doesn't change the map file

1,138 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MaxOnCodeRed on Wed Nov 19 03:56:04 MST 2014
Hi,

I'm using LpcExpresso 7.4.0. I need to change the heap position, so I set the symbol __user_heap_base inside linker option. When I run the program, I see that the heap was changed using my setting, but inside .map file I don't see this change because the __heaps and __end_of_heap remain the same.
Which is the trick ?

Thanks
11 Replies

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Wed Apr 01 05:11:15 MST 2015
This realloc issue has now been fixed in LPCXpresso 7.7.2 which has just been released.

Regards,
LPCXpresso Support
0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Mon Mar 23 04:54:00 MST 2015

Quote: lpcxpresso-support

This does indeed look like an issue in realloc when memory is exhausted. We'll investigate further.



We've now identified the cause of the problem, which will indeed prevent the correct trapping of a realloc when the heap memory becomes exhausted. We will fix this Redlib realloc issue formally in a future LPCXpresso release in the near future (though unfortunately it won't make it into the next release).

In the meantime, I've attached a "beta patch" containing a fix for this, suitable for Cortex-M3 parts such as LPC17xx, for you to evaluate.

To use this:
[list]
  [*]Extract alloc.o from the attached ZIP file into a temp directory.
  [*]Right click on your application project In the Project Explorer view
  [*]Select New -> Folder, calling this folder 'obj'
  [*]Drag and drop alloc.o into the 'obj' folder
  [*]Right click again on your application project, and select Properties
  [*]Goto C/C++ Build -> Settings -> Tool Settings -> MCU Linker -> Miscellaneous
  [*]In "Other objects", click on the Add (+) button, click on Workspace, and navigate to the object file and select it.
  [*]Now rebuild and the local version of the alloc functions should get picked up in preferences to the ones in the Redlib library files.
[/list]

Note: You will need to repeat this for both Debug and Release Build configurations.

Regards,
LPCXpresso Support
0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by EricBI on Sat Mar 21 01:08:27 MST 2015
i'm using a cortex M3 lpc1768.

I Found out that only the realloc from redlib is not working, in newlib it works fine.

I have created a test project on github: epinxteren/memory-allocation-test

<code>
#define MEM_BLOCK 200
#define POINTERS 40000 / MEM_BLOCK

void test_dynamicAllocation() {
    // Enough pointers to go over the 32k of memory.
    void * p[POINTERS];

    uint32_t used_memory = 0;
    uint32_t i = 0;

    /****************
     ** TEST Malloc.
     ****************/
    for (i = 0; i <POINTERS; i++) {
p = malloc(MEM_BLOCK);
if (p) {
used_memory += MEM_BLOCK;
memset(p, 0xAA, MEM_BLOCK);
}
    }

    // Test free
    for (i = 0; i <POINTERS; i++) {
if (p) {
free(p);
p = NULL;
}
    }
    used_memory = 0;


    /****************
     ** TEST calloc.
     ****************/
    for (i = 0; i <POINTERS; i++) {
p = calloc(1, MEM_BLOCK);
if (p) {
used_memory += MEM_BLOCK;
memset(p, 0xAA, MEM_BLOCK);
}
    }

    // Test free
    for (i = 0; i <POINTERS; i++) {
if (p) {
free(p);
p = NULL;

}
    }
    used_memory = 0;


    /****************
     ** TEST realloc with NULL pointer as first argument..
     ****************/
    for (i = 0; i <POINTERS; i++) {
p = realloc(p, MEM_BLOCK);
if (p) {
used_memory += MEM_BLOCK;
memset(p, 0xAA, MEM_BLOCK);
}
    }

    // Test free
    for (i = 0; i <POINTERS; i++) {
if (p) {
free(p);
p = NULL;
}
    }


    /****************
     ** TEST Test realloc, grow and shrink
     ****************/
    void * pointer = NULL;
    int grow = MEM_BLOCK;
    used_memory = grow;
    for (;;) {
void * temp = realloc(pointer, used_memory);
if (temp && used_memory != 0) {
pointer = temp;
memset(pointer, 0xAA, used_memory);
} else {
grow = grow * -1;
}

if (grow < 0 && used_memory <= MEM_BLOCK) {
used_memory = 0;
} else {
used_memory += grow;
}
    }

}
</code>
0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Fri Mar 20 08:07:51 MST 2015

Quote: EricBI
I have a related problem with 'realloc'.   Malloc, calloc, free works fine.



This does indeed look like an issue in realloc when memory is exhausted. We'll investigate further.

For our reference - can you confirm what your target MCU is?

Regards,
LPCXpresso Support

0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by EricBI on Thu Mar 19 13:47:47 MST 2015
I have a related problem with 'realloc'.   Malloc, calloc, free works fine.

This works:
        void * p = NULL;
while (true) {
p = malloc(200);

if (p == NULL) {
exit(1);
}
       }


This works with 'realloc':
        void * p = NULL;
while (true) {
p = realloc(NULL, 200);

if (p == NULL) {
exit(1);
}
       }



Only realloc fails (HardFault_Handler) when resizing:

        void * p = NULL;
        uint32_t size = 200;
while (true) {
p = realloc(p, size);

if (p == NULL) {
exit(1);
}
         
               size += 200;
       }



Using:
- redlib
- lpc1768
- LPCXpresso v7.6.2 [Build 326] [2015-02-02]

Linker config:

Quote:

-Map="${BuildArtifactFileBaseName}.map"
--defsym=_pvHeapStart=0x2007C000
--defsym=__user_heap_base=0x2007C000
--defsym=_pvHeapLimit=0x20083FFF
--gc-sections





0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Tue Feb 03 04:39:13 MST 2015

Quote: lpcxpresso-support

We'll investigate adding start/end symbols for all RAM blocks to managed linker scripts in a future LPCXpresso release though.



This has now been done in LPCXpresso 7.6. Thus you can now define the start / end of heap on the linker command line using commands such as:

--defsym=__user_heap_base=__end_bss_RAM2
--defsym=_pvHeapLimit=__end_bss_RAM2+0x800


Regards,
LPCXpresso Support
0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Sat Nov 22 07:55:57 MST 2014
Theoretically you can set __user_heap_base to have the value of any symbol already defined in the linker script, which should allow you to do what you want.

Unfortunately at the current time, the managed linker script mechanism doesn't generate a symbol automatically to mark the end of data/bss sections except for the 1st RAM block. Thus you would need to turn off the managed linker script mechanism and manually modify the linker script to include such a symbol - which you could then reference.

We'll investigate adding start/end symbols for all RAM blocks to managed linker scripts in a future LPCXpresso release though.

Regards,
LPCXpresso Support.

0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MaxOnCodeRed on Fri Nov 21 08:17:20 MST 2014
Hi,

I want to tell you that when you place the heap at specified address (using __user_heap_base and _pvHeapLimit linker symbols), and use the macro to place a variable in a specified segment (__BSS(RAM2) uint32_t my_var), the linker doesn't check if they can overlay each other. So to determinate a free starting address to assing to __user_heap_base, it is necessary to go in the map file and check the last used address.
Is it possible to inform the linker to detect this overlay ?

Thanks
0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Wed Nov 19 08:08:00 MST 2014
OK, I now understand what is confusing you.

In the linker map file, regardless of whether you have defined __user_heap_base, you are seeing the line similar to:

                0x02000034                _pvHeapStart = DEFINED (__user_heap_base)?__user_heap_base:.


[where 0x02000034 is the address in RAM where the heap is starting 'by default', which will depend on the target MCU and your application itself].

However if you look higher up the map file in the case where you define __user_heap_base, you will have line such as

               0x10003000                __user_heap_base = 0x10003000


[where 0x10003000 is the address I passed in on my linker command line.]

Your confusion comes from the fact that you are expecting to see in the case where you have defined __user_heap_base something like:

                0x10003000                _pvHeapStart = DEFINED (__user_heap_base)?__user_heap_base:.


Unfortunately this isn't what the linker actually does in the map file. But note that your code will actually use the value from __user_heap_base in your actual application. You will be able to see this when you debug, or if you process the AXF file using the "arm-none-eabi-objdump -t" command.

If you want to see the real heap start in the map file in this case, then we need to add a line to the linker script file to output the final value of _pvHeapStart. I've attached a linker script template file that will cause this to be done so that you will see the following in the map file:

                0x02000034                _pvHeapStart = DEFINED (__user_heap_base)?__user_heap_base:.
                0x10003000                _actual_pvHeapStart = ABSOLUTE (_pvHeapStart)


For details of how to use a linker script template, please see:

http://www.lpcware.com/content/faq/lpcxpresso/linker-script-templates

Regards,
LPCXpresso Support

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MaxOnCodeRed on Wed Nov 19 06:58:27 MST 2014
Hi,

I'm using your the LpcOpen2_10 lwip_tcpecho_sa project with LpcExpresso 7.4.0. Could you try to insert the linker symbols like in the image and then Build the project. Then you could check the map file.
[img]http://www.lpcware.com/system/files/linker_sym.JPG[/img]
Thanks
0 Kudos

848 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Wed Nov 19 06:21:26 MST 2014
See:

http://www.lpcware.com/content/faq/lpcxpresso/heap-checking-redlib

Also, if you originally created your project with a version of LPCXpresso prior to v7.4.0, ensure that you delete the Debug/Release directory so as to force a recreation of the managed linker scripts.

If you are still having problems, please provide a project showing the problem,

http://www.lpcware.com/content/faq/lpcxpresso/how-importexport-projects

or else specify exactly what you have done, and also post your build log showing the actual link command, plus generated linker script and map files

http://www.lpcware.com/content/faq/lpcxpresso/build-console

Regards,
LPCXpresso Support
0 Kudos