В вашем стеке есть 3 компонента:
- Адрес возврата вызова функции
- Параметры вызова функции
- автоматические (локальные) переменные
Ключом к минимизации использования стека является минимизация передачи параметров и автоматических переменных. Потребление места для самого вызова функции довольно минимально.
Параметры
Одним из способов решения проблемы параметров является передача структуры (через указатель) вместо большого количества параметров.
foo(int a, int b, int c, int d)
{
...
bar(int a, int b);
}
сделать это вместо:
struct my_params {
int a;
int b;
int c;
int d;
};
foo(struct my_params* p)
{
...
bar(p);
};
Эта стратегия хороша, если вы передаете много параметров. Если параметры все разные, то это может не сработать для вас. В результате вы получите большую структуру, содержащую множество различных параметров.
Автоматические переменные (локальные)
Это, как правило, самый большой потребитель стекового пространства.
- Массивы - убийца. Не определяйте массивы в ваших локальных функциях!
- Минимизировать количество локальных переменных.
- Используйте наименьший необходимый тип.
- Если повторный вход не является проблемой, вы можете использовать статические переменные модуля.
Имейте в виду, что если вы просто перемещаете все свои локальные переменные из локальной области в область модуля, вы НЕ экономите место. Вы обменяли пространство стека на пространство сегмента данных.
Некоторые RTOS поддерживают локальное хранилище потоков, которое выделяет «глобальное» хранилище для каждого потока. Это может позволить вам иметь несколько независимых глобальных переменных для каждой задачи, но это сделает ваш код не таким простым.