8 years, 10 months ago.

mbed LPC1768 Memory

Using mbed LPC1768, after compile of the program, in the right screen of "Program detail" -> "build" table, it was displayed that:

Flash: 52.2 KB Ram: 8.4 kB

but when I run it, it stuck!

Please can you me some suggestions? Thank you.

Can you edit the question and add your code. There is no way to tell what is going on.

posted by Paul Staron 09 Jul 2015

How do you know you are running out of memory rather than the program crashing?

The numbers from the compiler only include statically allocated memory, they don't include dynamically allocated memory on the heap or the stack since the compiler has no easy way to calculate that. Depending on your code it is possible to run out of memory no matter what the compiler claims.

posted by Andy A 09 Jul 2015

I use the sampling and signal processing. The thing is when set the sample_numb = 1024, it is working well. But if sample_numb = 2048, it is stuck. As the program is little large, I just list the two lines below:

sampling_freq = 40000;

sample_numb = 2048;

According to your opinions above, it is dynamical memory problem? It looks like that.

But if so, how can I manage dynamic memory? Thank you.

posted by Zhichao Zhang 09 Jul 2015

1 Answer

8 years, 10 months ago.

You manage dynamic memory by understanding knowing what the compiler does when you declare a variable. It would be easier to tell exactly what is going on if you posted some code rather than expecting us to guess or use telepathy.

Assuming you aren't using USB (other than the debug serial port), ethernet or CAN then there is an extra 32k of RAM available. Create the storage as global variables using:

static float BigBuffer[4096] __attribute__((section("AHBSRAM0"))); 
static float BigBuffer2[4096] __attribute__((section("AHBSRAM1"))); 

The attribute tells the linker to place that variable in the AHB ram block normally used for network buffers. There are 2 blocks (AHBSRAM0 and AHBSRAM1), each 16k. Floats are 4 bytes each, 16k/4 = 4k values max. If you use larger data structures then reduce the length of the array.

If you want a single large array of the same object then since the two memory blocks are next to each other and c doesn't check the limits on arrays you can cheat a little and read past the end of the first array. For the example above you could treat bigBuffer as an array of 8192 floats and it would work fine as long as you didn't try to also use bigBuffer2.

This will only work on the online compiler. Other compilers/linkers you'd need to use a different command.

There are other tricks to reduce memory use. e.g. are you using doubles? If so switch to using floats, it's 4 times faster, uses half the ram and is almost certainly good enough for what you want.

Accepted Answer

Thank you for your commends. After I delete the two lines below:

  1. include <stdio.h>
  2. include <iostream>

The Flash and Ram are both smaller: Flash: 35.1 KB, Ram: 0.9 KB. Now sample_numb = 2048 is working. But for bigger sample_numb, 3072, 4096, still not working.

I tried to paste the program here, but it was limited for the size 3000, how can I do that? Thank you.

The link is below:

https://developer.mbed.org/users/ZZhang/code/AC_sampling_05_1768_discussion/

posted by Zhichao Zhang 10 Jul 2015

For something that size the best option is to publish it and post a link here. In the compiler click on commit, that saves your current code into the version control system. Then click on the down arrow next to commit and click publish. Select to publish it as a program and make it either public (will show up in search results) or unlisted (anyone can view it but it won't show up in search results). You can then post a link to the project page here and other people can view or import the code.

At any time you can go to the project page and under Admin settings you can change the project to private so that no one else can see it.

Any changes you make after hitting publish are private to your account unless you commit it and then publish it again. When you publish a version all of the committed versions prior to that point are included in the project history.

posted by Andy A 10 Jul 2015

Thank you, Andy. The link of the code is below, please have a look. Thank you.

https://developer.mbed.org/users/ZZhang/code/AC_sampling_05_1768_discussion/

posted by Zhichao Zhang 10 Jul 2015

As expected almost all your memory is being allocated dynamically. Around line 53 of AC_sampling_05.cpp you have

    sample_valu = new float [sample_numb];
    period_record = new int [sample_numb];  
    max_array = new float [sample_numb];

The new command dynamically allocates memory for the data while the program is running. The compiler can only report memory that is allocated before the program starts to run. You are requesting 2 floats and 1 int = 12 bytes per sample. 2048 samples = 24k. Further down you use new to create another array of 101 floats, that's another 0.4k.

The compiler indicated 0.9k used so 25.5k are accounted for.

Almost all of your objects are being created on the stack (e.g. your Samples_stru object is local to main rather than being global) and so their memory requirements also aren't being reported by the compiler.

In short after the first 10 lines of main() your memory usage has gone from 0.9k to around 30k.

If the system can't allocate enough memory when you call new it returns a null pointer. You never check for this possibility, your program tries to use the invalid pointer and crashes. For debugging the following changes

    sample_valu = new float [sample_numb];
    if (!sample_valu)
      pc.printf("OUT OF MEMORY allocating sample_valu!\n");
    period_record = new int [sample_numb];  
    if (!period_record )
      pc.printf("OUT OF MEMORY allocating period_record !\n");
    max_array = new float [sample_numb];
    if (!max_array )
      pc.printf("OUT OF MEMORY allocating max_array!\n");

and similar lines after every instance of new or malloc would make this sort of thing a lot easier to find in the future.

As a quick fix put these two lines right at the start of AC_sampling_05.cpp

static float sampleBuffer[4096] __attribute__((section("AHBSRAM0"))); 
static float maxBuffer[4096] __attribute__((section("AHBSRAM1"))); 

and then in void Samples_stru::Initialization() change the values of sample_valu and max_array to being

    sample_valu = sampleBuffer;
    period_record = new int [sample_numb];  
    max_array = maxBuffer;

That will move the two float buffers out of main memory and so free up a lot of memory without requiring any significant code changes. Everything should then work for values of sample_numb up to 4096. Go over that and everything will fall to pieces and crash.

Going over that size would need some significant reworking to reduce memory usage.

As a general style point dynamic memory allocation like this isn't a good idea for embedded code, it has it's uses but should be avoided whenever possible. If you know how much memory you will need when you compile the code then allocate it statically instead if using new or malloc, it's far easier to debug code when the compiler can tell you the problem rather than trying to track down the cause of a random crash.

posted by Andy A 10 Jul 2015

Thank you very much Andy! Now for sample_numb = 4096 is working.

It seems for LPC1768, the case of sample_numb=8192 is impossible, is it true ?

If it was that, for QSB LPC4088, it should be no problem? Thank you.

posted by Zhichao Zhang 13 Jul 2015

Your memory useage is about 8k + 12k for each 1024 samples. So 2048 samples takes 32k, 4096 takes 58k and 8192 samples would take 104k.

So any mbed with over 104k of ram should work for 8k samples.

It may also be possible to re-work the code to reduce the memory usage.

posted by Andy A 14 Jul 2015