In the previous article, we talked about standalone watchdog timers.
In this article, we will look at the window watchdog timer.
Please forgive me if there is a little overlap with the previous article.
Here is the development environment at the time of posting.
PC: Windows 10 OS
IDE: STM32CubeIDE Version 1.3.0
Configurator: STM32CubeMX Version 5.5.0
Board: STM32Nucleo-F401RE
What is a watchdog timer?
We can call it a watchdog timer, or WDT for short.
It is a counter that is monitored and if it overflows, the microcontroller is reset.
The WDT is responsible for resetting the microcontroller to make it work properly if, for example, the program runs out of control and stops working.
Normally, the counter is refreshed to prevent the reset from occurring.
Until a long time ago, dedicated ICs that included a function to monitor the drop in power supply voltage were the mainstream, but nowadays, many of them are built into microcontrollers.
But nowadays, many of them are built into the microcontroller.
There are two types of watchdog timers available for the STM32
IWDG:
Independent Watchdog Timer
The first I stands for independence.
This is the more common of the two.
IWDG is a counter that runs and resets itself when it overflows.
The reason it is called an independent type is because the clock that runs the timer is separate from the main clock of the microcontroller.
Even if the microcontroller’s clock stops due to some fault, it can still be reset if the IWDG is running.
WWDG:
Window Watchdog Timer
Needless to say, the W at the beginning stands for window.
The meaning of window is a window frame rather than a window.
WWDG detects not only that a counter is overflowing, but also that its timing is earlier than expected.
In more robust systems, it seems to be recommended to use a combination of these two WDTs.
I’d like to add something that I failed to write last time.
Since this is about WWDG, it should only be described here.
The window watchdog timer runs on the microcontroller’s clock, so it can be stopped.
So if you need a watchdog timer in an intermittent system, this could be a useful tool.
Since ARM microcontrollers are known for their low power consumption, they are likely to be used in intermittent systems.
Window watchdog timer
In this article, we will check the behavior of the window watchdog timer.
As usual, create a project in the IDE (STM32CubeIDE).
Select File – New – STM32 Project.
In the Board Selector, select NUCLEO-F401RE and press Next.
Enter F401WWDT as the Project Name and press Finish.
When it asks “Initialize all peripherals with their default Mode ? and press Yes.
Do you want to initialize the peripherals with their default values?
This kind of project is associated with the STM32CubeMx perspective.
Press Yes when it asks “Do you want to open this perspective now?
This kind of project is associated with the STM32CubeMx perspective. Do you want to open it now?
I’m not sure what this means, but I interpreted it as “Do you want to import the configurator STM32CubeMX into the IDE layout? I interpreted it as “Do you want to import the STM32CubeMX configurator into the IDE layout?
Now I have created a project with certain specifications for this board, including the initialization of peripheral functions.
Click on WWDG in Pinout & Configuration – Categories – System Core.
Check the Mode – Activated checkbox.
In the Project Explorer, click on the project name F401IWDT and select Project – Build Project to build it.
MX_WWDG_Init() is now created in main().
Double-click on MX_WWDG_Init() to select it, and select Open Declaration from the right-click menu to see the inside of the function.
WWDT initialization code
static void MX_WWDG_Init(void)
{
hwwdg.Instance = WWDG;
Prescaler = WWDG_PRESCALER_1. hwwdg.Init;
hwwdg.Init.Window = 64;
Init.Counter = 64. hwwdg;
hwwdg.Init.EWIMode = WWDG_EWI_ENABLE;
if (HAL_WWDG_Init(&hwwdg) ! = HAL_OK)
{
Error_Handler();
}
}
Leaving out the comments, the code above is written.
hwwdg is a structure of type WWDG_HandleTypeDef.
Double-clicking on it to select it and right-clicking on the Open Declaration menu will take you to the declaration section where you can learn more about the structure.
Reset occurs during the initialization process
I don’t know why, but the reset occurs in HAL_WWDG_Init().
Next is the code generated by the configurator.
The reset is triggered the moment you step through the following part and write a value to the CR register of WWDG in the line above.
WRITE_REG(hwwdg->Instance->CR, (WWDG_CR_WDGA | hwwdg->Init.Counter));
WRITE_REG(hwwdg->Instance->CFR, (hwwdg->Init.EWIMode | hwwdg->Init.Prescaler | hwwdg->Init.Window));
I think this should be done in the opposite order, because we are enabling the watchdog timer before the conditions are set.
So I wrote the following code, and the reset is no longer triggered during the initialization process.
WRITE_REG(hwwdg->Instance->CR, hwwdg->Init.Counter);
WRITE_REG(hwwdg->Instance->CFR, (hwwdg->Init.EWIMode | hwwdg->Init.Prescaler | hwwdg->Init.Window));
if ((hwwdg->Instance->CR & 0x7f) < (hwwdg->Instance->CFR & 0x7f))
{
WRITE_REG(hwwdg->Instance->CR, (WWDG_CR_WDGA | hwwdg->Init.Counter));
}
In if(), we check that the counter value is less than the window value.
This is because writing a value to the CR register when the counter value is greater than the window value will cause a reset.
Actually, I had some doubts about this too, but since it worked, I was satisfied with the result.
What is questionable is that the watchdog timer is not enabled unless the condition in if() is satisfied.
However, it always goes through if(), so I said “Oh well”.
But if the condition of if() is taken, it resets the watchdog timer (mystery).
One more bonus.
I think the following code is the best, but when I use this one, it resets. This is also a mystery.
The counter is free-running, so this code seems to be fine.
while (1)
{
if ((hwwdg->Instance->CR & 0x7f) < (hwwdg->Instance->CFR & 0x7f))
{
WRITE_REG(hwwdg->Instance->CR, (WWDG_CR_WDGA | hwwdg->Init.Counter));
return HAL_OK;
}
}
Add code to refresh the counter
Let’s add a code in the main() function to refresh the counter so that it will not be reset.
while (1)
{
/* USER CODE END WHILE */
if ((hwwdg.Instance->CR & 0x7f) < (hwwdg.Instance->CFR & 0x7f))
{
HAL_WWDG_Refresh(&hwwdg);
}
/* USER CODE BEGIN 3 */ hwwdg.
}
Now, when we run the program, we can see that HAL_Init() only comes once at the beginning, which means that the counter refresh operation is working.
The refresh operation does not need to be done frequently in the while(1) loop, but should be handled periodically or otherwise considered by the system.
WWDG seems to be critical and very difficult to use.
If you are interested in it, please give it a try.





