почему не удается подвесить прерывание WDT ?
- Войдите на сайт для отправки комментариев
Попался на глаза вот такой код:
void(* resetFunc) (void) = 0; // фнкция ресета, вызывает прерывание 0 volatile uint8_t WDTb = 0; void SetWDT() { cli(); // Запрещаем прерывания на время изменения WDE и WDP asm("wdr"); // Сбрасываем WDT WDTCSR |= (1 << WDCE) | (1 << WDE); // Разрешаем изменение значения предделителя WDT: WDTCSR = (1 << WDP2) | (1 << WDP1) | (1 << WDP0) | (1 << WDIE ); // Interrupt mode, WD 2 сек sei(); // Разрешаем прерывания } ISR(WDT_vect) { WDTb++; if (WDTb > 2) { asm("wdr"); // Сбрасываем WDT delay(1000); resetFunc(); } } void setup() { SetWDT(); } void loop() { WDTb = 0; }
Это некий костыльный способ обойти вечный ребут при использовании ватчдога на Нано со старым бутом. Сам способ и его кривизну обсуждать не надо, вопрос не про это.
Собственно, по коду тут все понятно. Ватчдог настроен на прерывание, а не на ресет. В прерывании проверяется счетчик WDTb, и если основная программа не ресетила его 2 раза подряд - выполняется переход на нулевой адрес.
Код работает, проверил лично. Вопросы про другое - про обработчик прерывания WDT. Первая для меня непонятка - в нем стоит delay() . Но ведь все знают. что делей в прерывании использовать нельзя. он же сам использует прерывание? - как так?
И даже более того - есть поиенять делей на бесконечный цикл - программа все равно работает и софт-ресет происходит без малейшей задержки! Почему так?
ISR(WDT_vect) { WDTb++; if (WDTb > 2) { asm("wdr"); // Сбрасываем WDT while(1) {}; resetFunc(); } }
Можно бы подумать, что компилятор выкидывает while как пустой цикл- но нет, я пробовал вставлять в цикл разные операторы, разницы нет.
Может WDTb переполняется ?
Может WDTb переполняется ?
не, прерывание настроено раз в 2 секунды... это ж скока надо до переполнения... Тут сброс происходит быстро, визуально такое впечатление, что даже delay(1000) не отрабатывает.
Странно, что данный вопрос задан в песочнице.
ТС не знает ответа или предлагает решить эту задачу новичкам?
Если сам не знает ответа - то по delay(); достаточно заглянуть в первоисточники, чтобы понять почему не зависания (в данном конкретном случае).
Какие операторы? Мигалку может жахнуть, чтобы видно было.
А вообще вход в прерывание происходит ?
мигалку и ставил. Не успевает мигнуть ни разу, сразу софтресет... Такое впечатление, что улетает в ресет со сточки с wdr
Кстати мысль! А может команду wdr в прерывании ватчдога использовать нельзя??
Добавка позже - просмотрел даташит атмеги328 и атмеловский апноут про WDT - запрета на wdr в прерывании не нашел
ТС не знает ответа или предлагает решить эту задачу новичкам?
не знает.
про delay спасибо, ща гляну, не подсказывайте дальше :)
Странно, что данный вопрос задан в песочнице.
ну а где его еще задавать? разве что в "Отвлеченных"...
Мне почему-то кажется, что ответ по факту будет очень простым.
В loop WDTb постоянно обнуляется - как она может стать > 2 ???
В loop WDTb постоянно обнуляется - как она может стать > 2 ???
предполагается, что в ЛУП еще куча клиентского кода. который может зависнуть
Уточнения
Во-первых, для проверки, конечно, обнуление WDTb в лупе надо закомментировать.
Во-вторых - вопрос абсолютно реальный, не викторина и не глум. То что код c while(1) ресетится- проверено на стандартной нано с контроллером атмега328
Это некий костыльный способ обойти вечный ребут при использовании ватчдога на Нано со старым бутом. Сам способ и его кривизну обсуждать не надо, вопрос не про это.
Нет, как раз это и надо обсуждать, потому что это какой-то бред и полное непонимание процесса вечного ребута.
Цитата:
The Enhanced Watchdog Timer has three modes of operation. When operating in WDT System Reset Mode, a WDT timeout causes a system reset. If WDT Interrupt Mode and global interrupts are enabled, a WDT timeout sets the WDT Interrupt Flag and executes the WDT Interrupt handler, instead of resetting the system. If both WDT System Reset Mode and WDT Interrupt Mode are enabled, the first WDT timeout is handled as if only WDT Interrupt Mode was enabled. Then WDT Interrupt Mode is disabled automatically and the WDT is back in only WDT System Reset mode.
AVR132: Using the Enhanced Watchdog Timer стр 2
Нет, как раз это и надо обсуждать, потому что это какой-то бред и полное непонимание процесса вечного ребута.
согласен про бред и непонимание, но это не ко мне. Это к авторам идеи
Процесс вечного ребута и правильный путь его преодоления мне Дракула обьяснил еще 3 года назад.
Сейчас вопрос исключительно о том, почему while(1) не завешивает интеррапт-хендлер
Код представлен ТОЛЬКО ДЛЯ ИЛЛЮСТРАЦИИ
Сейчас вопрос исключительно о том, почему while(1) не завешивает интеррапт-хендлер
Для того и wdt, что бы НИЧТО не завешивало.)
Для того и wdt, что бы НИЧТО не завешивало.)
тоном обиженного новичка: " - Я понял, вы тут сами ответ не знаете..." :))
Ладно, обсуждение не было бесплодным, появились кое-какие идеи, вечером еще покопаю.
Дмитрий, главное не забудь пожалуйста результат изысканий опубликовать.
Дмитрий, ну ты же сам цитату из ДШ приводил. Что непонятно?
Стоит на while(1); Перегружает по сбросу. Или я не понял вопроса?
Дмитрий, ну ты же сам цитату из ДШ приводил. Что непонятно?
Стоит на while(1); Перегружает по сбросу. Или я не понял вопроса?
по какому сбросу7
wdt же перегружает.
Upper, все-таки wdr?
почему об этом в даташите ни слова?
Или я опять нифига не понял.... откуда берется джамп на нулевой адрес?
wdt же перегружает.
напиши четче. Если ты о том, что после первого прерывания WDT следующее идет на ресет - то это не так. Мы с Дедом это уже обсудили, но он потом предпочел стереть как ошибочное
Да я о том. Или я всё пропустил?)
Да я о том. Или я всё пропустил?)
в #13 перечислены три режима ватчдога. То, о чем вы с Дедом говорите - это третий режим, "Interrupt and Reset mode". А в этом коде использован второй - только Interrupt
В #20 не вижу while(1) ...
В #20 не вижу while(1) ...
я так понял, все что ниже wdr - при компиляции выкидывается и в код вообще не попадает. Ждем обьяснений от Upper
RJMP 0000 же попал
Тогда resetFunc(); он точно отбросил - понимает с..а что туда не попасть ...
Судя по листингу Upper, оптимизатор выкинул while(1);
а, ну да, он же Relative
Тогда где абсолютный переход на 0 ResetFunc() ?
А вот ResetFunc() оптимизатор выкинул.
А вот ResetFunc() оптимизатор выкинул.
если компилятор выкинул его - почему программа не виснет а все-таки улетает на нулевой адрес? - вернулись к исходному вопросу....
Прошил, проверил - виснет
setup вот так перепишите - попробуйте, сколько строчек "start" напишет?
Start печатается один раз.
Светодиод после первого Вкл Выкл включается и больше и не моргает, значит ни в loop ни в setup он больше не заходит
Start печатается один раз.
Светодиод после первого Вкл Выкл включается и больше и не моргает, значит ни в loop ни в setup он больше не заходит
спасибо за тест, вечером попробую на своей. У меня на подобном скетче start печатала дважды - то есть первый раз ресет все-таки срабатывал, а потом программа висла, не доходя до вторичной настройки setWDT() в сетапе
Мошт отключить канпилятору оптимизацию, чтобы условия сравнения были одинаковые?
Повторил тест Upper - все работает ровно так же, как у него. Программа виснет на бесконечном цикле, как и должна
После этого полез в свой код.... и сразу нашел ошибку.
Дело в том, что я до этого много экспериментировал и код был довольно большой. Но мне казалось, что я в нем все ненужное закомментировал. А оказалось - не все, причем так неудачно, что получился выход за границу массива. Вот он то ардуину и перегружал, причем еще до до того, как срабатывал ватчдог!
В общем, это называется - "Мойте руки перед едой" или другими словами - в программировании важна аккуратность.
Блин, я ж говорил, что эта тема - для "Песочницы" и причиной будет какая-то глупая ошибка. Зато я прошутидовал кучу материалов про WDT и теперь выучил все его режимы :)
Всем спасибо, а Upper - отдельно!
Upper, еще хотел спросить - а это из какой программы такой листинг?
Кстати, странно что в libc нет настройки режима wdt. Только enable/disable и reset.
b707 ИМХО это похоже на дизассемблер Atmel Studio
У мня Visual Micro так же умеет.
b707 ИМХО это похоже на дизассемблер Atmel Studio
Да это дизассемблер при отладке в Atmel Studio 7.
Формат отличается от создаваемого им же (Atmel Studio 7) листинга lss
Если просто надо посмотреть на генерируемый код, то в lss проще найти нужный код