Using a "placement new" to locate an object outside the heap

07 Feb 2012

Hi All,

I've been working on a project that manages 128 I/O pins through the use of some I2C expanders. The problem is, once I load up the code, I'm left with 8K of heap - not enough to even load the LWIP stack and run it.

Because the hardware configuration is static between boots, I was thinking of using the "other 32K" of RAM on the board.

Is this the right approach or are there any hints on how to scrounge back some RAM?

Thanks,

Anthony

07 Feb 2012

Do you use mbed libs? After I replaced mbed libs by own code I could reduce memory consumption from 21kB down to1.6kB

07 Feb 2012

Hi Rene,

I am using the Mbed libs as I am using the online compiler. I don't really want to go to offline - the online approach (zero tools) was part of the appeal of the Mbed...

Mbed folks: Is there any optimisation possible on the compiler? Whilst it is plug&go at the moment, there aren't any nerd-nobs to tweak either the build process or the code that's output

Anthony

14 Feb 2012

I have used the following code in the past to call from the beginning of my program to dump how much memory has been used up in each of the RAM banks by the compiler for statics and globals.

// These external symbols are maintained by the linker to indicate the
// location of various regions in the device's memory.  They will be used by
// DisplayRAMBanks() to dump the size of each RAM bank to stdout.
extern unsigned int Image$$RW_IRAM1$$Base;
extern unsigned int Image$$RW_IRAM1$$ZI$$Limit;
extern unsigned int Image$$RW_IRAM2$$Base;
extern unsigned int Image$$RW_IRAM2$$ZI$$Limit;
extern unsigned int Image$$RW_IRAM3$$Base;
extern unsigned int Image$$RW_IRAM3$$ZI$$Limit;


// Displays the size of static allocations for each RAM bank as indicated by
// ARM linker to stdout.
static void DisplayRAMBanks(void)
{
    printf("Static RAM bank allocations\r\n");
    printf("  Main RAM = %u\r\n", (unsigned int)&Image$$RW_IRAM1$$ZI$$Limit - 
                                  (unsigned int)&Image$$RW_IRAM1$$Base);
    printf("  RAM0     = %u\r\n", (unsigned int)&Image$$RW_IRAM2$$ZI$$Limit -
                                  (unsigned int)&Image$$RW_IRAM2$$Base);
    printf("  RAM1     = %u\r\n", (unsigned int)&Image$$RW_IRAM3$$ZI$$Limit -
                                  (unsigned int)&Image$$RW_IRAM3$$Base);
}

To move a global from main RAM to the RAM0 bank, you can declare it something like:

__attribute((section("AHBSRAM0"),aligned)) char LargeBuffer[1024];
17 Jun 2012

Have you tried this code?

I get a compile error, complaiing about symbols:

Apparently Image$$RW_IRAM2$$ZI$$Limit and Image$$RW_IRAM3$$ZI$$Limit do not exist?

Is using Image$$RW_IRAM2$$Limit and Image$$RW_IRAM3$$Limit the correct thing to do?

17 Jun 2012

Still works for me in the online compiler. Did you just copy the function and not the extern's as well?

#include "mbed.h"

DigitalOut myled(LED1);

static void DisplayRAMBanks(void);

int main() 
{
    DisplayRAMBanks();
    
    while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }
}

// These external symbols are maintained by the linker to indicate the
// location of various regions in the device's memory.  They will be used by
// DisplayRAMBanks() to dump the size of each RAM bank to stdout.
extern unsigned int Image$$RW_IRAM1$$Base;
extern unsigned int Image$$RW_IRAM1$$ZI$$Limit;
extern unsigned int Image$$RW_IRAM2$$Base;
extern unsigned int Image$$RW_IRAM2$$ZI$$Limit;
extern unsigned int Image$$RW_IRAM3$$Base;
extern unsigned int Image$$RW_IRAM3$$ZI$$Limit;


// Displays the size of static allocations for each RAM bank as indicated by
// ARM linker to stdout.
static void DisplayRAMBanks(void)
{
    printf("Static RAM bank allocations\r\n");
    printf("  Main RAM = %u\r\n", (unsigned int)&Image$$RW_IRAM1$$ZI$$Limit - 
                                  (unsigned int)&Image$$RW_IRAM1$$Base);
    printf("  RAM0     = %u\r\n", (unsigned int)&Image$$RW_IRAM2$$ZI$$Limit -
                                  (unsigned int)&Image$$RW_IRAM2$$Base);
    printf("  RAM1     = %u\r\n", (unsigned int)&Image$$RW_IRAM3$$ZI$$Limit -
                                  (unsigned int)&Image$$RW_IRAM3$$Base);
}
18 Jun 2012

I have the externals. I also use MSCFileSystem, an LCD library, and the CAN library.

The compiler does not like the "print... RAM0... " and RAM1 lines unless I remove the $$ZI from each line.

18 Jun 2012

Sorry, I can't reproduce your problem. The code compiles and links Ok with the online compiler if I create a new program and paste in the code above. I also tried the Export version of the mbed library and another sample I have which actually places data in the RAM0 and RAM1 areas and they all compile/link with no problems. There must be something particular about your code that causes problems but without access to your code, I am not likely to figure out the problem.

Dropping the $$ZI might not give the whole story if you are actually placing zero initialized variables in these sections. However maybe your code has globals in these sections but they are all initialized to non-zero values and that is what is causing my code to generate errors.

Things to note about my environment:

  • Not using the Beta mbed compiler.
  • Compiling for LPC1768 version of the mbed.
  • Using version 43 of the mbed libraries.

-Adam

10 Feb 2014

Hi,

This thread has been quiet for ages, but I'm running into issues around which section of RAM things are located in. Is there any way of forcing system libraries into the main bank? From DisplayRAMBanks, I get:

Static RAM bank allocations
  Main RAM = 13348
  RAM0     = 16384
  RAM1     = 11348

And without forcing things around certain things break. Or start working again. RAM0 seems pretty full and it seems like pure luck whether I'll get a properly working binary or not. When it does hit a limit, the Watchdog kicks in and resets the system. I'm using the following libraries with one SPI device, (which on their own or a less complex combination) work fine on their own.

#include "mbed.h"
#include "rtos.h"
#include "EthernetInterface.h"
#include "NTPClient.h"
#include "WatchDog.h"
#include "HTTPClient.h"

EthernetInterface, from a casual look around the forums, seems to cause a headache or two vis-a-vis RAM, so I'm wondering if that's eating too much of RAM0 and if placing it into the main bank wouldn't help.

Any suggestions or hints would be very welcome.

10 Feb 2014

One of the two extra RAMs is used for ethernet purposes, dunno which one, but if RAM0 is full then that is probably it. While other code can get access to it, by default the compiler should never place anything in it (outside of ethernet related stuff, and USB iirc can also use one of the other RAM banks).