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

Как определить где зависает?

В общем, где-то год назад было сделано устройство на ATmega168, которое нормально работает, но вот обнаружилось, что оно периодически (до 5 раз в день) программно зависает и перезагружается по сторожевому таймеру. Как определить где именно зависает? Устройство имеет светодиод, но им отлаживать, учитывая частоту зависания, не хочется. Есть выход в локальную сеть для передачи UDP-пакетов, в режиме прерывания по watchdog всё вполне работоспособно, как узнать в каком месте зависает? Программа написана на CVAVR. Заранее спасибо.

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


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

Расставить контрольные точки и в каждой выдавать тестовые сообщения в UART или ещё куда-нибудь.

При старте - специальная метка старта.

Потом посмотрите полученный лог и увидите последнее сообщение перед рестартом

Проверьте ещё целостность стека - не наползает ли он на область глобальных переменных.

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


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

UART не предусмотрен, поэтому хотелось бы использовать имеющийся ethernet интерфейс, возможно ли, например по прерыванию от вотчдога, сохранить в еепром какую-то информацию о месте где была программа в момент этого прерывания, чтоб после перезагрузки передать её по сети? Например значение программного счётчика? Как в CVAVR обратиться к этому счётчику? Просто давно это уже было и сейчас приходится заново вникать:(

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


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

UART не предусмотрен

Замените в сообщении MrYuran UART на LAN, далее по тексту

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


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

Можно также при зависании, в прерывании по вачдогу, сливать весь стек и регистры... Далее пишите какой-нибудт скриптик например на питоне, который получает на вход слитый стек и дизасм вашего проекта и по процессорному стеку разматывает стек вызовов функций.... 99% найдёте место зависания. Мы таким образом все jump на NULL отловили в своём коде.

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


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

Все тупо, но придется много писать. :)

Заводите две глобальные переменные, пусть будет trace_fn и trace_cp.

 

На входе в функцию:

unsigned int old_tfn = trace_fn;

unsigned int old_tcp = trace_cp;

trace_fn = <номер_функции>;

 

Внутри функции:

trace_cp = 1;

trace_cp = 2;

и так далее.

 

На выходе из функции восстанавливаете значения из переменных old.

Внутри функции watchdog отправляете на отладку обе глобальные переменные и видите, какой checkpoint в какой функции был последним.

Там поблизости и ищите...

 

 

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


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

в режиме прерывания по watchdog всё вполне работоспособно

Перепишите его так, чтобы не сохранять в стеке регистры. РС будет сверху. Дальше-дамп

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


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

Всем спасибо отловил место зависания весьма нехитрым способом: наставил в коде несколько меток, которые устанавливались при выполнении конкретной части кода, при зависании WDT давал прерывание, в обработчике которого значения меток сливались в eeprom, далее происходит ресет по WDT и слив полученных меток в сеть при старте программы. Соответственно, последняя активированная метка перед не активированной и показала место зависания.

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


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

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

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

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

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

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

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

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

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

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