Как определить максимальное использование стека во встроенной системе? - PullRequest
10 голосов
/ 16 июня 2011

Когда я даю компилятору Keil параметр «--callgraph», он статически вычисляет для меня точное «Максимальное использование стека».

Увы, сегодня он дает мне «Максимальное использование стека = 284»сообщение bytes + Unknown (Functions with stacksize ...) "вместе со списком" Функции без информации стека ".

Найджел Джонс говорит, что рекурсия - это действительно плохая идея во встроенных системах («Вычисление размера вашего стека» ( 2009), поэтому я старался не делать никаких взаимно рекурсивных функций в этом коде.

Кроме того, я удостоверяюсь, что ни один из моих обработчиков прерываний не будет повторно включенпрерывания до их окончательной инструкции возврата из прерывания, поэтому мне не нужно беспокоиться о повторных входящих обработчиках прерываний.

Без рекурсивных или повторных входящих обработчиков прерываний он должен иметь возможность статически определять максимальный стекиспользование.(И поэтому большинство ответов на Как определить максимальное использование стека? не применимы).Насколько я понимаю, программное обеспечение, которое обрабатывает параметр «--callgraph», сначала находит максимальную глубину стека для каждого обработчика прерываний, когда оно не прерывается прерыванием с более высоким приоритетом, и максимальную глубину стека функции main (), когда онане прерывается.Затем он добавляет их все, чтобы найти общую (в худшем случае) максимальную глубину стека.Это происходит, когда фоновая задача main () находится на своей максимальной глубине, когда она прерывается прерыванием с самым низким приоритетом, и это прерывание находится на своей максимальной глубине, когда оно прерывается следующим прерыванием с самым низким приоритетом, и так далее.

Я подозреваю, что программное обеспечение, которое обрабатывает --callgraph, запуталось из-за небольших функций языка ассемблера в списке «Функции без информации о стеке». - документация по вызову , кажется, подразумевает, что мне нужно вручную вычислить (или сделать консервативную оценку), сколько стеков они используют - они очень короткие, так что это должно быть просто - и тогда "Используйте рамочные директивы в коде ассемблера, чтобы описать, как ваш код использует стек. "Одним из них является начальный код запуска, который сбрасывает стек до нуля перед переходом к main () - так что, по сути, он потребляет нулевой стек.Другой - это обработчик прерывания «Ошибка», который блокируется в бесконечном цикле, пока я не включу и не выключу - можно с уверенностью предположить, что это потребляет нулевой стек.

Я использую Keil uVision V4.20.03.0скомпилировать код для LM3S1968 ARM Cortex-M3.

Итак, как мне использовать "директивы фреймов", чтобы сообщить программному обеспечению, которое обрабатывает "--callgraph", сколько стека используют эти функции?Или есть какой-то лучший подход для определения максимального использования стека?

(См. Как определить максимальное использование стека во встроенной системе с gcc? почти для того же вопроса, нацеленного на компилятор gcc.)

Ответы [ 2 ]

3 голосов
/ 18 июня 2011

Джон Регер из Университета Юты подробно обсудил измерение использования стека во встраиваемых системах на уровне http://www.embedded.com/design/prototyping-and-development/4025013/Say-no-to-stack-overflow,, хотя следует отметить, что ссылка на ftp.embedded.com устарела, и один случай «без прерываний отключен» ”Должно иметь как первое, так и последнее слово отрицаться. В коммерческом мире Coverity имеет настраиваемую проверку переполнения стека, а некоторые версии CodeWarrior имеют полудокументированную прагму warn_stack_usage. (Это не упоминается в моей версии документации компилятора, но содержится в документе MetroWerks «Targeting Palm OS».)

3 голосов
/ 18 июня 2011

Используйте стек --info = в опции компоновщика.Затем файл карты будет включать использование стека для всех функций с внешней связью.

В однозадачной среде использование стека для main () даст вам общее требование.Если вы используете RTOS, например RTX, где каждая задача имеет свой собственный стек, то вам нужно посмотреть на использование стека для всех точек входа в задачу, а затем добавить еще несколько (64 байта в случае RTX) для контекста задачи.хранилище.

Этот и другие методы, применимые к Кейлу и в более общем смысле, описаны здесь

...