2020-04-27 07:13 PM
I have repeatedly observed that changing the watchdog prescaler on a running watchdog from 16 down to 4 usually causes the watchdog counter to eventually stop decrementing. I assume this happens due to something like decreasing the prescaler value below the internal prescaler counters value. Sometimes it can be decreased and keeps running.
Anyways, I cant find any notes in the reference manual to say not to change the prescaler. IT is also a workaround to intentionally (or accidentally) stop a watchdog from running!
My code is set up correctly, window watchdog works exactly as expected. Only when reducing the prescaler to slow the watchdog down does it become and issue. The down counter stops decrementing as seen in the debugger and in my debug print output. No watchdog interrupt ever occurs if the down counter is stopped.
STM32H753
Solved! Go to Solution.
2020-04-27 11:46 PM
ANSWERED - While preparing an example that demonstrates this problem happening I stumbled upon what was going on and it makes sense. The watchdog counter does indeed cease to count down when its prescaler is changed, but not forever. Most likely long enough to cause a timing problem and watchdog reset if you are using the window feature.
Imaging the prescaler is a down counter that decrements the watchdog timer each time it reaches zero, then resets itself to the prescaler value (-1). So for a prescaler factor of 16, it decrements the watchdog counter every 16 clock counts. Now, say this prescalers counter is at 15 and you reduce the prescaler value to 4. You are expecting the watchdog counter to now decrement every four counts. But, for the first period the prescaler has to count all the way down to zero so it will take 15 clocks before the first time the watchdog counter is decremented. During this time the watchdog counter remains at a constant value. Kind of obvious really after you think about it, standard timer behavior without shadow registers.
In my case, this additional 11 counts equates to 5.5ms. This would not really be an issue if not using the window function. A risk that an expected watchdog reset could take longer but. If using the window function then you rely on another timer (tick count based maybe) to let you know if it has been long enough since the last kick to be allowed to kick again. So, you kick the dog, and think you are not allowed to kick it again for say 10ms, but it got stalled for 5.5ms by the prescaler change. So, when you go to kick it after 10ms, it has not counted down enough and you kick it inside the window and BOOM!
I have attached a minimal example (STM32H753ZITx and STM32CubeIDE) showing this happening for future reference. If you place a breakpoint on the line wdogslowed = 1, then after it is hit, place a breakpoint on the line 155 lastWDogKickTime = now then you can watch the WWDG CR counter not decrementing in the SFRs view. Eventually you will see it start to decrement again.
2020-04-27 07:28 PM
Can you give a minimal working examples that shows the problem?
It would be a pretty big flaw in the concept of a watchdog. Not sure prescaler is meant to be changed while in use, but I can't see anything in the RM disallowing it.
2020-04-27 08:05 PM
Sorry, it is part of a huge code base. I already wasted most of a day trying to work out what was going on! I can give some of the code, but not a minimal working example as I cant justify any more time on it. FYI, my workaround was to leave the prescaler and adjust the counter and window values. Gives the same effect but not as clean in my case as the reason for adjusting the prescaler was to match an adjustment in clock frequency. I was lucky enough I could get the required counter and window correction without running out of resolution.
In this example, code is initialized by STM32CubeMX generated code. This is for a STM32H753 running at 480MHz SYSCLK. AFAIK all STM32 use the same watchdog timer:
void MX_WWDG1_Init(void)
{
hwwdg1.Instance = WWDG1;
hwwdg1.Init.Prescaler = WWDG_PRESCALER_16;
hwwdg1.Init.Window = 85;
hwwdg1.Init.Counter = 101;
hwwdg1.Init.EWIMode = WWDG_EWI_ENABLE;
if (HAL_WWDG_Init(&hwwdg1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_WWDG_MspInit(WWDG_HandleTypeDef* wwdgHandle)
{
if(wwdgHandle->Instance==WWDG1)
{
/* USER CODE BEGIN WWDG1_MspInit 0 */
/* USER CODE END WWDG1_MspInit 0 */
/* WWDG1 clock enable */
__HAL_RCC_WWDG1_CLK_ENABLE();
/* WWDG1 interrupt Init */
HAL_NVIC_SetPriority(WWDG_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(WWDG_IRQn);
/* USER CODE BEGIN WWDG1_MspInit 1 */
/* USER CODE END WWDG1_MspInit 1 */
}
}
To change the prescaler I used the following:
// If watchdog is enabled, then correct its tick period
if (READ_REG(hwwdg1.Instance->CR) & WWDG_CR_WDGA)
{
// We have dropped APB3 clock frequency by a factor of 4, so reduce prescaler by a factor of 4
MODIFY_REG(hwwdg1.Instance->CFR, WWDG_CFR_WDGTB_Msk, WWDG_PRESCALER_4);
}
This code has a system thread running at 2ms loop dedicated to critical tasks as well as kicking the window watchdog within its allowed times. In that thread I printed the watchdog counter values before and after changing the prescaler. Most of the time they would stop down counting after the prescaler change, but occasionally they would keep down counting but at the new correct rate. I think it depends on the value of the internal prescaler counters value at the time you change the prescaler.
2020-04-27 08:24 PM
I messed around with it for a few minutes, could not replicate what you're seeing. Updates to the prescaler do appear to take effect immediately.
2020-04-27 08:31 PM
@TDK ,
> // We have dropped APB3 clock frequency by a factor of 4, so reduce prescaler by a factor of 4
Can't this be the reason?
JW
2020-04-27 08:42 PM
You would need to be varying when you altered the pre-scaler value. If when you alter it is synchronous with the watchdog counter then it may always work.
2020-04-27 08:43 PM
After clock frequency reduction, APB3 is running at 30 MHz. Other peripherals are running fine and as mentioned, sometimes the watchdog works fine after a prescaler change too, other times it just doesn't...
2020-04-27 08:47 PM
Understood. Like I said, I tried and could not replicate. I'm not going to spend hours on it.
2020-04-27 09:04 PM
Fair enough. One detail I just thought of was that I was most likely altering the prescaler during the window period (where you are not allowed to alter the counter value). But I dont see how that would be relevant. Actually, some times when it did work it was in that period and I saw it count down out of that period OK.
2020-04-27 09:05 PM
Are you suggesting changing APB3 clock frequency could trigger the issue? Or combination of that with reducing prescaler? Possible. I did not test that.
WWDG logic is pretty simple. I'd be surprised if there was a bug in the silicon.