Maximising available SRAM on the Arduino.

“Our situation has not improved.” – Henry Jones.

I ran into a strange problem recently with an Arduino project that I was working on. The existing code had been working perfectly up to that point, but I needed to add some more code for additional functionality. As soon as I did that however, I started having really strange run-time behaviour where other parts of the code would start misbehaving. I was able to trace it to my variables becoming corrupted in memory. For example:

void function()
{
	String strString;

	strString = "This is a string, obviously.";

	Serial.println(strString);
}

Simple right? You’d expect the Serial port to display “This is a string, obviously.”. However, instead I would find part of the string corrupt. This was most odd as the code that I had added was quite innocuous. In fact, the code that I added wasn’t the code with the problem. I added a new function at the end of the code, and one of the earlier functions started misbehaving. I’d then comment out the new function, and it would work.

Very strange. I decided to upgrade the version of the Arduino IDE I was using to the new beta version. That didn’t fix the problem, however what I did notice when I compiled was additional information that I hadn’t previously seen (it was new in the updated IDE).

Compiler Status

Ahhh. That’s interesting. This isn’t the screenshot of the issue I was having at the time, but you get the point. What this is telling me is that the application itself is using 7% of the 32K of onboard flash memory. The SRAM however, which is the memory used to host run-time variables has a limit of 2K (on this particular microcontroller). According to this, I’ve got 1.8K free. At the time, I found I actually had only 200-300 bytes free, yet that was still causing an issue (the run-time variables were exceeding that).

So, strange behaviour with your code – chances are you’re running out of SRAM. I did an analysis of my code and I realised that I had quite a few string variables (I send a lot of Serial debug messages and Syslog messages). After doing some digging, it turns out that you can actually pre-store some of your static variables (variables that you won’t change during run-time) in the flash memory with the code itself. Fantastic!

It turns out that the Arduino code set provides a macro that allows you to store a variable in flash. Realistically the macro tells the compiler to store the memory in flash, and then provides instructions for how to retrieve that information during run time.

void function()
{
	String strString;

	strString = F("This is a string, obviously.");

	Serial.println(strString);
}

Well that’s easy. Now that string is populated from flash. Granted its still copied into memory for use, but I can now move a lot of variables out of SRAM until they are actually needed by the code (all of the functions don’t store all of their variables in memory all of the time). This was all well and good, but the data-type returned by the F() function caused a few issues with some other functions I was using. Some functions must have a String variable provided, some functions must have a character array (char *) variable provided. To make this easier, I created a couple of macros of my own.

#define SF(x) String(F(x))
#define CF(x) String(F(x)).c_str()
void function()
{
	String strString;

	strString = SF("This is a string, obviously.");

	Serial.println(strString);
	Serial.write(CF("test string"));
}

For any times when you need a character array, you can simply use the CF() function. If you need a string, then you can use the SF() function. Either define those macros at the top of your code, or introduce them into one of the base header files in the Arduino library.

I used that where appropriate in my code, and the available SRAM was significantly increased bringing stability back to my application.

~ Mike

One thought on “Maximising available SRAM on the Arduino.

  1. Hi Mike and thanks for this excellent post.
    I’m using an arduino pro mini 3,3 with a mpu 6050, ble and sim 800c.
    Take data from mpu sensor read a beacon with ble and send for sms this data.
    All work fine, but when I send AT+CCLK to sim800 for date and hour don’t work.
    This AT command work perfect in a separate sketch, but not in the LONG sketch with ble and sensor.
    I think maybe is a ram problem behavior, not have any error message, only a empty string response.
    Is this kind of behavior a low ram ?
    the sketch is to long and messy, but I’m newly in arduino and embedded code.
    1000 thanks and sorry my eng.
    atte.
    Emilio Machado

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s