WDT
WDT(看门狗,WatchDog Timer)是一个APB从外设,可以用来防止由于SiFli芯片中的部件或程序冲突而导致的系统死机。 HCPU 和 LCPU 都有专用的WatchDog定时器。它可以生成中断作为不可屏蔽中断 (NMI) 或为子系统复位。WatchDog可以以独立复位 LCPU 或 HCPU 子系统。芯片还提供一个系统级别的Watchdog(IWDT),可以复位整个芯片。
工作机制
计数器
WatchDog有 2 个计数(count1 和 count2),从预设的超时值降序到零。计数器基于 32K 时钟,每 1/32768 秒减一。 1。当计数器 count1 达到零时,根据选择的输出响应模式,系统复位或中断发生。用户可以重新启动计数器到其初始值,或停止它。重新启动看门狗计数器的过程有时被称为喂狗(Pet Watchdog)。
中断
可以对WatchDog进行编程,使watchdog在count1 超时时产生中断, 同时count2开始计数。如果中断不被清理,在count2 超时的时候系统复位;如果它在第二次超时(count2 达到 0)之前清除中断,count1被复位,同时count2复位,重新开始计数。
备注
IWDT不会产生中断,直接复位芯片
系统复位
WatchDog也可以被编程为直接产生系统复位。 HCPU 或 LCPU 子系统在计数器count1减为 0后复位。
备注
SF32LB55X 有三个WDT, HCPU WDT1, LCPU WDT2以及一个系统IWDT. 其中WDT1/2提供中断功能,触发时只能reset HCPU/LCPU子系统。 IWDT不能提供中断功能,不过触发时可以reset整个芯片。55X的WDT时钟可以在RC10K/32K LXT中选择。 SF32LB56X/58X WDT1/WDT2 增加了功能,可以触发reset 整个芯片,SF32LB56X/58X的时钟来源于RC10K,不再从32K低功耗时钟获取。
使用WDT
以下代码将启动WatchDog定时器而不产生中断。
WDT_HandleTypeDef WdtHandle;
// Initialize Watchdog timer.
{
WdtHandle.Init.Reload = (uint32_t)g_tmout * 32768 ; // Counter is based on 32K clock, g_tmout is in seconds
HAL_WDT_Init(&WdtHandle); // Initialize the counter
__HAL_WDT_INT(&WdtHandle, 0); // Set to reset only, do not generate interrupt
}
__HAL_WDT_START(&WdtHandle); // Start watchdog timer.
...
HAL_WDT_Refresh(&WdtHandle); // Kick watchdog
HAL_Delay(g_tmout+1); // If do not kick watchdog befre g_tmout, reset will happen.
HAL_WDT_Refresh(&WdtHandle); // This will not reach, as watchdog reset system.
...
__HAL_WDT_STOP(&WdtHandle); // Stop watchdog timer.
以下代码将启动WatchDog定时器并在第一个计数器达到 0 后产生中断。
WDT_HandleTypeDef WdtHandle;
// Watchdog interrupt, It is a non-maskable interrupt
void WDT_IRQHandler(void)
{
__HAL_WDT_CLEAR(&WdtHandle); //cLear interrupt will reset timer 1.
}
// Initialize Watchdog timer.
{
WdtHandle.Init.Reload = (uint32_t)g_tmout1 * 32768 ; // Counter 1, counter is based on 32K clock, g_tmout1 is in seconds.
WdtHandle.Init.Reload2 = (uint32_t)g_tmout2 * 32768; // Counter 2, counter is based on 32K clock, g_tmout2 is in seconds.
HAL_WDT_Init(&WdtHandle); // Initialize the counter
__HAL_WDT_INT(&WdtHandle, 1); // Generate interrupt when g_tmout1 times out before you kick interrupt
}
__HAL_WDT_START(&WdtHandle); // Start watchdog timer.
...
HAL_WDT_Refresh(&WdtHandle); // If kick before g_tmout1, it will NOT generate interrupt
HAL_Delay(g_tmout1+g_tmout2+1); // If kick after g_tmout1, interrupt will generate.
HAL_WDT_Refresh(&WdtHandle); // This could reach if you kick watchdog in interrupt.
...
__HAL_WDT_STOP(&WdtHandle); // Stop watchdog timer.