0

I am creating an Arduino sketch which involves quite some classes, and I want to check if it will run on an Arduino Uno or Mega (2 KB vs 8 KB SRAM).

So far my global variables take up around 1,200 bytes, and I expect this will rise. However, beyond that I need to make sure the stack memory is not using up too much. How can I find the maximum used stack size?.

I can check manually by calculating the maximum function stack and calculating all parameters + local variables, but this is a very tedious job (especially since my application changes still a lot).

Or another way: I know it is possible to get the free space, but should I add this in 'strategic' locations or in the beginning of all functions and continue from there? (there will be many of them).

Or is there preferable some static way of checking this?

The application works within Visual Studio C++ as stand alone too, so maybe that helps for some solution.

I expect the stack size easily to be a few hundred bytes (which is quite a lot for the Arduino Uno SRAM).

3

Knowing the stack size is pretty easy: the stack pointer is initially set to RAMEND and goes down as the stack grows. Thus:

static inline size_t stack_size()
{
    return RAMEND - SP;
}

should I add this in 'strategic' locations [...]

Obviously, the result will depend on where this is evaluated. Ideally you should test this in the deepest parts of your call chain, as this is where the stack will be at its maximum size. Note that ISRs stack on top of all your regular code.

Edit: There is no easy way to know the maximum stack size. You could get an approximation by sampling the stack at regular intervals, e.g.:

#include <util/atomic.h>

volatile size_t min_sp = RAMEND;

ISR(TIMER0_COMPA_vect)
{
    if (SP < min_sp)
        min_sp = SP;
}

static inline size_t max_stack_size()
{
    size_t min_sp_copy;
    ATOMIC_BLOCK(ATOMIC_FORCEON) {
        min_sp_copy = min_sp;
    }
    return RAMEND - min_sp_copy;
}

If you enable TIMER0_COMPA interrupt in setup():

TIMSK0 |= _BV(OCIE0A);

then the stack size will be sampled every 1.024 ms. Note, however, that this ISR is itself using some stack space for its own purposes (9 bytes in my experiment), and that this is not sampling other ISRs or critical sections.

  • Thanks, the interrupt way is indeed great to check the maximum size. And good to know about the RAMEND / SP variables (registers). – Michel Keijzers May 13 at 10:15
  • 1
    @MichelKeijzers: RAMEND is actually a constant defined in <avr/io.h>. SP is indeed an IO register or, rather, a pair of registers. – Edgar Bonet May 13 at 10:16
  • Thanks for the clarification. – Michel Keijzers May 13 at 10:19
  • This assumes you do not use the heap: no new, no malloc, no String objects. A good idea on small controllers, anyway. – DataFiddler May 13 at 11:32
  • @DataFiddler: The question title was about heap (has been fixed since), but the question body is about stack. My answer specifically addresses the stack, not the heap. – Edgar Bonet May 13 at 11:54
3

Initialize the entire SRAM space from the top of the heap to the bottom of the stack, either during setup, or in a modified version of the Arduino-provided main() function, with some unlikely pattern, such as {0x55, 0xAA, ...} or "UnusedUnused...".

After your program has run a while, examine memory for dirty footprints, reading up from the top of heap to find the highest heap excursion, and down from the stack-pointer to find the lowest address used by stack. You could use a debugger if you have one, or just a hex & ASCII dump to the terminal. Pick through it with whatever tools you have handy on your PC. If there's been no collision and you're using a memory dump, it's pretty easy to start somewhere in the middle that wasn't disturbed, and scroll in either direction. The place where your initialized pattern has been overwritten usually stands out very plainly.

  • I upvoted it because it's another idea, but I think just printing the value seems easier.... or is it possible to download a 'hex dump' from a running program? (e.g. by the Arduino IDE) – Michel Keijzers May 13 at 19:08
  • 1
    I send the hex dump to the Arduino terminal, save it to a PC file, and inspect it on the PC. – JRobert May 13 at 21:14
  • Thanks also sounds like an interesting idea. Thanks – Michel Keijzers May 13 at 21:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.