I'm programming in C for RAM limited embedded microcontroller with RTOS.
I regularly break my code to short functions, but every function calling require to more stack memory. Every task needs his stack, and this is one of the significant memory consumers in the project.
Is there an alternative to keep the code well organized and readable, still preserve the memory?
Try to make the call stack flatter, so instead of a()
calling b()
which calls c()
which calls d()
, have a()
call b()
, c()
, and d()
itself.
If a function is only referenced once, mark it inline
(assuming your compiler supports this).
There are 3 components to your stack usage:
The key to minimizing your stack usage is to minimize parameter passing and automatic variables. The space consumption of the actual function call itself is rather minimal.
Parameters
One way to address the parameter issue is to pass a structure (via pointer) instead of a large number of parameters.
foo(int a, int b, int c, int d)
{
...
bar(int a, int b);
}
do this instead:
struct my_params {
int a;
int b;
int c;
int d;
};
foo(struct my_params* p)
{
...
bar(p);
};
This strategy is good if you pass down a lot of parameters. If the parameters are all different, then it might not work well for you. You would end up with a large structure being passed around that contains many different parameters.
Automatic Variables (locals)
This tend to be the biggest consumer of stack space.
Keep in mind that if you're simply moving all your local variables from local scope to module scope, you have NOT saved any space. You traded stack space for data segment space.
Some RTOS support thread local storage, which allocates "global" storage on a per-thread basis. This might allow you to have multiple independent global variables on a per task basis, but this will make your code not as straightforward.
In the event you can spare a lot of main memory but have only a small shred of stack, I suggest evaluating static allocations.
In C, all variables declared inside a function are "automatically managed" which means they're allocated on the stack.
Qualifying the declarations as "static" stores them in main memory instead of on the stack. They basically behave like global variables but still allow you to avoid the bad habits that come with overusing globals. You can make a good case for declaring large, long-lived buffers/variables as static to reduce pressure on the stack.
Beware that this doesn't work well/at all if your application is multithreaded or if you use recursion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With