Как настроить векторный таймер прерываний сторожевого таймера на Arduino Redboard/Uno?

Я пытаюсь настроить прерывание сторожевого таймера для выполнения процедуры в ISR WDT_vec с некоторым повторяющимся интервалом. Я не хочу, чтобы процессор сбрасывался, а просто выполнял код в прерывании и возвращался к «нормальной» работе. У меня есть следующий тестовый шаблон, взятый из сети, который, как утверждается, устанавливает это:

#include <avr/wdt.h>

 void setup_WDT() {
      noInterrupts();  // отключить все прерывания
      MCUSR = 0;       // убедитесь, что векторы сброса выключены

      /* Отключить и очистить все настройки Watchdog. */

      _WD_CONTROL_REG = (1 << WDCE) | (1 << WDE);
      _WD_CONTROL_REG = 0;

      /* Установка сторожевого таймера для прерывания и отсутствия сброса, а также тайм-аута приблизительно 500 мс */
      _WD_CONTROL_REG = (1 << WDIE) | (1 << WDP2) | (1 << WDP0);

      interrupts();  // повторно включить прерывания
    }

void setup() {
  setup_WDT();
  Serial.begin(9600);
  Serial.println("Startup");
}

void loop() {
}

ISR(WDT_vec) {
  Serial.println("Watchdog Interrupt");
}

Вывод показывает, что процессор просто сбрасывается многократно и никогда не достигает ISR. Также я получаю следующее предупреждение при компиляции из IDE (Arduino 1.8.2):

предупреждение: «WDT_vec» похоже на неправильно написанный обработчик сигнала, отсутствует __векторный префикс [-Wmisspelled-isr] ISR(WDT_vec) {

, 👍2

Обсуждение

Будьте осторожны, используя строку serial.print внутри вашего ISR. Последовательная связь требует прерываний для функционирования., @lemontwist

@lemontwist Спасибо, похоже, работает достаточно хорошо, чтобы просто проверить, срабатывает ли ISR или нет. Я бы не стал этого делать в реальной работе..., @Bitrex


2 ответа


Лучший ответ:

1

Две ошибки:

  1. Вектор прерывания сторожевого таймера называется WDT_vect, а не WDT_vec.
  2. Оператор _WD_CONTROL_REG = 0; не служит никакой полезной цели, и скорее всего, нарушит временную последовательность смены сторожевого таймера Настройка. Просто удалите ее.
,

Эти изменения заставили всё работать!, @Bitrex


0

_WD_CONTROL_REG = 0; выполняет важную функцию. Если сторожевой таймер случайно включается, например, из-за неконтролируемого указателя или состояния отключения питания, устройство будет сброшено, а сторожевой таймер останется включенным. Если код не настроен на обработку сторожевого таймера, это может привести к вечному циклу сбросов по тайм-ауту. Чтобы избежать этой ситуации, прикладное программное обеспечение всегда должно очищать флаг сброса системы сторожевого таймера (WDRF) и бит управления WDE в инициализации рутина, даже если Watchdog не используется. Если вы используете его при разработке продукта, программа которого никогда не должна зависать, то об этом важно помнить.

,

это нехороший ответ. в Arduino загрузчик управляет микроконтроллером через несколько секунд после включения питания или сброса. правильные загрузчики AVR отключают сторожевой таймер. в setup() слишком поздно для большинства интервалов wdt, @Juraj

спасибо, @juraj, за твой добрый комментарий. СБРОС, который мы воспринимаем обычно, и сброс, который происходит после сброса WDT, отличаются. Жесткий сброс снова запускает загрузчик, но сброс WDT даже не переинициализирует ОЗУ, запуск загрузчика — это другая проблема. Читать статью: https://playground.arduino.cc/Main/ArduinoReset & Там написано, что: К сожалению, как только Arduino начнет выполнять скетч, по-видимому, нет возможности написать программную функцию, которая имела бы точно такой же эффект, как нажатие кнопки сброса. Я буду признателен и буду рад, если окажусь неправ и узнаю что-то новое :)., @bandejiya

сторожевой таймер сбрасывается до загрузчика, @Juraj

тогда как мы можем доказать, что сторожевой таймер сбрасывает загрузчик? пожалуйста, поделитесь кодом или чем-то подлинным..!, @bandejiya

есть проекты загрузчиков для прошивки через Ethernet. но для его активации необходимо удаленно сбросить плату в загрузчик. используется сброс watchdog.https://github.com/per1234/Ariadne-Bootloader/tree/master/libraries/EthernetReset, @Juraj

на форуме arduino.cc пользователь прошил Atmega с помощью esp8266 с прошивкой AT, подключенной к RX/TX. Из скетча он инициировал с помощью AT-команд подключение к серверу, а затем сделал сброс сторожевого таймера, и сервер выполнил последовательную прошивку через esp8266 в прозрачном режиме., @Juraj

случай из предыдущего комментария https://forum.arduino.cc/index.php?topic=519242.msg3545523#msg3545523, @Juraj

@juraj PFA ссылка на техническое описание Atmega328pu на странице № 77, я нашел свой ответ в виде примечания, которое вы назвали плохим ответом..! Я немного запутался, может быть, я неправильно воспринимаю техническое описание, пожалуйста, проясните этот факт. Заранее спасибо. http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf, @bandejiya

В Arduino очистка флага сторожевого таймера является обязанностью загрузчика Arduino. Поэтому ваш ответ здесь не рассматривается., @Juraj