Попробовал включить в Orduino Nano v1.1 сторожевой таймер, и он действительно срабатывает, так, как надо, т.е. как будто ресетит ардуину, но после этого она почему то зависает. При этом лампочка на d13 начинает моргать, но это уже, наверное, и не важно. Модуль подключен к компьютеру через USB. Чтобы вывести в нормальное состояние надо отключить и подключить USB. Почему не работает так, как надо?
Код примерно такой: Код (Text): #include <avr/wdt.h> int n = 0; void setup() { Serial.begin(9600); wdt_enable (WDTO_2S); } void loop() { ++n; Serial.println(n, DEC); if(n < 100) wdt_reset(); delay(100); } Я ожидаю, что поработав примерно 12 сек (10 сек до прекращения выдачи сброса WatchDog и 2 сек до переполнения WatchDog), ардуина сбросится и начнет сначала. Однако через указанное время работа просто останавливается, как будто после срабатывания WatchDog, ардуина зависает.
Ваша проблема обсуждалась на форуме Arduino. Попробуйте прошить последний bootloader на свой Orduino или попробуйте bootloader от adafruit.
Скоро мозги закипят - на сайте Ардуино все ссылки на загрузчик для Mega 2560 зациклены на одну и ту же страницу, где прошивки загрузчика нет. Подскажите, где он находится - уж больно нужен сторожевой таймер в режиме RESET.
В общем, нашел загрузчик для Мега2560: stk500boot_v2_mega2560.hex. Только это не тот, который идет в штатном комплекте к IDE Ардуино - этот почему-то не сбрасывает сторожевой таймер при сбросе через WDT, хотя представленные загрузчики для остальных плат это делают. Почему разработчики так сделали - одному богу известно. По паспорту загрузчик Меги2560 должен быть размером в 8Кбайт, однако stk500-й имеет размер 20Кбайт. Хотел найти родной загрузчик и доработать его, однако его нет нигде, даже hех-файла. Пришлось загрузить тот, что нашел. Имея вторую Ардуину сделал программатор, прошив ее соответсвующим примером из Ардуины и перерезав перемычку. При прошивке вылезла ошибка верификации. Перепрошивка давала такой же результат. Однако, бутлоадер заработал как надо. Вот пример кода. Если загрузить его в Ардуино с непропатченным загрузчиком, то через 10 сек светодиод на 13 пине начнет мелко моргать, а платка зависнет. С пропатченным, после включения 2 раза моргнет бутлоадер, потом 2 сек пауза, потом прога моргнет длинно и коротко, затем, через 6 сек все повторится. Т.е. загрузчик останавливает WDT. #include <avr/sleep.h> int led = 13; int ll; void setup() { pinMode(led, OUTPUT); ll = 0; delay(2000); WDTCSR=0x39; WDTCSR=0x29; sleep_enable(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); } void loop() { digitalWrite(led, LOW); delay(200); digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(200); digitalWrite(led, HIGH); delay(200); digitalWrite(led, LOW); sleep_cpu(); } Вылез еще один косяк с новым загрузчиком. Теперь платку можно загрузить только через IDE Ардуино, а раньше она грузилать и через avrdude. Сейчас таймаут - и все.
Сталкивался с такой проблемой решил прошивкой нового bootloader (optiboot) http://habrahabr.ru/post/189744/
Подскажите вот в таком вопросе начсет сторожевого таймера, от от кварца тактуется или у него свой генератор. Поможет ли он при зависании железа? Есть пара чипов, вроде бы глючных, я на них собрал простые часики из примера к библиотеке, вобщем где то через сутки они виснут, иногда раньше. Не идут и все, на индикаторе последнее время (оно же время работы). Отдельный светодиод-моргатель тоже не моргает. Это происходит как с кварцем, так и от внутреннего генератора. Хочу использовать их в какой нибудь мигалке. Носможет ли сторож ее перегрузить, если зависание не программное?
Не знаю, может кому понадобится, но если есть программатор, то лучше шить скетчи Ардуино IDE через него. Отличие от стандартного способа прошивки только в том, что во флэш-памяти освобождается место, занятое ранее загрузчиком. Кроме того, начинает работать сторожевой таймер (актуально для Меги2560). Вот код со сторожевым таймером на виринге, разработанный в Ардуино IDE, который у меня заработал: Код (C++): #include <avr/wdt.h> uint8_t wd_change_bit = 0; uint8_t wd_control_reg = 0; uint8_t mcusr = 0; uint8_t mcusr_setup = 0; void setup() { wd_change_bit = _WD_CHANGE_BIT; wd_control_reg = _WD_CONTROL_REG; mcusr = MCUSR; if (MCUSR & 8) // сработал WDT и его надо отключить { MCUSR &= 0xE0; // код заточен на Мегу 2560 wdt_reset(); _WD_CONTROL_REG=0x10; _WD_CONTROL_REG=0x00; } else { mcusr_setup = MCUSR; } wdt_disable(); Serial.begin(9600); if (wd_control_reg == 0) // изначальное состояние { Serial.println("Setup.."); Serial.print("Init_MCUSR: "); Serial.println(mcusr_setup, HEX); Serial.print("Init_WD_CHANGE_BIT: "); Serial.println(wd_change_bit, HEX); Serial.print("Init_WD_CONTROL_REG: "); Serial.println(wd_control_reg, HEX); } else // состояние после срабатывания WDT { Serial.println("--------------------------------------------"); Serial.println("Watchdog reset."); Serial.print("RESET_MCUSR: "); Serial.println(mcusr, HEX); Serial.print("RESET_WD_CHANGE_BIT: "); Serial.println(wd_change_bit, HEX); Serial.print("RESET_WD_CONTROL_REG: "); Serial.println(wd_control_reg, HEX); } // состояние после выключения WDT Serial.println("Watchdog disabled."); Serial.print("dis_MCUSR: "); Serial.println(MCUSR, HEX); Serial.print("dis_WD_CHANGE_BIT: "); Serial.println(_WD_CHANGE_BIT, HEX); Serial.print("dis_WD_CONTROL_REG: "); Serial.println(_WD_CONTROL_REG, HEX); pinMode(LED_BUILTIN, OUTPUT); Serial.println("Wait 5 sec.."); delay(5000); // Задержка, чтобы было время перепрошить устройство в случае bootloop wdt_enable (WDTO_8S); // Для тестов не рекомендуется устанавливать значение менее 8 сек. // состояние после запуска WDT Serial.println("Watchdog enabled."); Serial.print("en_MCUSR: "); Serial.println(MCUSR, HEX); Serial.print("en_WD_CHANGE_BIT: "); Serial.println(_WD_CHANGE_BIT, HEX); Serial.print("en_WD_CONTROL_REG: "); Serial.println(_WD_CONTROL_REG, HEX); Serial.println("--------------------------------------------"); } int timer = 0; void loop(){ // Каждую секунду мигаем светодиодом и значение счетчика пишем в Serial if(!(millis() % 1000)) { timer++; if (digitalRead(LED_BUILTIN) == HIGH) { Serial.println(timer); } digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) == HIGH ? LOW : HIGH); delay(1); } // wdt_reset(); } Здесь программа сначала ждет 5 секунд, затем светодиод моргает 4 раза. Потом происходит срабатывание сторожевого таймера. Но лучше всего смотреть на мониторе порта. Видно, как меняются регистры при срабатывании WDT. За основу был взят код из статьи https://geektimes.ru/post/255800/ , частично измененный по результатам экспериментов на С в CVAVR.