Increase of the standard 32kB by altering memory layout in LPC1768.sct

10 Mar 2013

Dear all,

We have a very complex program and currently we are experiencing problems with MBED crashing. The most likely cause is related to the RAM memory usage of our program.

Anyhow, MBED has 64kB from which for the standard user's program one can only access 32kB. We would like to increase this standard available 32kB by using some of the additional 32kB RAM that MBED has available.

(For the interested among you I have gathered some forum links related to this topic: http://mbed.org/forum/mbed/topic/579/, http://mbed.org/forum/mbed/topic/2203/, https://mbed.org/forum/helloworld/topic/4265/)

So the way of doing so, if you are sure you don't use them for CAN or ethernet, appears to be placing your static or globals variables on the additional memory banks as follows:

static char buf1[0x2000] __attribute__((section("AHBSRAM0")));

However, in our case this solution would be quite cumbersome as we have many smaller globals or static variables (instead of only a few large buffers) for which each instantiation would have to be changed. This proved difficult.

Another way of using some of the additionally available 32kB RAM might be changing the memory layout in LPC1768.sct. /media/uploads/raalst1/lpc1768.sct (or have a look at: http://mbed.org/users/screamer/code/mbed/file/976df7c37ad5/LPC1768/ARM/LPC1768.sct)

Is it possible to change the memory layout by altering this LPC1768.sct file?

RW_IRAM1 0x100000C8 0x7F38 { .ANY (+RW +ZI) }

For example increase it to 55kB by just changing the 0x7F38 (32kB) to 0xD6D8 (55kB)? What about the starting addressess?

An example of how this should be correctly done would help. Especially how to cope with the memory starting addresses?

10 Mar 2013

I looked into a similar thing but there appears to be no easy way to do it, the problem being the memory regions are not contiguous. I don't think there is a way to tell the linker to "daisy chain" segments.

It seems that the user must make explicit memory assignment. Rather than use section attributes, an alternative might be to use wildcards within the link file to assign modules to different regions. If you had a naming convention subsystem_module name, then you could collect all the data for a subsystem using "subsystem_*.o (+RW, +ZI)".

10 Mar 2013

Dear Bob,

Thanks for the reply.

I do not really understand the use of wildcards and naming convention subsystem?

Quote:

Rather than use section attributes, an alternative might be to use wildcards within the link file to assign modules to different regions. If you had a naming convention subsystem_module name, then you could collect all the data for a subsystem using "subsystem_*.o (+RW, +ZI)".

So what solution did you use? Could you give an example of the changes made to do so?

10 Mar 2013

Wildcards are pretty straightforward, any filename matching the wildcard is placed in that section. You can see an example in the sct files you linked to. "*.o" collects all files with a ".o" extension.

Therefore if you have files buf_read.c and buf_write.c then a wildcard "buf_*.o" would refer to all files starting with "buf_". So for example, if you put all your gui related code into files starting "gui_" then it is easy to collect them together.

If wildcards are not suitable for your project then you can specify individual files. This may be quicker/easier than adding section attributes throughout your code.

e.g.

  RW_IRAM1 0x100000C8 0x7F38  {
    main.o    (+RW +ZI)
    file1.o    (+RW +ZI)
    file2.o    (+RW +ZI)
  }
  RW_IRAM2 0x2007C000 0x4000  {  ; RW data, ETH RAM
   .ANY (AHBSRAM0)
    file3.o    (+RW +ZI)
    file4.o    (+RW +ZI)
  }
  RW_IRAM3 0x20080000 0x4000  {  ; RW data, ETH RAM
   .ANY (AHBSRAM1)
    file5.o    (+RW +ZI)
    file6.o    (+RW +ZI)
  }

Note, I think you can join the two extra segments because they are contiguous, if you are not using them for peripheral buffers:

  RW_IRAM2_3 0x2007C000 0x8000  {  ; RW data
    file3.o    (+RW +ZI)
    file4.o    (+RW +ZI)
    file5.o    (+RW +ZI)
    file6.o    (+RW +ZI)
  }
10 Mar 2013

Thanks! This clears things up.

In the meanwhile I moved some variables throughout the code with use of

<<code >> __attribute__((section("AHBSRAM0"))); <</code>>.

This gave me just enough RAM memory left to execute the program without MBED crashing.

However, the RAM memory left is still on its limits to let it execute properly (tricky) so I fancy your proposed solution of putting certain files explicitly on the other RAM memory banks. That seems like a good (cleaner) way to do it.

10 Mar 2013

Bob, I've tried your suggestion of altering the LPC1768.sct file by making explicit TheFile.o on RW_IRAM2.

In the previous case, that I put certain global arrays defined in TheFile.cpp on AHBSRAM0 via use of attribute((section("AHBSRAM0"))), I would see the RAM memory usage (the percentage) drop after compiling and looking at the build details.

However, now I have implemented it differently, via altering the LPC1768.sct file, I do not see this reduced usage of the RAM Memory. I would expect this though, as now the whole file and its variables are allocated to AHBSRAM0?

Why isn't this the case? Like this it doesn't seem to sort the desired effect.

10 Mar 2013

Another possible approach is the one that we use in our Astrobe (Oberon language) IDE. We just set the start of the heap to the AHBSRAM address so that all dynamically allocated variables go there, leaving more space for locals and globals in the CPU RAM. See:

"Using the additional 16 / 32kB of RAM on LPC175x/6x MCUs"

http://www.astrobe.com/forum/viewtopic.php?f=7&t=267

Somebody else might be able to advise if and how that can be done using the LPCXpresso IDE.