3

How can we determine how much memory is being used, or will be used by firmware in a microcontroller? What tools can support this?

Generally we don't use dynamic memory in embedded systems, but how can we determine the worst case stack usage for example? A compiler can't be enough.

For example we may not know until run-time how many times a function could be called, potentially causing a stack-overflow.

can a debugger tell us exactly at any point in the execution flow, how much memory is being used?

Engineer999
  • 161
  • 1
  • 7
  • 6
    If you don't use recursion or function pointers then static analysis tools can quite easily tell you what your stack usage will be because your worst-case call-tree will be predictable. – brhans Feb 20 '19 at 19:42
  • 1
    @brhans Those tools can if and only if you don't call functions through pointers to functions, don't use co-routines, iterators, etc. Static call-graph/tree analysis has been used for decades in 8051 compilers, for example. But the moment you start using function pointers of any kind, it breaks down. – jonk Feb 21 '19 at 04:56
  • 1
    @jonk - the start of my comment "If you don't use recursion or function pointers ..." ¯\\_(ツ)_/¯ – brhans Feb 21 '19 at 11:57
  • @brhans Also, such tools typically don't take interrupts in account. – Lundin Feb 21 '19 at 12:57

4 Answers4

6

Yes, a debugger can tell you at any point in time how much memory is being used by the stack. Just check the current value of the stack pointer.

Another thing you can try is to fill up all of the unused RAM area with some obvious bogus value, like 0xAAAA. Run your code for a while and then check the RAM to see how many of the bogus values were overwritten...that's your maximum stack size.

The amount of memory used by static variables should be shown in some kind of log or report from the linker, as this is determined at compile time.

Elliot Alderson
  • 31,192
  • 5
  • 29
  • 67
2

How can we determine how much memory is being used, or will be used by firmware in a microcontroller? What tools can support this?

The static (compile-time) information can usually be found in an output file generated by the linker, if you request it. Most linkers will have an option for this purpose, as well as options to greatly expand the level of detail provided. You should look to the documentation on the linker tool for ways to generate these listings, expanded or simple. (I used to just call these "map files.")

When a compiler (or several different compiler front ends, if you use gnu tools and like to program in multiple source languages) generates object files, these need to be linked together with library code in order to produce the final result. That result will include all the code, all of the required initialized data, and all of the statically allocated data.

There are some dynamic (run-time) memory allocations (stack and heap, for example.) These will NOT be included in the linker's map output file, for obvious reasons.

Generally we don't use dynamic memory in embedded systems, but how can we determine the worst case stack usage for example? A compiler can't be enough.

Different people use different methods for testing and validating stack usage. A way that does not test for worst case (unless you get lucky) is to first set all of the available stack space to a "special value" prior to the main code starting up. Then you run it for a while, poke away at different features and functions within the software, and finally freeze things and go look at the memory. It's pretty easy to see how much got "stepped on" during execution.

If you want the actual "worst case," there are a couple of ways. One is to exhaustively test all of the code -- some medical (critical) software requires that every single line of code be tested. If you work out a testing regime to meet that requirement, you can probably work out the worst case (using the "special value" technique just mentioned and being exhaustive in testing.)

But some compiler tools (often at the linker stage but not always and, most notably, the ones written for the 8051 core because of some reasons of history and its design architecture; but I'm sure many others as well) offer the ability to build and then analyze the call graph in order to calculate the maximum stack usage. This static analysis works okay if your code doesn't make indirect calls using function pointers. So some compilers also allow you to provide them with a list of functions that might be called from each calling function in some kind of "stack usage control file" that you have to provide. So this is another possible way.

Of course, you can work it out by hand (given enough time and money, most things can be done.)

For example we may not know until run-time how many times a function could be called, potentially causing a stack-overflow.

Yes. So see the above discussion I just provided.

can a debugger tell us exactly at any point in the execution flow, how much memory is being used?

I'm not entirely sure what you mean. But perhaps you mean that if you hit some breakpoint, can the debugger tell you enough? It may be able to do so. Some hardware includes information that can be reported by the debugger that will tell you a lot. The stack pointer, for example, will have a value in it that tells you where the stack bottom is currently at. That can tell you the stack usage up to that point. (However, because activation frames may have been used and then freed before you get to your breakpoint, that might not be as helpful as you'd like. You might have picked a bad location for the breakpoint.)

Often, heap space information is also important. And there are tools that will walk the heap space for you and tell you what's in use, what's not in use, etc. You can also use heap allocation libraries that will report very detailed information on the heap space usage. You could include those libraries, while testing. For stack space, if your MCU supports segmented or paged memory allocation for the stack, then information can be captured and reported to tell you the worst case usage of the stack (so far.)


So what brought all these questions to the fore? If you have a specific compiler toolset, just ask the vendor. They will be able to provide you with all the details available to your circumstances. If you are just asking "in general," then the above is the best I can offer you, in general.

jonk
  • 77,059
  • 6
  • 73
  • 185
1

Some compilers are able to do static stack usage analysis. As it is known at compile time how much each function use stack and how the functions call each other, the deepest stack usage can be calculated. What it may not take into account is stack used in interrupt routines or RTOS context switching.

Justme
  • 127,425
  • 3
  • 97
  • 261
0

You can estimate the worst case stack depth:
1. Take the maximum stack depth of the main thread.
2. Determine how many interrupt levels you have. (eg: how many priority groups)
3. Add the maximum stack depth of each interrupt level.
4. Add fault handler stack depth.

All of the above information can be found in the reports generated by the linker.
Sometimes you have to explicitely enable these reports, like with --callgraph.

Jeroen3
  • 21,976
  • 36
  • 73