2010-11-10 1 views
3

Я пишу прошивку для микроконтроллера Atmel XMEGA в c, и я думаю, что я заполнил 4 КБ SRAM. Насколько я знаю, у меня есть только статические/глобальные данные и локальные переменные стека (I не использовать malloc в моем коде).Как я узнаю, когда моя память заполнена?

Я использую локальную переменную для буферизации некоторых пиксельных данных. Если я увеличиваю буфер до 51 байта, на моем дисплее появятся странные результаты - буфер из 6 байтов работает нормально. Вот почему я думаю, что мой баран заполнен, и стек переписывает что-то.

Создание бесплатной памяти не моя проблема, потому что я могу просто переместить некоторые статические данные во флеш-память и загрузить ее только тогда, когда это необходимо. Меня беспокоит тот факт, что я никогда не мог обнаружить, что память заполнена.

Возможно ли каким-либо образом вырезать (например, путем перепродажи микроконтроллера), когда память заполнена, вместо того чтобы позволить ей перезаписать некоторые другие данные?

ответ

3

Может быть очень сложно точно предсказать, сколько стека вам понадобится (некоторые инструментальные средства могут пойти на это, если вы включите правильные параметры, но это всего лишь приблизительное руководство).

Обычный способ проверки состояния стека состоит в том, чтобы заполнить его полностью известным значением при запуске, запустить код как можно тяжелее/долго, а затем посмотреть, сколько не было перезаписано.

Код запуска для вашей инструментальной цепочки может даже иметь возможность заполнить стек для вас.

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

Неочищенные способы проверки того, что переполнение стека является причиной вашей проблемы, - это сделать все ваши локальные массивы «статическими» и/или увеличить размер стека, а затем увидеть, работают ли все лучше. Это может быть трудно сделать на небольших встроенных системах.

0

Обычно ваш программный инструмент знает параметры контроллера, поэтому вам следует предупредить, если вы использовали больше (без mallocs, это известно во время компиляции).

Но вы должны быть осторожны с pixeldata, потому что большинство дисплеев не имеют линейного адресного пространства.

EDIT: обычно вы можете указать размер стека вручную. Оставьте достаточно памяти для статических переменных и зарезервируйте остальную часть для стека.

+0

Насколько я знаю, локальные переменные живут в стеке. Но размер стека неизвестен во время компиляции, или я ошибаюсь? – Martin

+0

@Martin: Размер стека может быть известен во время компиляции, если вы не используете локальные переменные рекурсии и переменные размера (буква допускается только с некоторыми C-компиляторами). – Curd

1

«Является ли это каким-то образом можно dected (например по сбросу микроконтроллера), когда память заполнилась до вместо позволяя ему переписать некоторые другие данные?»

Я полагаю, что в настоящее время у вас есть отображение памяти, подобное (1). Когда стек и/или переменное пространство становятся много, они сталкиваются и перезаписывают друг друга (*).

Другая возможность - это отображение памяти, подобное (2). Когда стек или переменное пространство превышают максимальное пространство, они попадают в непереведенное пространство addr (*). В зависимости от контроллера (я не уверен в отношении семейства AVR) это вызывает сброс/ловушку или аналогичные (= то, что вы хотели).

[not mapped addr space][ RAM mapped addr space ][not mapped addr space] 
(1)      [variables ---> * <--- stack] 
(2)      *[ <--- stack variables ---> ]* 

(стрелки указывают направление растет, если используется более изменчивы/стек)

Конечно, лучше, чтобы убедиться заранее, что RAM достаточно велик.

1

Обычно компоновщик отвечает за выделение памяти для кода, констант, статических данных, стеков и кучек. Часто вы должны указывать требуемые размеры стека (и доступную память) в компоновщик, который затем будет отмечать ошибку, если он не может вместить все.

Обратите также внимание, что если вы имеете дело с многопоточным приложением, то каждый поток имеет собственный стек, и они часто выделяются из кучи по мере начала потока.

Если у вашего процессора нет аппаратной проверки переполнения стека на него (маловероятно), есть несколько трюков, которые вы можете использовать для контроля использования стека.

  • Заполните стек известным шаблоном маркера и изучите память стека (выделенную компоновщиком), чтобы определить, какая часть маркера остается неповрежденной.
  • В прерывании таймера (или аналогичный) сравнивает основной указатель стека потока с основанием стеки для проверки переполнения

Оба этих подхода полезны при отладке, но они не гарантируется, что все проблемы и, как правило, только флаг проблемы ПОСЛЕ того, что стек уже поврежден что-то еще ...