Перейти к содержанию
    

Переполнение стека в 8051 - как узнать?

Привет, 

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

Как узнать в этом ли проблема из самой программы? Средств отладки кроме самого камня на плате и осцилографов нет. 

Мониторить указатель стека или какие еще варианты?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну да, мониторинг. Если средства позволяют, можно задействовать аналог "стековой канарейки".
При переполнении вызовется специальный callback, где можно будет дернуть ножкой. Но накладные расходы увеличатся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В стародавние времена память под стек заполняли однотипными значениями. Программу гоняли некоторое время в разных режимах. Затем - останавливали и смотрели на значения ячеек памяти, выделенной под стек. Так в первом приближении определялся потребный размер стека.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добавил в программу вывод максимального значения регистра указателя стека SP и получил интересный прикол:

Проглядывая листинг после компилятора, вижу, что стек используется только в функциях обработки прерываний. Т.е. там стоит такое:

T2_int:
	PUSH	PSW
	PUSH	ACC
	PUSH	DPH
	PUSH	DPL
	PUSH	B
	PUSH	_R
	PUSH	_R+1
	PUSH	_R+2
	PUSH	_R+3
	PUSH	_R+4
	PUSH	_R+5
	PUSH	_R+6
	PUSH	_R+7

Ну и при возвращении из них, соответственно:

POP	_R+7
	POP	_R+6
	POP	_R+5
	POP	_R+4
	POP	_R+3
	POP	_R+2
	POP	_R+1
	POP	_R
	POP	B
	POP	DPL
	POP	DPH
	POP	ACC
	POP	PSW
	RETI

Т.е. это 13 байт + в стек пихается адрес возврата - 2 байта Program Counter(PC). Т.е. всего 15 байт.

Больше PUSH и POP не используются нигде в программе - я проверял все листинги.

У меня два уровня вложенности/приоритета прерываний (8051 больше не позволяет), т.е получается, что в худшем случае достаточная величина стека должна быть: 15(регистры и PC основной программы при первом прерывании) + 15 (регистры и PC первого прерывания при прерывании с более высоким приоритетом) = 30 байт, что собственно мне линкер и показывает в дампе памяти, выделив аж 29 байт на стек.

Но в реале, когда я добавил мониторинг SP, при работе программы указатель стека опускается аж на 43 байта. 

Почему так? Это я что-то не учитываю, или это у меня прерывания неправильно работают?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может, принудительное выравнивание стека компилятором используется? Согласно какому-нибудь ABI, например.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 minutes ago, xvr said:

CALL'ы используются? Они тоже стек используют

 

Да, используются. Извиняюсь, мой провтык. Получается, что CALL тоже засовывает PC стек и в итоге выходит, что чтобы рассчитать нужную величину стека, нужно еще посчитать вложенность всех функций. Мда, задачка не из легких. 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А локальные переменные в функциях где у вас живут ?

Или у вас два стека : программный стек и стек данных ? Как это например делает IAR для AVR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 minutes ago, dimka76 said:

А локальные переменные в функциях где у вас живут ?

В data overlay сегменте памяти. По крайней мере  судя по листингу, обращение к ним не через стек.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 hours ago, dimka76 said:

А локальные переменные в функциях где у вас живут ?

Вот тут нашел еще один прикол - у меня в прерываниях используются локальные переменные, которые, как я понял, находятся тоже в data overlay. Что произойдет с ними, если прерывание с более высоким приоритетом прервет прерывание с низким приоритетом, в котором используются локальные переменные? Получается, что оно может испортить их значение?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, syoma said:

Вот тут нашел еще один прикол - у меня в прерываниях используются локальные переменные, которые, как я понял, находятся тоже в data overlay. Что произойдет с ними, если прерывание с более высоким приоритетом прервет прерывание с низким приоритетом, в котором используются локальные переменные? Получается, что оно может испортить их значение?

https://www.keil.com/support/man/docs/bl51/bl51_overlaying.htm

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 hours ago, dimka76 said:

Почитал и поменял нафиг все локальные переменные в прерываниях на статические, так как не знаю насколько хорошо мой компилятор умеет этот overlay. Также заменил вызовы функций в прерываниях и где возможно в основной программе на их копии. Да, размер кода слегка увеличился, но думаю так будет надежнее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...