STM32 watchdog (independent watchdog and window watchdog)

Introduction

STM32 has two watchdogs, one is the independent watchdog (IWDG) and the other is the window watchdog (WWDG). The independent watchdog is called a pet dog, and the window watchdog is called a police dog.

In layman’s terms, the independent watchdog is a 12-bit down counter. When the value of the counter decreases from a certain value to 0, the system will generate a reset signal, that is, IWDG_RESET. If the value of the counter is refreshed before the count is reduced to 0, then no reset signal will be generated. This action is what we often call feeding the dog. The watchdog function is powered by VDD voltage domain and still works in stop mode and standby mode.
The independent timer is relatively simple, so I won’t talk about it, and the direct decrement triggers reset.

The window watchdog is a 7-bit decrement counter that counts down, sets an upper window value, and the lower window value is fixed. It can only be reset between the upper window and the lower window value. Before reset, an emergency interrupt can be triggered. The most important event before doing the reset. ?

Frequency division

The clock of my watchdog is APB1, and the main frequency of the clock is 42M. The data sheet stipulates that the watchdog must be divided by 4096. You can also perform another frequency division (1, 2, 4, 8) through the CFR register. CNT_CK=PCLK1/4096/(2^WDGTB)

Window value

The window value is determined by the CFR register. The lower window value is fixed. The initial value of the register is 0x7F, which is 01111111 in binary. The lower window value is 0x3F, so the upper window value can only be set between 0x3F and 0X7F, that is, 63 to 127.

Timeout calculation

Register Introduction


Code

Interrupt priority initialization

// WWDG interrupt priority initialization

static void WWDG_NVIC_Config(void)

{<!-- -->
\t
  NVIC_InitTypeDef NVIC_InitStructure;
  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init( &NVIC_InitStructure);
}

WWDG configuration function

/* WWDG configuration functions
 * tr : The value of the decrement timer, the value range is: 0x7f~0x40, if it exceeds the range, it will be reset directly
 * wr: window value, the value range is: 0x7f~0x40
 * prv: prescaler value, the value can be
* @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1(42MHz)/4096)/1 about 10253Hz 97us
* @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1(42MHz)/4096)/2 about 5126Hz 195us
* @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1(42MHz)/4096)/4 about 2563Hz 390us
* @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1(42MHz)/4096)/8 about 1281Hz 780us
*
* Example: tr = 127 (0x7f, the maximum value of tr) wr = 80 (0x50, 0x40 is the minimum value of wr) prv = WWDG_Prescaler_8
* ~780 * (127-80) = 36.6ms < refresh window < ~780 * 64 = 49.9ms
* That is to say, call WWDG_Config to perform such a configuration. If the dog is fed before 36.6ms, the system will reset. If the dog is not fed after 49.9ms, the system will also reset.
* It is necessary to feed the dog within the time of refreshing the window, so that the system will not reset.
 */
void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv)
{<!-- -->
// Turn on the WWDG clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
\t
// Set the value of the down counter
WWDG_SetCounter( tr );
\t
// Set the prescaler value
WWDG_SetPrescaler( prv );
\t
// set upper window value
WWDG_SetWindowValue( wr );
\t
// Set the value of the counter and enable WWDG
WWDG_Enable(WWDG_CNT);
\t
// Clear early wakeup interrupt flag bit
WWDG_ClearFlag();
\t
// Configure WWDG interrupt priority
WWDG_NVIC_Config();
\t
// Enable WWDG interrupt
WWDG_EnableIT();
}

Interrupt function before death

// WWDG interrupts the service program, if this interrupt occurs, it means that the program has failed,
// This is a pre-death interrupt. The most important thing should be done in this interrupt service routine,
// For example, to save important data, etc., how long is this time, to
// Determined by the value of WDGTB:
// WDGTB:0 113us
// WDGTB: 1 227us
// WDGTB: 2 455us
// WDGTB:3 910us
void WWDG_IRQHandler(void)

{<!-- -->
// clear the interrupt flag bit
WWDG_ClearFlag();

//LED2 is on, lighting up the LED is just a schematic operation,
//When it is actually used, this should be the most important thing to do
LED2(ON);
}

feed the dog function

// Feed the dog
void WWDG_Feed(void)
{<!-- -->
// Feed the dog, refresh the value of the decrement counter, and set it to the maximum WDG_CNT=0X7F
WWDG_SetCounter( wwdg_cnt );
}

main function

int main(void)
{<!-- -->
Debug_USART_Config();
printf("\r\
This is a watchdog routine\r\
");
\t
uint8_t wwdg_tr, wwdg_wr;
\t
/* LED port initialization */
LED_GPIO_Config();
  
// BLUE blue light is on
LED3(ON);
Delay(0XFFFFFF);
\t
// WWDG configuration
\t
/* WWDG configuration function
 * tr : The value of the decrement timer, the value range is: 0x7f~0x40, if it exceeds the range, it will be reset directly
 * wr: window value, the value range is: 0x7f~0x40
 * prv: prescaler value, the value can be
* @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1(42MHz)/4096)/1 about 10253Hz 97us
* @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1(42MHz)/4096)/2 about 5126Hz 195us
* @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1(42MHz)/4096)/4 about 2563Hz 390us
* @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1(42MHz)/4096)/8 about 1281Hz 780us
*
* Example: tr = 127 (0x7f, the maximum value of tr) wr = 80 (0x50, 0x40 is the minimum value of wr) prv = WWDG_Prescaler_8
* ~780 * (127-80) = 36.6ms < refresh window < ~780 * 64 = 49.9ms
* That is to say, call WWDG_Config to perform such a configuration. If the dog is fed before 36.6ms, the system will reset. If the dog is not fed after 49.9ms, the system will also reset.
* It is necessary to feed the dog within the time of refreshing the window, so that the system will not reset.
*/
// Initialize WWDG: configure the initial value of the counter, configure the upper window value, start WWDG, and enable early wake-up interrupt
WWDG_Config(127,80,WWDG_Prescaler_8);
\t
// We set the window value to 0X5F during initialization, and this value will not change
wwdg_wr = WWDG->CFR & 0X7F;
\t
while(1)
{<!-- -->
// BLUE blue light
LED3(OFF);
//------------------------------------------------ -----
// This part should write the program that needs to be monitored by WWDG, the running time of this program
// Determines how big the window value should be.
//------------------------------------------------ -----
\t\t
// Timer value, initialized to a maximum of 0X7F, when WWDG is turned on, this value will continue to decrease
// When the value of the counter is greater than the window value, if you feed the dog, it will be reset. When the counter is reduced to 0X40
// If you haven't fed the dog yet, it will be very, very dangerous, and the counter will be reset when it reaches 0X3F
// So feed the dog when the value of the counter is between the window value and 0X40, where 0X40 is fixed.
wwdg_tr = WWDG->CR & 0X7F;
\t\t
if( wwdg_tr < wwdg_wr )
{<!-- -->
// Feed the dog, reset the counter to a maximum value of 0X7F
WWDG_Feed();
}
}
}