There are 3 components to your stack usage:
- Function Call return addresses
- Function Call parameters
- automatic(local) variables
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.
- Arrays are the killer. Don't define arrays in your local functions!
- Minimize the number of local variables.
- Use the smallest type necessary.
- If re-entrancy is not an issue, you can use module static variables.
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.