Optimising SRAM usage on a ATmega328P.

I’ve been attempting to use the Atmega328P as a sort of intermediary that processes requests from a computer and sends commands to an Adafruit GPS (MK3339) unit, then saves the data to EEPROM. I’m still testing a few things, and I do plan to change the design (such as adopting an external EEPROM), but anyway, that’s the rough context.

So far, things have been peachy – but as I’ve started integrating control elements to allow changes during runtime (chip gets a request over serial, trips a switch, sends back a dump of EEPROM contents), I’ve run into memory issues, specifically with the SRAM.

The problems I’ve observed and things I’ve done.

  • Running the sketch and sending messages to the chip over serial is fine initially, but then the second message ends up crashing the chip (so I gather since it resets automatically).

  • I ran some tests to check the RAM usage and got the following numbers (Point 1:1073, Point 2 :-1219). Point 1 being before the CarryOutCommands function, Point 2 aftewardsr. So I’m definitely exceeding the RAM’s capacity, right?

  • I’ve optimised the code to the best of my knowledge, but it’s possible I might have overlooked or mistaken something. I think the CarryOutCommands function is suspect; I feel I’m overthinking what should just be a simple operation.

I’m a little lost at the moment in regards to my options. Either I’m carrying out the optimisation incorrectly (probable), or it would be better to just upgrade to something with a bit more memory than an Atmega328P to fit my needs.

((I’ve added the code as an attachment since it wouldn’t let me paste it in here)).

draftCode_arduinoGPS.ino (7.89 KB)

You're using String objects and new. Dynamic memory allocation is risky business with so little SRAM. Try using plain old C arrays instead.

wildbill: You're using String objects and new. Dynamic memory allocation is risky business with so little SRAM. Try using plain old C arrays instead.

Ah, good catch! I guess with trying to optimise every other little thing, I missed that. I'll take care of that and see if it improves things.

As an update, that was exactly where the issues were. I was abusing the memory pretty badly inside that one function, but it's all sorted now (bad use of pointers and syntax). I've pretty much got rid of every String object and dynamic allocation and it works like a charm now, at least with the few tests I've been able to do so far.

I've certaintly learnt my lesson in that regard.

Just one more question to wrap things up: generally, once we're done using a char array in a function or wherever, is there anything to recommend for or against 'clearing' (using the term loosely) the array? Allocating and deallocating memory is always (well, not to speak in absolutes ...) a good idea, I'm just not sure if I should be doing this with the limited resources of the Atmega chip?

For now, I'm calling,

memset(charArray, 0, sizeof(charArray)); // free memory after use

Would creating a charArray and then clearing it after each function call (where it lives only within the function's scope) fragment the memory after some appreciable amount of time?

If you create the char array within the function, then it only exists in the scope of that function. If it isn't declared static, then it exists on the stack and when the function exits it ceases to exist. You don't need to do anything special to clean up local variables in functions as long as you're not allocating them on the heap with new.

Delta_G: If you create the char array within the function, then it only exists in the scope of that function. If it isn't declared static, then it exists on the stack and when the function exits it ceases to exist. You don't need to do anything special to clean up local variables in functions as long as you're not allocating them on the heap with new.

Great, that makes things much clearer in my head. Thanks!