Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Неправильная работа Watch Dog Timer'a
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
SerSh
Прошу помощи у Клуба!

Проблема в неправильной работе Watch Dog Timer'a на ATmega640-16AU.
Суть в следующем: после запуска Watch Dog Timer'a в режиме "System Reset Mode" через запрограммированое (2 сек) время камень не перезапускается (System Reset), а тупо виснет.
Проверку осуществляю при помощи вставленных циклов ожидания функции __delay_cycles().

Компилятор IAR EWB v.6.21.1.
Прошивка в железо - AVReal.
Инициализация в основной программе (main):
// Инициализация Watchdog-таймера
_WDR(); // Сброс Watchdog
WDTCSR |= (1<<WDCE)|(1<<WDE);
WDTCSR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); // Установка времени срабатывания ~2 с
_SEI(); // Глобальное разрешение прерывания

Фьюз WDTON=1.
Сама программа без WDT или с включённым WDT, но без принудительной сверхзадержки работает без проблем.
Аналогичные варианты других программ, но на камнях ATmega64 с идентичными параметрами (инициализация, фьюзы, способы проверки срабатывания WDT) работают тоже без проблем.
Сергей Борщ
QUOTE (SerSh @ Jun 19 2013, 14:50) *
WDTCSR |= (1<<WDCE)|(1<<WDE);

Попробуйте тут убрать "ИЛИ".
SerSh
Убрал.
Стало:
// Инициализация Watchdog-таймера
_WDR(); // Сброс Watchdog
WDTCSR = (1<<WDCE)|(1<<WDE);
WDTCSR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); // Установка времени срабатывания ~2 с
_SEI(); // Глобальное разрешение прерывания

В работе ничего не поменялось!
_Артём_
Цитата(SerSh @ Jun 19 2013, 16:33) *
Убрал.
Стало:
// Инициализация Watchdog-таймера
_WDR(); // Сброс Watchdog
WDTCSR = (1<<WDCE)|(1<<WDE);
WDTCSR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); // Установка времени срабатывания ~2 с
_SEI(); // Глобальное разрешение прерывания

В работе ничего не поменялось!

Возможно инициализация WDT не укладывается в нужное время. Покажите сгенерированный код.

Ещё вариант: у вас нет сброса флагов в регистре MCUSR. Что у вас там?
Палыч
Цитата(SerSh @ Jun 19 2013, 17:33) *
В работе ничего не поменялось!

А, если убрать глобальное разрешение прерываний ?
SerSh
К регистру MCUSR я вообще не обращаюсь.

Листинг функции main:
448 // Инициализация Watchdog-таймера
449 _WDR(); // Сброс Watchdog
\ 000002A8 95A8 WDR
450 WDTCSR = (1<<WDCE)|(1<<WDE);
\ 000002AA E108 LDI R16, 24
\ 000002AC 9300.... STS _A_WDTCSR, R16
451 // WDTCSR = (1<<WDE)|(1<<WDP3); // Установка времени срабатывания ~4 с
452 WDTCSR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); // Установка времени срабатывания ~2 с
\ 000002B0 E00F LDI R16, 15
\ 000002B2 9300.... STS _A_WDTCSR, R16
453 _SEI(); // Глобальное разрешение прерывания
\ 000002B6 9478 SEI

Сам файл листинга = 1,2Мб загружаться не хочет.

Цитата(Палыч @ Jun 19 2013, 16:48) *
А, если убрать глобальное разрешение прерываний ?


Тогда ничего работать не будет: В проге задействовано 4 USARTa, SPI, 2T/C.
А, вцелом, я вначале описал, что если отключить WDT, то всё прекрасно работает.

Ещё одна подозрительная тонкость: после зависа проги по WDT и дальнейшей перепрошивки проги заново - завис не прекращается, нужно обязательно передёрнуть питание. После этого прога начинает работать (до следующего срабатывания WDT).
_Артём_
Цитата(SerSh @ Jun 19 2013, 17:02) *
Ещё одна подозрительная тонкость: после зависа проги по WDT и дальнейшей перепрошивки проги заново - завис не прекращается, нужно обязательно передёрнуть питание.

Возможно это связано с несброшенным битом WDRF в регистре MCUSR.
SerSh
Цитата(_Артём_ @ Jun 19 2013, 17:11) *
Возможно это связано с несброшенным битом WDRF в регистре MCUSR.


И когда его сбрасывать?
_Артём_
Цитата(SerSh @ Jun 19 2013, 17:12) *
И когда его сбрасывать?

В самом начале программы. Желательно до инициализации переменных, так как инициализация может занять слишком много времени и опять произойдёт сброс по WDT.
SerSh
Цитата(SerSh @ Jun 19 2013, 17:12) *
И когда его сбрасывать?


Перед инициализацией WDT сбросил этот бит: clrbit (MCUSR, WDRF);.
Не помогло!
Палыч
Цитата(SerSh @ Jun 19 2013, 18:02) *
Тогда ничего работать не будет: В проге задействовано 4 USARTa, SPI, 2T/C.
А, вцелом, я вначале описал, что если отключить WDT, то всё прекрасно работает.

Давайте "отделим мух от котлет"!
Без WDT Ваша программа правильно работает. Вот и чудесно.
WDT без Вашей программы работает ? Проверяли ? Если - нет, проверьте... Я думаю, что тоже будет работать...
Для проверки работы WDT с программой Вы вставили задержку __delay_cycles(), вероятно, перед сбросом WDT (может, я и не прав, но так понял из Вашего первого сообщения). Как предположение: эта задержка приводит к краху части функционала программы, но та часть, что отвечает за сброс WDT продолжает работать, при этом, поскольку остальная часть не работает, то время на __delay_cycles(), вероятно, уменьшилось и сброс WDT производится с периодом меньшим 2 сек, что приводить к отсутствию сброса МК.
Для проверки работы WDT совместно с программой я бы убрал __delay_cycles(), а вместо него либо - "глухой" цикл при запрещенных прерываниях, либо флаг и проверка флага: взведен - то сброс WDT не производить.

SerSh
Цитата(Палыч @ Jun 19 2013, 18:07) *
WDT без Вашей программы работает ?

Кажется работает. Я вводил задержку специально чтобы сымитировать ситуацию "зависание - рестарт".
Если задержку не вводить, то программа работает, и WDT как-то там себе живёт, не беспокоит.

Цитата(Палыч @ Jun 19 2013, 18:07) *
Как предположение: эта задержка приводит к краху части функционала программы...

Как может цикл портить функционал программы мне не понятно.

Цитата(Палыч @ Jun 19 2013, 18:07) *
, но та часть, что отвечает за сброс WDT продолжает работать, при этом, поскольку остальная часть не работает, то время на __delay_cycles(), вероятно, уменьшилось и сброс WDT производится с периодом меньшим 2 сек, что приводить к отсутствию сброса МК.

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

Цитата(Палыч @ Jun 19 2013, 18:07) *
Для проверки работы WDT совместно с программой я бы убрал __delay_cycles(), а вместо него либо - "глухой" цикл при запрещенных прерываниях, либо флаг и проверка флага: взведен - то сброс WDT не производить.

Не совсем понятна идея. Если поставить просто глухой цикл типа while(1);, то всё повторяется - зависание. При этом не важно: открыты или закрыты все прерывания (проверял только что).
Палыч
Цитата(SerSh @ Jun 19 2013, 19:51) *
Кажется работает.
Кажется? Или, всё-таки - работает?

Цитата(SerSh @ Jun 19 2013, 19:51) *
Как может цикл портить функционал программы мне не понятно.
А, нам-то и подавно не понятно, поскольку Вы как партизан молчите о том, куда Вы задержку вставили...

Цитата(SerSh @ Jun 19 2013, 19:51) *
Если поставить просто глухой цикл типа while(1);, то всё повторяется - зависание. При этом не важно: открыты или закрыты все прерывания (проверял только что).
А, если вместо всяких циклов/задержек просто закомментировать стоку сброса WDT - будет ли Ваша программа рестартовать каждые 2 сек ?
SerSh
Цитата(Палыч @ Jun 19 2013, 19:43) *
Кажется? Или, всё-таки - работает?

Я в предыдущем посте описал работу программы. А слово "кажется" использовал специально для Вас. )))

Цитата(Палыч @ Jun 19 2013, 19:43) *
А, нам-то и подавно не понятно, поскольку Вы как партизан молчите о том, куда Вы задержку вставили...

Задержку вставил сразу после инициализации WDT. И вовсе я не партизан, просто это не имеет значения. Её куда ни вставь, она и в Африке задержка.

Цитата(Палыч @ Jun 19 2013, 19:43) *
А, если вместо всяких циклов/задержек просто закомментировать стоку сброса WDT - будет ли Ваша программа рестартовать каждые 2 сек ?

А вот это завтра утром на работе попробую. А сейчас - спать.
Спокойной ночи, господа, спокойной ночи!...
SerSh
Закомментировал все команды WDR, но всё осталось по-прежнему: через 2 сек. после старта - завис.
Такое впечатление, что он уходит в рестарт, но попадает не на начальный адрес старта, а на какой-нибудь бутлоадер, которого на самом деле нет, и, пробегая по пустым местам, возвращается обратно, при этом портя стек.
Палыч
Цитата(SerSh @ Jun 20 2013, 10:15) *
Закомментировал все команды WDR, но всё осталось по-прежнему: через 2 сек. после старта - завис.

Осталось проверить, что WDT без всей остальной части Вашей программы нормально работает (это я Вам давно рекомендавал сделать). Собирите маленький проект, где будет только инициализация WDT (ну, ещё какой либо сигнал, что программа запустилась/перезапустилась). Если этот проектик будет нормально рестартовать через 2 сек, то ошибку нужно искать в остальной части Вашей программы: вероятно, где-то кто-то портит регистр WDTCSR (собственно, WDT m640 и отличается от m64 старшими битами этого регистра - возможностью вместо рестарта генерить прерывание).
SerSh
Цитата(Палыч @ Jun 20 2013, 09:49) *
Осталось проверить, что WDT без всей остальной части Вашей программы нормально работает (это я Вам давно рекомендавал сделать). Собирите маленький проект, где будет только инициализация WDT (ну, ещё какой либо сигнал, что программа запустилась/перезапустилась). Если этот проектик будет нормально рестартовать через 2 сек, то ошибку нужно искать в остальной части Вашей программы: вероятно, где-то кто-то портит регистр WDTCSR (собственно, WDT m640 и отличается от m64 старшими битами этого регистра - возможностью вместо рестарта генерить прерывание).


ОК, пошёл пилить...
Сергей Борщ
Заодно фуз BOOTRST проверьте
SerSh
Цитата(Сергей Борщ @ Jun 20 2013, 10:30) *
Заодно фуз BOOTRST проверьте

Фьюз BOOTRST я не трогал, по умолчанию он равен 1, т.е. старт с адреса 0х0000.

Цитата(Палыч @ Jun 20 2013, 09:49) *
Осталось проверить, что WDT без всей остальной части Вашей программы нормально работает (это я Вам давно рекомендавал сделать). Собирите маленький проект, где будет только инициализация WDT (ну, ещё какой либо сигнал, что программа запустилась/перезапустилась). Если этот проектик будет нормально рестартовать через 2 сек, то ошибку нужно искать в остальной части Вашей программы: вероятно, где-то кто-то портит регистр WDTCSR (собственно, WDT m640 и отличается от m64 старшими битами этого регистра - возможностью вместо рестарта генерить прерывание).


Видимо правда Ваша: что-то в основном цикле портит, например, WDTCSR.
Сварганил я новый main(), вернее жёстко порезал старый. Оставил только инициализацию WDT, несколько переменных для цикла и прерывания по таймеру (refresh). При старте один раз пищит звуковой сигнал, а затем каждые пол-секунды коротко вспыхивает подсветка LCD.
Если команда _wdr(); в цикле присутствует, то вспышки подсветки длятся бесконечно, а если _wdr(); убрать, то снова рестарт: короткий звуковой сигнал и четыре вспышки подсветки и цикл. Значит WDT работает правильно, но кто-то ему мешает, кажется, (крестится). )))
SerSh
Неожиданное продолжение.
Стал возвращать в программу ранее закомментированые блоки и выяснил, что описанные выше проблемы появляются при наличии в тексте программы функции инициализации LCD - lcd_init();. Причём, обращение к LCD без инициализации ничего не портит (на экране, естественно, кракозябры, но это не важно), а только инициализация. Содержимое этой функции тоже не имеет большого значения, тем более, что сам LCD работает прекрасно, и библиотека связи с LCD написана где-то в 2003-2004 году и работает в десятке различных серийных приборах. В листинге инициализации тоже ничего особенного.
Короче, начал я койки переставлять ))) и пришёл к тому, что если сначала инициализировать WDT, а затем LCD, то всё работает как нужно: при наличии команд wdr всё работает, а при отсутствии - перезапускается через запрограммированное время, а если наоборот: сначала инициализировать LCD, а затем WDT, то всё виснет при отсутствии команд wdr.
Всё это мне кажется весьма подозрительным, боюсь неожиданных приключений.
Не будет ли у многоуважаемого Клуба каких-либо умных мыслей на сей счёт.
Палыч
Цитата(SerSh @ Jun 26 2013, 11:08) *
Не будет ли у многоуважаемого Клуба каких-либо умных мыслей на сей счёт.

Информации - маловато...
Приведите текст функции ициализации LCD, а также часть схемы подключения LCD (или опишите словами связи МК - LCD).
SerSh
Цитата(Палыч @ Jun 26 2013, 10:40) *
Информации - маловато...
Приведите текст функции ициализации LCD, а также часть схемы подключения LCD (или опишите словами связи МК - LCD).


Схема порта LCD и функция инициализации LCD.
Да, и ещё нужен define.h
Палыч
Цитата(SerSh @ Jun 26 2013, 12:00) *
... функция инициализации LCD.

Не увидел того, чего хотел: настройка направлений информации на пинах МК и установка сигналов с "начальные" состояния.

Включен ли BOD? Какой уровень установлен?

Цитата(SerSh @ Jun 26 2013, 11:08) *
Не будет ли у многоуважаемого Клуба каких-либо умных мыслей на сей счёт.

Мысль такая:
Замечено, что AVR при определенных "неполадках" питания могут становиться в некое "раскоряченное" состаяние, при котором нарушается нормальная их работа. Например, при очень медленном нарастании напряжения питания (несколько секунд) AVR легко поставить в такое вот "раскоряченное" состояние: работать - не работает, на сигнал сброса - не реагирует, только снятие и подача "нормального" питания...
Думаю, что что-то этакое имеет место и у Вас. О похожих симптомах Вы говорили в предыдущих сообщениях... Возможно, при инициализации пинов МК и LCD на некоторое малое время имеет место встречное включение сигналов: например, МК на каком-то сигнале выдаёт низкий уровень, а в это же время LCD на этом же проводнике пытается держать высокий уровень. При этом происходит "проседание" напряжения питания и МК (веренее в Вашем случае - его какая-то часть, связанная с WDT) переходит в "раскоряченное" состояние.
Правда, я наблюдал полностью не работающий МК (конкретно - m128) в таком "раскоряченном" состоянии, в m640, возможно, "раскорячивается" только WDT, да и то - если он ещё не запущен.
Вот такие у меня мысли...
SerSh
Цитата(Палыч @ Jun 26 2013, 12:59) *
Не увидел того, чего хотел: настройка направлений информации на пинах МК и установка сигналов с "начальные" состояния.

Файлик с low_level_init'ом на всякий случай прикладываю.

Цитата(Палыч @ Jun 26 2013, 12:59) *
Включен ли BOD? Какой уровень установлен?

Да, включён, в фьюзы BODLEVEL прошиваю 4, что соответствует 4,1...4,5В. CKSEL прошиваю F, SUT=1. Всё это соответствует "Crystal Oscillator, BOD enabled" (таблица 10-4) при частоте кварца 14.7456МГц

Цитата(Палыч @ Jun 26 2013, 12:59) *
Вот такие у меня мысли...

Спасибо за Ваши мысли. Сейчас попробую поиграться с разными напряжениями BOD.
Кстати, питание проца - рядом стоящий импульсный стабилизатор (типа КРЕНка=+5В). Для силовых цепей есть отдельная такая же КРЕНка, но на 12В. Общий провод - большой полигон (плата двусторонняя). Кондёр (чип) по питанию проца припаян как раз под ним на полигоне. Аналогичным образом ведёт себя совершенно другая плата, но с таким же контроллером (мега640), стартовая инициализация у них похожая.
Палыч
Беглый анализ кода показал: таки возможно встречное включение, более того - оно присутствует всегда !
Сигналы шины данных DB4-DB6 Вы "держите" в положении "на вывод" всегда, и только сигнал DB7 переключаете "на ввод" при чтении с LCD. Правильно делать - переключать всю группу DB4-DB7 "на ввод" при операции чтения. По соображениям "безопасности" эту группу сигналов (DB4-DB7) логичнее держать в высокоимендансном состоянии (т.е. "на ввод"), и только при выводе байта переводить в состояние "на вывод", а после окончания команды вывода - снова переводить в высокоимпендансное состояние.
SerSh
Цитата(Палыч @ Jun 26 2013, 14:32) *
Беглый анализ кода показал: таки возможно встречное включение, более того - оно присутствует всегда !
Сигналы шины данных DB4-DB6 Вы "держите" в положении "на вывод" всегда, и только сигнал DB7 переключаете "на ввод" при чтении с LCD. Правильно делать - переключать всю группу DB4-DB7 "на ввод" при операции чтения. По соображениям "безопасности" эту группу сигналов (DB4-DB7) логичнее держать в высокоимендансном состоянии (т.е. "на ввод"), и только при выводе байта переводить в состояние "на вывод", а после окончания команды вывода - снова переводить в высокоимпендансное состояние.

Спасибо, сейчас буду что-то посмотреть.
SerSh
К сожалению, хороших результатов нет. sad.gif
Установка BOD на 2,5...2,9В ничего не дала, всё как и было.
Библиотеку общения с LCD я подправил, теперь DB - на выход только при записи, всё остальное время на вход без pull-up'a.
Но изменений результата нет. Всё виснет при рестарте если WDT инициализировать после LCD.
Если сначала WDT, а затем LCD, то WDT срабатывает с рестартом через нужное время при отсутствии команд wrd.
Умных мыслей больше нет, остались одни выражения...
Палыч
Цитата(SerSh @ Jun 26 2013, 16:59) *
теперь DB - на выход только при записи, всё остальное время на вход без pull-up'a.
Надеюсь, что речь идёт о всех четырёх линиях шины данных. Или только о DB7 ?
SerSh
Цитата(Палыч @ Jun 26 2013, 16:12) *
Надеюсь, что речь идёт о всех четырёх линиях шины данных. Или только о DB7 ?

Нет, конечно вся тетрада! Но, главное, результат тот же... sad.gif
В любом случае большое спасибо всем принявшим участие в обсуждении, особенно товарищу Палычу!
zombi
Цитата(SerSh @ Jun 26 2013, 10:08) *
пришёл к тому, что если сначала инициализировать WDT, а затем LCD, то всё работает как нужно: а если наоборот: сначала инициализировать LCD, а затем WDT, то всё виснет при отсутствии команд wdr.

Если всё действительно так как Вы пишете то я в такой ситуации поступил бы след. образом.
При условии что незакоченная инициализация LCD не приведёт к его порче.
Т.е. когда мозг отказывается понимать происходящее а глаза не видят ошибку biggrin.gif
Закомментировал бы всю программу инициализации LCD и начал бы поочерёдно последовательно открывать по одной строке/команде проверяя после этого работоспособность.
В конце концов обязательно найдёте ту самую виновницу...


SerSh
Цитата(zombi @ Jun 27 2013, 00:28) *
Если всё действительно так как Вы пишете то я в такой ситуации поступил бы след. образом.
При условии что незакоченная инициализация LCD не приведёт к его порче.
Т.е. когда мозг отказывается понимать происходящее а глаза не видят ошибку biggrin.gif
Закомментировал бы всю программу инициализации LCD и начал бы поочерёдно последовательно открывать по одной строке/команде проверяя после этого работоспособность.
В конце концов обязательно найдёте ту самую виновницу...

В своём посте чуть выше я писал, что содержимое функции инициализации LCD вообще не имеет значения. Я именно закомментировал ВСЕ строки в этой функции, оставил только вход и выход, и получил зависание. Я сам в шоке sm.gif
Дело даже не в работоспособности/неработоспособности LCD в устройстве при отладке. Даже без функции инициализации всё работает на ура! При этом сама функция весьма простая, я её выкладывал. Просто - чудеса (он в чудеса не верит), я бы сам не поверил.
zombi
Получается (если рассматривать программу в кодах ассемблера) что нерабочая программа отличается от рабочей наличием всего двух команд call XXXX и RET по адресу XXXX.
Это ж бред.
Палыч
Цитата(zombi @ Jun 27 2013, 12:43) *
Это ж бред.

Вы сильно всё упростили.
Выполнение некой функции занимает определенное время. Убрав вызов этой функции Вы измените временнЫе соотношения между наступлением неких событий. В коде присутствует некая ошибка, которая проявляется именно при наступлении определённых событий в неком, конкретном временнОм интервале. Меняя местами вызовы функций ТС изменяет эти временнЫе соотношения. На время тестирования устройства те самые "нехорошие" события разошлись во времени, но не факт, что через продолжительное время эти "нехорошие" события вновь не "сойдутся"...
Так что, по большому счету, перестановка местами вызовов функций проблему не решает. И дело здесь, возможно, и не в инициализации LCD вовсе. Хотя и в такой "обсосанной" со всех старон теме, как инициализация LCD, ТС умудрился "накосячить"... Если у ТС LCD на HD44780, то "невооруженным взглядом" видны отклонения в коде от DS - они остались после исправлений с направлением передачи данных по шине данных. Вероятно, кроме LCD в изделии присутствуют и др компоненты, с которыми взаимодействует МК. Возможны "косяки" и при работе с ними...
Заметил, что "баги" давольно "прочно" поселяются с частях программ, "кочующих" из проекта в проект годами. С трудом вериться, что в коде, "проверенном" не одним проектом, могут быть какие-то ошибки... Ан - могут ! Однажды я нашёл ошибку в коде "благополучно" применявшимся 10 лет ! Поиск в программе ошибок, связанных с временнЫм соотношением между наступлением неких событий - дело трудное и не предсказуемое по результату...
SerSh
Цитата(zombi @ Jun 27 2013, 11:43) *
Это ж бред.

Вы думаете, что я не понимаю, что это похоже на бред?
В своём посте чуть выше я написал о своих опасениях на этот счёт. Как пишет Палыч, очень возможно, что сейчас купированные симптомы потом вылезут где-то в другом месте.
Что сейчас делать я не знаю, потому и обратился за помощью на форум. Я над этой проблемой ломаю голову уже третью неделю.
Я ведь уже всё главное в программе сделал, а там куча разного железа: заняты все СОМ-порты, SPI, все таймеры... (не буду загружать). Короче, я думал, что уже включу WDT, и всё. Включил и всё... пропало! Тут только всё и началось.
Если будет желание посмотрите сами на инициализацию. В комментах я отметил как было вначале, когда всё зависало.
zombi
У Вас SEI сразу после инита WDT и затем еще какие то иниты.
Прерывания не рано разрешаете?
Палыч
Цитата(SerSh @ Jun 27 2013, 23:21) *
Что сейчас делать я не знаю

Я бы привел работу функций взаимодействия МК с LCD в соответствие с DS. Не вникал в них глубоко, но бросается в глаза несоответствие DS HD44780 от Hitachi (в Вашем LCD какой контроллер используется ?) коду функций lcd_init и lcd_ready. Заодно и др функции проверить - я в них смотрел "одним глазом", Вы же - посмотрите внимательно...

P.S. Кстати - константы задержек для функции __delay_cycles в файле defines.h определены неверно (у Вас - целые, а требуются - unsigned long) - после цифирек добавить UL
berberber
Та же песня!
ATMega88 после интервала для срабатывания Watchdog происходит полное зависание контроллера, выводы переходят в z состояние и всё, прога не стартует заново.

Код был портирован из ICCAVR где нормально работал в AtmelStudio с WinAVR, где и начались чудеса.
Симптомы полностью соответствуют указанным ранее, питание в норме, BOD включен, BOOTRST в 1 и.т.д.

Upd rolleyes.gif

Нашел!
Если инициализация watchdog происходит перед вызовом "_delay_ms(100)" (это из delay.h от winavr),
то watchdog работает корректно, при превышении интервала происходит нормальный сброс контроллера.
Если инициализацию поставить после этой задержки, то сброс по watchdog не происходит, все виснет намертво!

Дальше разбираться не стал, некогда.

Когда код был под ICCAVR задержка там была реализована другим образом и проблем не возникало, инициализировать watchdog можно было в любом месте программы.
Думаю что это компилятор зараза! (Оптимизация стоит на -O2)
Сергей Борщ
Цитата(berberber @ Apr 1 2015, 12:56) *
Думаю что это компилятор зараза! (Оптимизация стоит на -O2)
Давайте так: я доказываю невиновность компилятора, а вы ставите бутылку коньяка. Надо же как-то отвечать за подобные обвинения.
demiurg1978
ТС, вам нужно сделать переменную в ОЗУ. И придумываем значение. Пусть будет 0xAA.

В начале программы делаем следующее: проверяем переменную. Если переменная не равна 0xAA, делаем то что и должны в начале программы, инициализируем переменные, ввод-вывод, устройства, устанавливаем значение 0xAA. Если переменная равна 0xAA, то в обязательном порядке заново инициализируем то, что должно инициализироваться, дисплей к примеру.

Поясняю: если происходит сброс по сторожевому значению, то в ОЗУ остались какие-то рабочие значения, из-за которых и происходит затык МК. Программа ведет себя так, как будто сброса не было. В ОЗУ остались установленные флаги, состояния. Работа с дисплеем у вас идет с опросом флага ожидания. И скорее всего, заглючивший дисплей после сброса - виновник зависания. Или еще какое устройство, которое инициализируется при включении устройства.

Готовьте коньяк для Сергея. sm.gif
berberber
Цитата(Сергей Борщ @ Apr 1 2015, 14:22) *
я доказываю невиновность компилятора, а вы ставите бутылку коньяка

Коньяк на доказательства менять не стану, он мне ближе к сердцу biggrin.gif

Проблема для меня потеряла актуальность, поскольку я ее обошел, но осадочек остался sad.gif

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

Код
#include <avr/io.h>
#include <avr/wdt.h>
#include <util/delay.h>

int main(void)
{
        _delay_ms(100);//delay 100ms
        
         wdt_reset(); WDTCSR|=(1<<WDCE)|(1<<WDE); WDTCSR = 0x0F;//watchdog init        
                 
         DDRD=0x01;PORTD=0x01;//LED ON
        
         while(1);
}
Сергей Борщ
Цитата(berberber @ Apr 2 2015, 10:47) *
Кому интересно, прилагаю упрощенный пример:
Чтобы подтвердить вину компилятора нужны как минимум листинги одного и второго вариантов.

добавлено:
Цитата(berberber @ Apr 2 2015, 10:47) *
Если сперва идет задержка, потом инициализация watchdog, получаем полный висяк через 2 секунды.
А собака случайно принудительно не включена фузами? Тогда, возможно, она успевает сработать во время задержки и программа просто не успевает дойти до перенастройки собаки.

И кроме того, если предыдущий сброс был по собаке, то установившийся бит WDRF автоматически выставляет WDE. Это означает, что после сброса по собаке программа работает с включенной собакой с минимальным периодом в 16 мс. И если ее не перенастроить, через 16 мс произойдет повторный сброс. Что мы и наблюдаем, если до перенастройки стоит задержка много больше этих 16 мс - 2 секунды до первого сброса и потом постоянние повторные сбросы не доходя до выполнения полезных действий.

Цитата
• Bit 3 - WDE: Watchdog System Reset Enable
WDE is overridden by WDRF in MCUSR. This means that WDE is always set when WDRF is
set. To clear WDE, WDRF must be cleared first. This feature ensures multiple resets during conditions
causing failure, and a safe start-up after the failure.


Итак, компилятор снова оказался не при чем, виноват оказался программист, невнимательно читавший документацию. Как и в 99,9% остальных случаев, когда обвиняют компилятор. Надо было насчет коньяка додавить sm.gif
demiurg1978
Цитата(berberber @ Apr 2 2015, 14:47) *
Проблема для меня потеряла актуальность, поскольку я ее обошел, но осадочек остался sad.gif

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

Кстати, да. Если у вас перенастраивается сторожевой таймер, то Сергей Борщ прав.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.