【应用笔记】TAE32G5800 WWDG 使用详解
窗口看门狗通常被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常运行序列而产生的软件故障。除非递减计数器的值在 T6 位变成 0 前被刷新,看门狗电路在达到预置的时间周期时,会产生一个系统复位。如果在递减计数器达到窗口寄存器值之前刷新控制寄存器中的递减计数器值,也会产生复位。这意味着必须在限定的时间窗口内刷新计数器。
WWDG 主要具有以下特性:
▶ 自由运行递减计数器
▶ 当递减计数器值小于 0x40 时复位(如果看门狗已激活)
▶ 在窗口之外重载递减计数器时复位(如果看门狗已激活)
▶ 提前唤醒中断(EWI):当递减计数器减至 0x40 时触发(如果已使能且看门狗已激活),可用于在中断内重载计数器以避免 WWDG 复位
3.1 复位信号
如果激活看门狗( WWDG_CR 寄存器的 WEN 位置 1) , 当 16 位递减计数器从 0x40 滚动到 0x3F 时会引发复位信号;如果软件在计数器值(WWDG_CVR)大于窗口寄存器(WWDG_WVR)中所存储的值时重载计数器,也会产生复位信号。
如果 RCU_SRSTSR 寄存器的 WWRSTE 位置 1,则 WWDG 的复位信号最终导致系统复位。
应用程序在正常运行过程中必须定期地写 WWDG_CVR 寄存器以防止发生复位。只有当计数器值低于窗口寄存器值时,才能执行此操作。存储在 WWDG_CVR 寄存器中的值须介于 0xFFFF 和 0x40 之间(如果设置为 0x40 将无法触发提前唤醒中断 Early Wakeup Interrupt),用户应当根据实际应用需求合理配置。
在使能窗口看门狗之后递减计数器(WWDG_CVR[15:0]) 就开始运行, 每个计数周期执行一次递减操作。使能看门狗前,用户需要根据自己的应用需求确保以下限制:
▶ 递减计数器的值不应当配置 0x40 以下,否则启动窗口狗后将立即引发系统复位信号。
▶ 如果需要启用提前唤醒中断(EWI) 功能, 递减计数器的值不应当配置在 0x41 以下(仅在递减计数器从 0x41 递减至 0x40 时触发提前唤醒中断)
在 WWDG 开始工作后,为了防止系统复位,当递减计数器的值低于窗口寄存器(WWDG_WVR[15:0])的值,且大于 0x3F 时,必须对递减计数器进行重载(向 WWDG_CVR[15:0] 写入新值)。重载后递减计数器从新值重新开始按计数周期递减。
4.1复位模式
WWDG 的复位功能,还需要在 RCU_SRSTSR 寄存器的 WWRSTE 位置 1,使能 WWDG 的系统复位功能,否则 WWDG 发出的复位信号并不会引发实际的系统复位,直到 RCU_SRSTSR 寄存器的 WWRSTE 位置 1。
通过将 SYSCTRL_SYSDCR 寄存器的 WWDGDEN 位置 1,开启 WWDG 的调试模式。开启后,当 MCU 进入调试模式,并且处于 Halt 状态(Cortex™-M4 内核停止),WWDG 的递减定时器也会停止工作,直到退出调试模式或调试处于非 Halt 状态。
5.1超时公式
通过设置分频值和递减计数器的值,可以确定 WWDG 的超时时间。根据设定的超时时间来确定程序喂狗的位置。超时时间与分频值、递减计数器关系如下公式:
• tWWDG = tAPB0CLK × (PSC + 1) × (CV − 0x3F + 1)ms
PSC : WWDG_PSCR 窗口看门狗分频寄存器
CV : WWDG_CVR 窗口看门狗递减计数器
tWWDG : WWDG 超时时间
tAPB0CLK : APB0 时钟周期, 以 ms 为测量单位
案例:
假设 APB0 频率为 100MHz(tAPB0CLK=1/100000 ms),PSC 值为 99,CV 值为 999:
tWWDG =(1/100000)×(99 + 1)×(999 - 0x3F+ 1) = 1.87 ms
计数值在 WWDG_CVR.CV[15:0]~WWDG_WVR.WV[15:0]这部分时间为禁止刷新区,若在此喂狗,会产生一个复位信号,使系统复位。计数值在 WWDG_WVR.WV[15:0]~0x3F 这部分时间为允许刷新区,在此窗口喂狗,会重新更新计数值。计数到 0x40 时,产生一个提前唤醒中断。提前唤醒中断用于通知程序需抓紧处理,可以在中断里喂狗,也可做业务代码的提醒,表示这轮周期内喂狗不及时。
图 5.2 为 WWDG 不同分频系数下对应的超时时间最大值与最小值。
6.1中断
通过设置控制寄存器(WWDG_CR)中 EWIE 位使能该中断。当递减计数器的值从 0x41 递减至 0x40 时,将生成中断。在 WWDG 递减计数器继续递减到 0x3F 之前,可以使用相应的中断服务程序来触发特定操作(例如通信或数据记录) 或重载递减计数器避免复位。
注意:在提前唤醒中断的处理中,如果处理时间超过一个计数周期未重载递减计数器,计数器从 0x40 递减至 0x3F,WWDG 将发出复位信号,引发系统复位(如果使能复位)。因此所有操作必须在这一个计数周期内完成。
7.1中断模式配置
代码清单 7.1 为 WWDG 看门狗初始化函数、中断函数。递减计数器计数到 0x40 后进入中断翻 IO。
//初始化 WWDG
void User_WWDG_Init(IWDG_TypeDef *Instance)
{
WWDG_InitTypeDef iwdg_init;
__LL_RCU_RegWrite_Unlock(RCU);
__LL_RCU_WWDG_Rst_En(RCU);
__LL_RCU_RegWrite_Lock(RCU);
//User WWDG Init, Interrupt period set to 10ms
wwdg_init.counter = 10063-1;
wwdg_init.pre_div = 90-1;
wwdg_init.window = 5031;
wwdg_init.early_wk_int_en = true;
LL_WWDG_Init(Instance, &wwdg_init);
LL_WWDG_Start(Instance);
}
//GPIO 初始化函数
void User_GPIO_Init()
{
GPIO_InitTypeDef GPIO_Init;
//User GPIO Init
GPIO_Init.Pin = GPIO_PIN_0;
GPIO_Init.Alternate = GPIO_AF1_OUTPUT;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.IntMode = GPIO_INT_MODE_CLOSE;
GPIO_Init.OType = GPIO_OTYPE_PP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
LL_GPIO_Init(GPIOC, &GPIO_Init);
}
//WWDG 中断函数
void WWDG_IRQHandler(void)
{
if (__LL_WWDG_IsEarlyWakeupIntEn(Instance) &&
__LL_WWDG_IsEarlyWakeupIntPnd(Instance))
{
//Interrupt Pending Clear
__LL_WWDG_EarlyWakeupIntPnd_Clr(Instance); //清除标志位
LL_WWDG_Refresh(WWDG,10063-1); //喂狗
LL_GPIO_TogglePin(GPIOC, GPIO__PIN_0); //PC0 IO 翻转
}
}
代码清单 7.2 WWDG 看门狗初始化函数、GPIO 初始化函数。
//WWDG 初始化函数
void User_WWDG_Init(IWDG_TypeDef *Instance)
{
WWDG_InitTypeDef wwdg_init;
__LL_RCU_RegWrite_Unlock(RCU);
__LL_RCU_WWDG_Rst_En(RCU);
__LL_RCU_RegWrite_Lock(RCU);
//User WWDG Init, Interrupt period set to 10ms
wwdg_init.counter = 10063-1;
wwdg_init.pre_div = 90-1;
wwdg_init.window = 5031;
wwdg_init.early_wk_int_en = false;
LL_WWDG_Init(Instance, &wwdg_init);
LL_WWDG_Start(Instance);
}
//GPIO 初始化函数
void User_GPIO_Init()
{
GPIO_InitTypeDef GPIO_Init;
//User GPIO Init
GPIO_Init.Pin = GPIO_PIN_0;
GPIO_Init.Alternate = GPIO_AF1_OUTPUT;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.IntMode = GPIO_INT_MODE_CLOSE;
GPIO_Init.OType = GPIO_OTYPE_PP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
LL_GPIO_Init(GPIOC, &GPIO_Init);
}
int main(void)
{
SystemClock_Config();
LL_Init();
User_Debug_Init(USER_DBG_IFC_ITM);
User_GPIO_Init();
User_WWDG_Example(WWDG);
while (1) {
LL_GPIO_WritePin(GPIOC, GPIO_PIN_0,GPIO_PIN_SET); //PC0 IO 置高
delay_ms(5);
LL_WWDG_Refresh(WWDG,10063-1); //喂狗
}
}
8.1中断模式
图 8.2MCU 进入 WWDG 提前唤醒中断时,此时 WWDG 递减计数器值为 0x40,中断标志位被置位,PC0 翻转,图 8.1 每 10ms 翻转一次,符合程序设计。
不喂狗测试:
WWDG 时钟搭载在 APB0 总线上,APB0 时钟配置为 90M,按 90 分频得到 WWDG 的实际频率为 1MHz,计数 10063 次的时间为 10ms。图 8.3MCU 的复位时间为 10.02ms 是符合设计要求的。WWDG 在未重载导致超时后,PC0 翻转。
非窗口期喂狗测试:
设置的窗口值 5031(5ms),在 while 循环里每 4ms 喂一次狗,PC0 在 4ms 延迟前拉高,4ms 后喂狗,此时喂狗不在窗口时间内,MCU 复位,PC0 复位拉低。图 8.4 说明 MCU 复位。
窗口期喂狗测试:
设置的窗口值 5031(5ms),在 while 循环里每 8ms 喂一次狗,PC0 在 8ms 延迟前,8ms 后喂狗,此时喂狗在窗口时间内,MCU 不复位,PC0 恒为高。图 8.5 说明 MCU 没有复位。