STM32CubeMx и watchdog. Настройка и использование IWDG.

Использование WatchDog таймера

Зачастую возникают ситуации, в которых программа зависает на какой-то точке, и в этом случае единственными решениями являются либо сброс питания микроконтроллера, либо нажатие на кнопку Reset. Но порой у пользователя просто нет доступа непосредственно к электронике, установленной внутри какого-либо корпуса. Да и даже если этот  доступ есть, нет ничего хорошего в том, чтобы вынуждать покупателя вашего устройства ковыряться в микросхемах и платах 🙂 Именно для этих целей и придуман периферийный модуль микроконтроллера под названием Watchdog. И именно этим инструментом мы сегодня и научимся пользоваться при помощи STM32CubeMx.

Эксперименты я буду проводить на отладочной плате STM32F429Discovery. Давайте создадим новый пустой проект, но перед этим немного поговорим о работе watchdog-таймеров в целом.

Итак, что же это за такой отдельный таймер?

Суть его работы довольно проста и заключается в следующем. Мы инициализируем watchdog для работы с определенным периодом (для этого мы настраиваем предделитель частоты и период – как и для обычных таймеров общего назначения). Сторожевой таймер начинает считать от установленного в регистр значения до нуля. И если он дойдет до нуля, то сразу же перезапустит микроконтроллер.

Для того, чтобы перезапуск не происходил постоянно необходимо перезагружать счетный регистр таймера до того, как он дошел до нулевого значения. Давайте рассмотрим небольшой тестовый пример для того, чтобы наглядно увидеть, в чем же заключается принцип работы watchdog’а.

void main()
{
	WatchdogInit();

	while(1)
	{
		WatchdogRefresh();
		Function();
	}
}

Давайте разберемся, как будет работать эта маленькая программа. Сразу же после входа в функцию main() мы инициализируем watchdog – пусть период составляет 500 мс.

В цикле while(1) основную полезную работу нашей программы выполняет функция Function(). В этой функции может быть все, что угодно – расчеты, отправка данных, работа с файлами и т. д. Но мы точно знаем, что в нормальном режиме работы время выполнения этой функции всегда составляет величину, меньшую 500 мс (пусть к примеру это время равно 100 мс).

Таким образом, сторожевой таймер никак не повлияет на работу программы в нормальном режиме. Но если вдруг внутри Function() случится какая-то неприятность, и программа зависнет (например, во вложенном цикле while() или на ожидании какого-либо флага), то watchdog перезапустит контроллер по истечению 500 мс. Получается, что он предотвратит глобальное зависание МК и запустит программу заново. Вот в этом то и состоит задача этого таймера!

У микроконтроллеров STM32 есть даже не один, а два модуля – IWDG и WWDG. Во многом они похожи, но есть и отличия. Сегодня мы сосредоточим наше внимание на IWDG. Ну а в одной из следующих статей мы проведем аналогичные сегодняшним тесты и для WWDG.

Пришло время перейти к программированию. Открываем новый проект для STM32CubeMX и активируем IWDG. Заодно давайте настроим выводы контроллера, подключенные к светодиодам на работу в режиме вывода:

Настройка сторожевого таймера

На этой вкладке нам больше ничего предпринимать не потребуется, переходим на Configuration и заходим в настройки таймера:

Настройка watchdog

Здесь мы настраиваем предделитель и период. IWDG в нашем примере тактируется от внутреннего низкочастотного генератора 32 КГц. Разделим частоту на 32 и получим 1 КГц. Таким образом, при величине периода, равной 1000, сторожевой таймер будет обнуляться и перезапускать контроллер по истечению 1 секунды. Генерируем программный код и открываем создавшийся проект. В самом начале функции main() видим вызов функций инициализации:

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_IWDG_Init();

Кроме того, необходимо запустить сторожевой таймер:

HAL_IWDG_Start(&hiwdg);

Для того, чтобы перезагрузить значение счетного регистра IWDG необходимо вызвать функцию:

HAL_IWDG_Refresh(&hiwdg);

Теперь давайте создадим следующий тестовый алгоритм:

HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(500);

HAL_IWDG_Refresh(&hiwdg);

HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(600);

HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET);

Давайте посмотрим, что у нас тут происходит. После запуска таймера он у нас начинает считать от значения 1000 мс до 0. Зажигаем зеленый светодиод (G13) и ждем 500 мс. После этого перезагружаем значение счетного регистра таймера, чтобы избежать перезапуска программы. После этого мы гасим зеленый светодиод. Далее у нас следуют команда задержки и команда включения красного светодиода. При таком значении задержки, как в данном примере, на момент включения красного светодиода сторожевой таймер досчитает до 400 мс (1000 – 600). И красный диод будет светиться 400 мс, после чего программа перезапустится.

Теперь попробуем увеличивать величину задержки в функции HAL_Delay(600) и увидим, что красный диод находится во включенном состоянии все меньшее время. А если сделать величину задержки большей 1000, то диод не загорится вовсе (сторожевой таймер сработает раньше, чем программа дойдет до включения диода красного цвета). И в этом случае мы будем наблюдать только мигание зеленого светодиода, так как программа будет раз за разом перезапускаться.

В общем, я думаю никаких вопросов по работе сторожевого таймера уже не осталось, поэтому на данном примере статья подходит к концу 🙂 Но вскоре мы освежим в памяти все то, что обсудили сегодня, поскольку будем разбирать принцип работы модуля WWDG  в STM32!

Поделиться!

Подписаться
Уведомление о
guest
10 Комментарий
старее
новее большинство голосов
Inline Feedbacks
View all comments
vitaliy
vitaliy
4 лет назад

Спасибо за статью !!!! очень полезная инф..

Паша
4 лет назад

Новых статей давно чего то нету! Чем все таки отличаются IWDG от WWDG ?

Паша
4 лет назад

Спасибо, уже изучаю!

Паша
4 лет назад

C StandartPerefLibrary это будет выглядеть так?

// настройка
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_32); //делитель на 32 =1кгц
IWDG_SetReload(1000); // период
IWDG_ReloadCounter(); // сброс счетчика
IWDG_Enable(); //вкл WatchDog

//сброс счетчика в программе
IWDG_ReloadCounter();

Vitali
Vitali
3 лет назад

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

Игорь
Игорь
3 лет назад

Скажите, а как понять, что контроллер перезагрузился именно по IWDG, то есть как программно определить, что контроллер ранее зависал.
Спасибо.

Игорь
Игорь
3 лет назад

Вопрос решен.
Для того, чтобы понять что перезагрузка произошла по срабатыванию IWDG (да и WWDG) нужно следить за регистром Control/status register (RCC_CSR). Там есть биты IWDG RSTF (WWDG RSTF). Если он выставлен в 1, то перезагрузка произошла по нему. Чтобы его сбросить нужно в этом же регистре в бит RMVF записать 1 (как я понял, она обнуляет весь регистр).

Alex
Alex
5 месяцев назад

Как запустить какой нибудь обработчик когда значение IWDG счетчика угрожающе. Нужно прерывание какое нибудь, поскольку обычное выполенение будет блокировано.

Присоединяйтесь!

Profile Profile Profile Profile Profile
Vkontakte
Twitter

Язык сайта

Август 2020
Пн Вт Ср Чт Пт Сб Вс
 12
3456789
10111213141516
17181920212223
24252627282930
31  

© 2013-2020 MicroTechnics.ru