This is a tag page.

Prevent ATMega328P crashes with a stack monitor

John Peck
Published

The ATmega328P is used on the Arduino UNO, the Nano, and on many other mass-produced microcontroller boards. But it has only 2048 bytes of SRAM, which is shared between the stack and storage for things like local variables. Bizarre behavior can happen if the SRAM needed for variable storage overlaps that needed for the stack, but it's hard to understand how much space these variables will use until the program is actually running. This is where Michael McTernan's stack monitor is useful.

The stack monitor "paints" SRAM storage registers with a magic value before application code executes. You can then check for unused stack memory during execution by counting up these magic values. Here's some debug output from my Diamond firmware running on the EVL-510:

debug trace

The unused SRAM is initially 200 bytes, but falls to 179 after turning the volume knob. Changing the volume calls a few functions that allocate local variables in SRAM. These get cleaned up when the function exits, but the stack monitor can see that the memory was used. The idea is to exercise as much of the system as you can and then make sure you still have some unused memory.

I call the function with a scheduler made from avr-simple-scheduler. The code block below shows adding the stack reporting function to the scheduler with a period of 5s. I could have made this even longer, since I only need the report to run after I've excercised as much as I can.

if (strcmp( LOG_LEVEL, "debug" ) == 0) {
    // Start the task to monitor free memory
    OS_TaskCreate(&system_report_stack_free, 5000, BLOCKED);
}