сайт для палких паяльників

Watchdog, или сторожевые таймеры, существуют для того, чтобы в случае зависания программы микроконтроллера, его (микроконтроллер) можно было перезагрузить. У STM32 есть два watchdog. IWDG и WWDG. IWDG – независимый ( “I” – Independent). WWDG – Оконный ( “W” – Window). Если Вы завели настроили и запустили watchdog, надо периодически сбрасывать его счетчик. Если счетчик не обновлять определенное время, watchdog считает, что с микроконтроллером то не так и перезагружает его. Это главная идея watchdog. Теперь рассмотрим их подробнее и разберем, в чем разница между IWDG и WWDG.

IWDG – Independent Watchdog

Independent – независимый Watchdog. IWDG тактируется от отдельного, встроенного в микроконтроллер, генератора низкой частоты. Смотри: 4. STM32. Программирование STM32F103. Тактирование.

Инициализация IWDG выполняется следующим образом:

  • Включается LSI (40 kHz) (генератор низкой частоты, которым тактируется IWDG)
  • Включается доступ к регистрам IWDG
  • Настраивается делитель входной частоты
  • Устанавливается счетчик (от 0 до 0x0FFF)
  • Включается IWDG

Сразу после запуска IWDG начинает отнимать от установленного счетчика 1. Он это делает с частотой тактирования разделенную на делитель. И, когда счетчик досчитает до 0, произойдет перезагрузка микроконтроллера. Чтобы микроконтроллер НЕ перезагружался, надо периодически обновлять счетчик. Пример:

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_iwdg.h"
#include "misc.h"

int main(void)
{
  int i;
  /* Initialize Leds mounted on STM32 board */
  GPIO_InitTypeDef  GPIO_InitStructure;
  /* Initialize LED which connected to PC13, Enable the Clock*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  /* Configure the GPIO_LED pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* Disable LED */
  GPIO_SetBits(GPIOC, GPIO_Pin_13);
  /* delay */
  for(i=0;i<0x100000;i++);

  /* Enable the LSI OSC */
  RCC_LSICmd(ENABLE);
  /* Wait till LSI is ready */
  while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {}

  /* Enable Watchdog*/
  IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
  IWDG_SetPrescaler(IWDG_Prescaler_4); // 4, 8, 16 ... 256
  IWDG_SetReload(0x0FFF);//This parameter must be a number between 0 and 0x0FFF.
  IWDG_ReloadCounter();
  IWDG_Enable();

  /* Enable LED */
  GPIO_ResetBits(GPIOC, GPIO_Pin_13);

  while (1)
  {
	  //IWDG_ReloadCounter();
  }
}

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

WWDG – Window Watchdog

В отличии от IWDG, WWDG тактируется частотой, которой тактируется микроконтроллер. Вернее сказать, частота тактирования WWDG равна частоте PCLK1 (частота на выходе APB1), деленная на постоянный делитель 4096. Таким образом можно сказать, что работа WWDG синхронизирована с работой программы микроконтроллера.

При чем здесь Window? Для WWDG можно настроить “окно” (промежуток времени), в которое надо обновлять счетчик watchdog. Не раньше и не позже. То есть, если WWDG обновить раньше или позже, чем следовало, будет выполнена перезагрузка микроконтроллера. Это свойство используется не только для контроля зависания программы, а еще для контроля несанкционированных переходов. Например, если по каким-либо причинам была пропущена важная процедура. Именно слишком малое время между событиями и может стать сигналом того, что критическая процедура не была выполнена.

У WWDG есть особенность – счетчик работает в диапазоне от 127 до 64 есть, он считает вниз от указанного числа до 64. Для того, чтобы настроить окно, нам надо чтобы WindowValue было меньше начального значения счетчика. Например, мы установили WindowValue = 90, а счетчик 120. WWDG начинает уменьшать счетчик от 120 до 64. И, если мы перезапишем счетчик раньше, чем он досчитает до 90, произойдет перезагрузка микроконтроллера, так как мы не попали в окно.

Если WindowValue равна или больше счетчик, тогда WWDG работает как обычный watchdog.

Инициализация WWDG выполняется следующим образом:

  • Включается тактирование WWDG
  • Настраивается делитель входной частоты
  • Устанавливается окно (от 64 до 127)
  • Устанавливается счетчик (от 64 до 127) и включается WWDG
  • Включается и настраивается прерывание, если нужно

Пример:

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_wwdg.h"

int main(void)
{
  int i;
  /* Initialize Leds mounted on STM32 board */
  GPIO_InitTypeDef  GPIO_InitStructure;
  /* Initialize LED which connected to PC13, Enable the Clock*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  /* Configure the GPIO_LED pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* Disable LED */
  GPIO_SetBits(GPIOC, GPIO_Pin_13);
  /* delay */
  for(i=0;i<0x100000;i++);

  /* Enable Watchdog*/
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
  WWDG_DeInit();
  WWDG_SetPrescaler(WWDG_Prescaler_8);
  WWDG_SetWindowValue(0x7F);
  WWDG_Enable(0x5F);

  /* Enable LED */
  GPIO_ResetBits(GPIOC, GPIO_Pin_13);

  while (1)
  {
	//WWDG_SetCounter(0x5F);
  }
}

Для WWDG можно настроить обработку прерывания. Например, нам нужно сохранить какие-то данные перед перезагрузкой. Или выполнить какие-то процедуры и решить действительно надо перезагрузить микроконтроллер или позволить ему работать дальше. Если сбросить флаг WWDG функцией WWDG_ClearFlag() перезагрузки не произойдет.

Пример:

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_wwdg.h"
#include "misc.h"

void WWDG_IRQHandler(void) {
    int i;
    WWDG_ClearFlag(); //This function reset flag WWDG->SR and cancel the resetting
    WWDG_SetCounter(100);

    /* Toggle LED which connected to PC13*/
    GPIOC->ODR ^= GPIO_Pin_13;
}

int main(void)
{
  /* Initialize Leds mounted on STM32 board */
  GPIO_InitTypeDef  GPIO_InitStructure;
  /* Initialize LED which connected to PC13, Enable the Clock*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  /* Configure the GPIO_LED pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* Disable LED */
  GPIO_SetBits(GPIOC, GPIO_Pin_13);

  /* Enable Watchdog*/
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
  WWDG_DeInit();
  WWDG_SetPrescaler(WWDG_Prescaler_8); //1, 2, 4, 8
  WWDG_SetWindowValue(127); // 64...127
  WWDG_Enable(100);
  WWDG_EnableIT();

  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;    /*WWDG interrupt*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);/*    NVIC initialization*/

  while (1)
  {

  }
}

Памятка

WWDG тактируется частотой: (PCLK1/4096)/WWDG_Prescaler

Интервал до перезагрузки рассчитывается как:
T = 1000 / PCLK1 * 4096 * WWDG_Prescaler * (Counter – 63) мс
Например:
T = 1000 / 8000000 * 4096 * 1 * (120-63) = 29.184 мс

Интервал, после которого можно обновлять счетчик WWDG, рассчитывается как:
t = 1000 / PCLK1 * 4096 * WWDG_Prescaler * (Counter – WindowValue) мс
Например:
t = 1000 / 8000000 * 4096 * 1 * (120-80) = 20.48 мс

Желаю успехов!

Смотри также:

4 комментария: 17. STM32. Программирование STM32F103. Watchdog

  • TAron говорить:

    после включение , можно ли отключить watchdog? , IWDG

    • andre говорить:

      Вырубить ему тактирование:
      RCC_LSICmd(DISABLE);

        • andre говорить:

          Спасибо, на это я не обратил внимание.

Translate
Архіви

© 2011-2018 Андрій Корягін, Кременчук - Київ, Україна