For the WWDG routines given by the STM32 window watchdog and the atomic battleship, there are a few issues to be recorded. 1. WWDG time-out formula derivation 1.1 WWDG work diagram
1.2 WWDG time-out formula derivation
(1) The value of the upper window can only be set, the maximum number of 7 bits binary can only be set to 127 (0x7F), the minimum must be greater than the 0x40 of the lower window, so its value range is 64~127 (ie: 0x40~0x7f)
(2) Configuration register WWDG->CFR
Window watchdog clock comes from the PCLK1, in the clock configuration, the frequency is the external clock after the multiplier of the second-frequency clock, that is, 36MHz
(3) According to the above analysis, the window time Calculation formula is:
Last window time: t_min
= (wwdg_cr[6:0]-wwdg_cfr[6:0])/(tck/(2^WDGTB)) (US)
= (wwdg_cr[6:0]-wwdg_cfr[6:0])/((tpck1/4096)/(2^WDGTB)) (US)
= 4096 * (2^WDGTB) * (wwdg_cr[6:0]-wwdg_cfr[6:0])/(72/2) (US)
= 4096 * (2^WDGTB) * (wwdg_cr[6:0]-wwdg_cfr[6:0])/36 (US)
Next window time: T_max = 4096 * (2^WDGTB) * (wwdg_cr[6:0]-0x3F)/36 (US)
Window watchdog timeout formula (refresh time formula):
TWWDG = T_max-t_min
= 4096 * (2^WDGTB) * (wwdg_cfr[6:0]-0x3F)/36 (US)
= 4096 * (2^WDGTB) * (wwdg_cfr[6:0)-/36 (US)
And because wwdg_cfr[6:0] value range is: 0~127,
(wwdg_cfr[6:0]–63) >0,
So
1<= (wwdg_cfr[6:0]–63) <= 127-63=64
And because a 6-bit binary x[5:0] value range is 0~63,
1 <= x[5:0]+1 <= 64
So
The above formula can be expressed as:
TWWDG = 4096 * (2^WDGTB) * (t[5:0]+1)/36 (US)
(4) According to the above formula, can calculate the timing range of WWDG:
WDGTB (counter divider value) |
The earliest time to feed the dog/US |
The latest time to feed the dog/ms |
0 |
113 |
7.28 |
1 |
227 |
14.56 |
2 |
455 |
29.12 |
3 |
910 |
58.25 |
2. Problems with the atomic Battleship WWDG library function Routines
2.1 Problem Description
Under normal circumstances, the WWDG library function (v3.5) routine provided by the burning atom battleship will see that the red light is lit at first, then goes out, and the yellow lights start flashing. However, burn the program and only see the red light flashing. This indicates that the WWDG generated an interrupt, but the yellow blinking statement (LED1=~LED1) in the interrupt function was not executed. 2.2 Problem Solving
For the above problem description, you can exclude the problem of WWDG initialization error (because the red light LED0 is flashing, indicating that the WWDG has been generated), to locate the interrupt initialization failure or interrupt function writing error problem. The interrupt function is relatively simple and can be used to eliminate the problem of writing an interrupt function after checking.
Below, a check is made for the interrupt initialization function. After checking, it can be found that the interrupt channel enable setting is missing in the original routine, i.e. "nvic_initstructure.nvic_irqchannelcmd=enable; Channel enable ". The code changes before and after the comparison is shown below. After the modification, again burn execution, will find the phenomenon is normal: At first, the red light lit, then extinguished, the yellow light began to blink.
(1) Interrupt initialization of the original code:
WWDG interrupt initialization of
void Wwdg_nvic_init ()
{
nvic_inittypedef nvic_initstructure;
Nvic_initstructure.nvic_irqchannel = wwdg_irqn; WWDG Interrupt
//preemption 2 sub-priority 3 Group 2
nvic_initstructure.nvic_irqchannelpreemptionpriority = 2;
nvic_initstructure.nvic_irqchannelsubpriority = 3;
Nvic_init (&nvic_initstructure);//nvic initialization
}
(2) Interrupt initialization of modified code:
WWDG interrupt initialization of
void Wwdg_nvic_init ()
{
nvic_inittypedef nvic_initstructure;
Nvic_initstructure.nvic_irqchannel = wwdg_irqn; WWDG Interrupt
//preemption 2 sub-priority 3 Group 2
nvic_initstructure.nvic_irqchannelpreemptionpriority = 2;
nvic_initstructure.nvic_irqchannelsubpriority = 3;
nvic_initstructure.nvic_irqchannelcmd=enable; Channel Enable
Nvic_init (&nvic_initstructure);//nvic initialization
}
2.3 Problem Supplement--WWDG sequence of library function calls when initializing
(1) for the following WWDG initialization function, after burning, run normally. However, the WWDG enable and load initial value statement wwdg_enable (WWDG_CNT) is placed on the purge wake-up interrupt flag bit statement Wwdg_clearflag () and the open window watchdog interrupt Statement Wwdg_enableit () is executed again, Abnormal phenomenon: Only the red light is flashing, the yellow light has been extinguished.
Correct program:
Saves the setting value of the WWDG counter, which defaults to maximum.
U8 wwdg_cnt=0x7f;
Initialize window watchdog
//tr : t[6:0], counter value
//WR : w[6:0], window value
//fprer: Divider factor (WDGTB), minimum 2 bits 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; Initializes the wwdg_cnt.
Wwdg_setprescaler (fprer);////set IWDG prescaler value
wwdg_setwindowvalue (WR);//Set window value
wwdg_nvic_init ();//Initialize window watchdog NVIC
wwdg_enable (wwdg_cnt); Enable WWDG and load initial value
Wwdg_clearflag ();//Clear wake-up interrupt flag bit
Wwdg_enableit ();//Open window watchdog interrupt
}
Exception Program:
Saves the setting value of the WWDG counter, which defaults to maximum.
U8 wwdg_cnt=0x7f;
Initialize window watchdog
//tr : t[6:0], counter value
//WR : w[6:0], window value
//fprer: Divider factor (WDGTB), minimum 2 bits 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; Initializes the wwdg_cnt.
Wwdg_setprescaler (fprer);////set IWDG prescaler value
wwdg_setwindowvalue (WR);//Set window value
wwdg_nvic_init ();//Initialize window watchdog NVIC
Wwdg_clearflag ();//Clear wake-up interrupt flag bit
Wwdg_enableit ();//Open window watchdog interrupt
wwdg_enable (wwdg_cnt) ; Enable WWDG and load the initial value
}
(2) Error analysis
Executes the wwdg_enable (WWDG_CNT) statement, which enables the WWDG to be loaded and the initial value CNT to the counter. Executing this sentence will also set the WWDG_SR's ewif to 1, causing the program to fail to enter the interrupt handler function.
Using Jlink to step through this in Keil, you can find that Wwdg_sr ewif is set to 1 after executing the wwdg_enable (WWDG_CNT) statement, as shown in the following figure.
First step: Before executing the wwdg_enable (wwdg_cnt) statement, the status register wwdg_sr=0x0000, which is ewif=0
Second step: After executing the wwdg_enable (wwdg_cnt) statement, the status register wwdg_sr=0x0001, which is ewif=1
(3) Conclusion
The WWDG enable function must be executed before the WWDG clears the early wake interrupt flag bit and the open window watchdog interrupt.