STM32F401xD/E has two Watchdog timers- Independent watchdog (IWDG) and Window watchdog (WWDG). In this project we will see how to activate and periodically pet the dog, I mean refresh the watchdog. Also we will see what will happen if you don't pet your watchdog within the window i.e. petting (refreshing) too late or too early.
Some knowledge of STM32CubeMX, Keil MDK, GPIOs, Counters are assumed from the reader to follow along.
TheoryAs the name watchdog suggests, it is watching the application running on the MCU. It is a monitoring function. In case of any abnormality from the normal sequence of program execution- software fault, the watchdog detects it. It then initiates a MCU reset, which will help to start the software all over again.
From the functionality stand point, there are two major differences between IWGD and WWDG.
- IWDG does not offer a window for refresh. [This means, IWDG doesn't care as long as it is refreshed before the down counter (WWDG_CR[6:0], rolls over]
- IWDG offers no Interrupt Service Routine (ISR) where as WWDG does. [This means, just before initiating a reset, an interrupt is generated, where you could write your routine to have a safe exit.]
Unlike IWDG, WWDG is clocked by the APB1 peripheral clock. The following image shows a snapshot form STM32CubeMX.
In this project we will, configure and test these cases.
- Case 1: Activate WWDG and we will not refresh the WWDG and check that a reset is triggered, by the time down counter WWDG_CR[6:0] is elapsed. We will monitor the reset line using Digilent- Analog Discovery (Legacy) instrument.
- Case 2: Include our routine to refresh it within the window and see that no reset is initiated by the WWDG. [At this point I have not yet explained what this window is. It will get familiar in some time]
- Case 3: We will refresh the WWDG too early and check that a reset is triggered.
- Case 4: We will enable the EWI interrupt and write a routine to toggle the on-board Green LED there. We will observe on the oscilloscope that the ISR is executed before initiating a MCU reset. This is an advance feature in WWDG which is not available in IWDG.
1. Create a project in STM32CubeMX from the board selector. Refer to the attached file for details- 'Create STM32CubeMX project'.
2. On the left pane, expand- System Core and select- WWDG. A window appears showing WWDG configuration. There click Activated. This activates the WWDG with the default configuration as displayed in the section 3 in the below image.
Lets understand these WWDG Clocking parameters.
WWDG counter clock prescaler: The resulting value of the clock is equal to (PCLK1/4096)/prescaler
- PCKL1 is APB1 clock (42MHz for STM32F401RE)
- 4096 is internal divider
[Prescaler is just a clock divider. Higher the prescaler lower the clock frequency to the counter. Thus longer the counting takes.]
Lets select the prescaler to be 8: (PCLK1/4096)/8
This results in the WWDG clock for down counter to be (42MHz/4096)/8 = 1281.738 Hz. Hence the clock period (1 clock cycle) is ca. 780us
tClkWwdg = 780us
Window: This term in WWDG refers to a time frame within which it is allowed to refresh the watchdog. Out of this zone is interpreted as software fault and MCU reset is initiated by the WWDG. Let us now configure this window. Please find the image below.
The highlighted 3 parameters define the window.
T[6:0] is WWDG_CR[6:0] register for down counter. The max value is 127. Once the watchdog is activated WWDG_CR[7] is set, the count down starts at a rate of tClkWWDG. In this case it is 780us.
W[6:0] is WWDG_CFR[6:0] register for window value that is to be compared to the downcounter during run-time.
0x3F is the lowest limit to which the down counter counts to. Once the counter reaches this value, a reset is triggered.
It is important that the WWDG is serviced (refreshed/updated) when the down counter value is greater than W[6:0] and less than 0x3F. Failing to refresh in this window is interpreted as a software fault by the WWDG and a reset is initiated.
Let us choose some values for the watchdog window.
Prescaler = 8; W = 94; T = 127.
Let us now calculate the timing.
Time taken by the down counter to count down from 127 to 63 is tWWDG = tClkWWDG * (127 - 63) = 49.92ms
No refresh is allowed from the start of the down counter 127 till it reaches 94, i.e. tNoRefr = tClkWWDG * (127-94) = 25.74ms
Refresh is allowed after tNoRefr and before tWWDG.
Lets get back to CubeMX, switch to Project Manager perspective and select Keil MDK, save the project and hit - 'Generate code'.
Note that Watchdog Interrupt (Early Wakeup Interrupt- EWI) is kept disabled. We will get to it at a later part.
Select Open project and the Keil MDK IDE opens up. As shown in the image below, open the main.c file.
Build the project and see that there are no errors.
Right click on the watchdog init function and select go to definition.
static void MX_WWDG_Init(void);
Note that the parameters are as we specified in CubeMX.
Also feel free to have a look at the source file- stm32f4xx_it.c
, for EXTI (External interrupt/event controller) routines. For the moment we have not configured any interrupts. In the later part we will have a deeper look at it.
Deploy and test:
Without wasting much time lets just build the project and deploy it to our ST32F401RE Nucleo board.
Case 1:Since we are not servicing yet the WWDG, after the down counter reaches 0x3F, a MCU reset will be triggered. We will connect Oscilloscope channel 1 of the super useful Digilent Analog Discovery to the Reset line and monitor it.
Our expectation, reset is triggered by the WWDG every ca.50ms.
CN4- Pin 5 is NRST
Please refer to the two images below for reference.
Open Digilent Waveforms. I have configured channel 1 with some measurement options- x cursors, that will help us see the frequency of reset occurrence.
Build the project and hit the debug button.
Let us monitor the CRC register from the RCC peripheral. Window watchdog reset flag (WWDGRSTF) and Remove reset flag (RMVF) are of interest in the CRC register. Please go through the STM32 MCU reference manual for details. I have just provided these two images of RCC_CRC register for convenience.
The code is still halted. You will notice that we have some reset flags set. Clear all the resets before proceeding to have a clean setup.
Click RMVF bit
Hit
Run (F5) to start the program
You will immediately see WWDGRSTF getting set.
We can see that as expected reset line is toggled every ca. 52ms.
Let us pet our dog so that it does't bark. Ok..I mean lets refresh our WWDG within the window and see what happens..
Go to main.c. If you are still in degug mode, exit the debug perspective. Include this snippet of code in the infinite while loop.
HAL_Delay(30);
HAL_WWDG_Refresh(&hwwdg);
HAL_Delay(30) halts the MCU for 30ms. We wait for 30ms and refresh the WWDG. As it might be clear by now that we can't refresh the watch dog for a duration of tNoRefr (25.74ms).
The outcome.. there should be any reset triggered by the WWDG. Lets build the project and check it..
Follow the same steps as before to build the project and open it in debug mode. Set the RMVF bit to clear the reset flags and Run the program. You should see that WWDGRSTF flag to be always clear.
No reset. Our dog is happy :)
Case 3:We will refresh the WWDG too early and check that a reset is triggered.
Modify the delay value from 30ms to anything less than tNoRefr (25.74ms).
I choose 15ms.
Result:
Since we are refreshing the WWDG much soon, a reset is triggered every 18ms.
Case 4:The most interesting part. We should not forget that WWDG has a beatiful feature - it generates an interrupt just before triggering a rest. This will help us to exit in a safe state, say take a snapshot of the system and store to EEPROM may be.
Lets check this functionality by enabling the EWI interrupt and write a routine to toggle the on-board Green LED. We will observe on the oscilloscope that the ISR is executed before initiating a MCU reset. This is an advance feature in WWDG which is not available in IWDG.
You could use CubeMX to enable the EWI graphically as shown below.
This is just not sufficient. We need to enable the Watchdog interrupt in NVIC settings. Without enabling the global watchdog interrupt just enabling EWI does not work as the interrupt will not be able to pass through the Interrupt Controler- NVIC. I highly recommend you to go through the EXTI section in the reference manual for more details as this is beyond the scope of this article.
Save the project and build. This time when you switch back to Keil, it should ask you that the files are updated and do you want to load them. Say, yes.
Now you should have the latest files in your Keil project. Go to the file stm32f4xx_it.c. You will see at the end this extra piece of code is added (in the red box). It is the WWDG interrupt handler.
Go to the definition of HAL_WWDG_IRQHandler(&hwwdg);
indicated in the blue box.
We can see that the early wakeup callback is enabled and __weak function is created for us. Copy the function and paste it in the main.c and remove __weak. Thats where we will write our routine to toggle the on-board Green LED to see if the ISR is executed before reset is initiated. Please see the image below indicating the location where it has to be copied in main.c. Do it after all the peripheral initialization functions are completed and in between user code begin and end.
Lets remove all the content from the function body and toggle our on-board LED.
Also, comment out the code written inside while(1) infinite loop. This time we will let the down counter elapse and expect that the WWDG resets the MCU. But before doing that we want it to service our interrupt. This we will monitor by toggling the led every 20ms.
Please follow the same steps as before to build the project and open it in debug mode. Set the RMVF bit to clear the reset flags and Run the program.
Result:
Please refer to the video showing toggling on-board Green LED-
Oscilloscope:
Ch1: NRST
Ch2: LED
We can see that the Interrupt is generated ca. 780us before reset, which is exactly one WWDG clock cycle before. But the reset is triggered every 52ms, i.e. only after the down counter counts down to 0x3F (decimal: 63).
Note: In case if you need complete information about HAL libraries for STM32F4 and how to use them, please refer to the manual UM1725. Description of STM32F4 HAL and low-layer drivers
ConclusionWe have configured and tested the Window watchdog of STM32F401RE in various scenarios. In Case 4, we see something quite interesting. The on-board led is not being toggled every 20ms. The reset is forcing the led to turn off as the WWDG is giving the MCU only 1 clock cycle to do anything important. As the reset happens every 52ms, we might misinterpret the LED toggling as our ISR routine. In fact the HAL_GPIO_TogglePin()
is not even fully executed. It is broken by the reset. Try to comment out the HAL_Delay()
, try to replace HAL_GPIO_TogglePin()
to HAL_GPO_WritePin()
and see what happens.
Also with the EWI enabled, try to refresh the WWDG too early and see if ISR is executed. Let me know if you have any questions. I would be happy to hear your feedback. Thanks for the read!
Comments