Why window watchdog?
For the general watchdog, the program can refresh the watchdog at any time before it is reset, but there is a hidden danger. It is possible that the program runs disorderly and returns to the normal place, or the disordered program just performs the refresh watchdog operation. In this case, the general watchdog cannot be detected;
If the window watchdog is used, the programmer can set a time window to refresh the watchdog according to the normal execution time of the program, so as to ensure that the watchdog will not be refreshed in advance or delayed. In this way, it can detect that the program does not run according to the normal path and skips some program segments abnormally.
Window watchdog
The reason why it is called window is that its dog feeding time is within the range (window) with upper and lower limits. You can set its upper limit time (the lower limit is fixed 0x3F) by setting relevant registers. The dog feeding time cannot be too early or too late. Dogs can only be fed during the window period, and will be reset if it is too early or too late.
The independent watchdog limits the dog feeding time to 0-x, which is determined by the relevant register. The dog feeding time cannot be too late.
Working diagram of window watchdog
Window watchdog block diagram:
Summary of window watchdog working process
There is a 7-bit down counter T[6:0] in the window watchdog of STM32F,
It will generate watchdog reset in one of the following two situations:
If the watchdog is activated and interrupts are allowed, an early wake-up interrupt (EWI) is generated when the down counter is equal to 0x40, which can be used to feed the dog to avoid WWDG reset.
Window watchdog timeout
Other precautions for window watchdog:
Control register WWDG_CR
void WWDG_Enable(uint8_t Counter);// Start and set initial value
void WWDG_SetCounter(uint8_t Counter);// feed a dog
Window watchdog configuration process
RCC_APB1PeriphClockCmd();
② Set frequency division coefficient:
WWDG_SetPrescaler();
③ Set the upper window value:
WWDG_SetWindowValue();
④ Enable early wake-up interrupt and group (optional):
WWDG_EnableIT();
NVIC_Init();
⑤ Enable watchdog:
WWDG_Enable();
⑥ Feed the dog:
WWDG_SetCounter();
⑦ Write interrupt service function
WWDG_IRQHandler();
wdg.c
#include "wdg.h" #include "led.h" void IWDG_Init(u8 prer,u16 rlr) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //Enable register IWDG_PR and iwdg_ Write operation of RLR IWDG_SetPrescaler(prer); //Set IWDG prescaled value: set IWDG prescaled value to 64 IWDG_SetReload(rlr); //Set IWDG reload value IWDG_ReloadCounter(); //Reload the IWDG counter according to the value of the IWDG reload register IWDG_Enable(); //Enable IWDG } //Hey, independent watchdog void IWDG_Feed(void) { IWDG_ReloadCounter(); //Heavy load count value } //Save the setting value of WWDG counter. The default value is maximum u8 WWDG_CNT=0x7f; //Initialize window watchdog //Tr: T [6:0], counter value //WR: w [6:0], window value //fprer: frequency division coefficient (WDGTB), only the lowest 2 bits are valid //Fwwdg=PCLK1/(4096*2^fprer). void WWDG_Init(u8 tr,u8 wr,u32 fprer) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG clock enable WWDG_CNT=tr&WWDG_CNT; //Initialize WWDG_CNT. WWDG_SetPrescaler(fprer);set up IWDG Prescale Vlaue WWDG_SetWindowValue(wr);//Set window value WWDG_Enable(WWDG_CNT); //Enable the watchdog, Set counter WWDG_ClearFlag();//Clear the early wake-up interrupt flag bit WWDG_NVIC_Init();//Initialize window watchdog NVIC WWDG_EnableIT(); //Open window watchdog interrupt } //Reset the value of the WWDG counter void WWDG_Set_Counter(u8 cnt) { WWDG_Enable(cnt);//Enable the watchdog, Set counter } //Window watchdog interrupt service routine void WWDG_NVIC_Init() { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG interrupt NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //Preemption 2, sub priority 3, group 2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //Preemption 2, sub priority 3, group 2 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure);//NVIC initialization } void WWDG_IRQHandler(void) { WWDG_SetCounter(WWDG_CNT); //When this sentence is disabled, the window watchdog will reset WWDG_ClearFlag(); //Clear the early wake-up interrupt flag bit LED1=!LED1; //LED status flip }
main.c
#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "usart.h" #include "wdg.h" int main(void) { delay_init(); //Delay function initialization NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Set the interrupt priority group as 2: 2-bit preemption priority and 2-bit response priority uart_init(115200); //The serial port is initialized to 115200 LED_Init(); KEY_Init(); //Key initialization LED0=0; delay_ms(300); WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8);//The counter value is 7f, the window register is 5f, and the frequency division number is 8 while(1) { LED0=1; } }