【应用笔记】TAE32G5800 IWDG 使用详解
独立看门狗具有安全性高、使用灵活的特点。可用于检测并解决软件错误导致的故障,在定时器到达指定的超时值时触发系统复位。独立看门狗(IWDG)由其专用低速时钟(LSI)驱动,因此即便在主时钟发生故障时仍然保持工作状态。IWDG 最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。
IWDG 主要具有以下特性:
▶ 自由运行递减计数器
▶ 16 位重载计数值寄存器,计数时钟支持 4 到 512 分频
▶ 时钟由独立 RC 振荡器(LSI)提供(可在待机模式下独立运行)
▶ 当递减计数器值达到 0x0 时产生复位(如果看门狗已激活)
3.1 IWDG 键值功能
对 IWDG->KEYR_b.KEY 写入图 3.1 的键值,实现其相应功能。
键值 | 功能 |
---|---|
0x3FAC
|
使能对 CR、RLV 和 PSC 寄存器的访问
|
0xAAAA
|
可发起 RLV 值的重装
|
0xCCCC
|
使能看门狗
|
0xDDDD
|
关闭看门狗
|
在使能窗口看门狗之后递减计数器(WWDG_CVR[15:0]) 就开始运行, 每个计数周期执行一次递减操作。使能看门狗前,用户需要根据自己的应用需求确保以下限制:
IWDG 预分频寄存器(IWDG_PSCR)、重加载寄存器(IWDG_RLR)及控制寄存器(IWDG_CR)具有写访问保护。若要修改上述寄存器,首先需要将 0x3FAC 写入键寄存器(IWDG_KEYR[15:0]) 解除上述寄存器的访问保护;写入其他值,则使寄存器访问保护重新生效,下次修改则需要重新解除访问保护。这意味着重装载操作(写 0xAAAA) 也会启动写保护功能。
状态寄存器指示预分频值和递减计数器是否正在被更新。
4.1 中断模式
中断模式下,IWDG 在未重载导致超时后,IWDG_SR 寄存器中的 TOIF 将会置位,并触发中断(如果使能 IWDG 中断),且不会导致系统复位。
复位模式下,IWDG 在未重载导致超时后,触发一个系统复位信号,如果 RCU_SRSTSR 中的 IWRSTE 位(RCU_SRSTSR.IWRSTE)已经使能,则会引发系统复位(如果 IWRSTE 位未使能,则同样不会导致系统复位,直到该位使能)。
当芯片进入调试模式时(Cortex™-M4 内核停止),IWDG 计数器会根据 SYSCTRL_SYSDCR 寄存器中的 IWDGDEN 位(SYSCTRL_SYSDCR. IWDGDEN) 选择继续正常工作或者停止工作。
LSI(32KHz)时钟作为 IWDG 的时钟源,可通过 IWDG->PSCR_b.PSC 修改 IWDG 的分频系数。图 5.1 为 32KHz 下,不同分频系数的计时时间。
6.1中断模式配置
代码清单 6.1 为 IWDG 看门狗初始化函数、中断函数。递减计数器计数到 0 后进入中断翻 IO。
//初始化 IWDG
void User_IWDG_Init(IWDG_TypeDef *Instance)
{
IWDG_InitTypeDef iwdg_init;
//User IWDG Init, Interrupt period set to 1s
iwdg_init.mode = IWDG_MODE_INTERRUPT; //IWDG->CR_b.MODE 寄存器
IWDG->CR_b.TOIE 寄存器
iwdg_init.pre_div = IWDG_PRE_DIV_4; //IWDG->PSCR_b.PSC 寄存器
iwdg_init.reload_val = 8000; //IWDG->RLR_b.RLV 寄存器
LL_IWDG_Init(Instance, &iwdg_init);
LL_IWDG_Start(Instance); //IWDG->KEYR_b.KEY 寄存器
}
//IWDG 中断函数
void IWDG_IRQHandler(void)
{
if (__LL_IWDG_IsTimeoutIntEn(Instance) && __LL_IWDG_IsTimeoutIntPnd(Instance))
{
//Interrupt Pending Clear
__LL_IWDG_TimeoutIntPnd_Clr(Instance); //清除标志位 IWDG->SR_b.TOIF 进中断后,
超时中断标志位会置位,需要对该位写 1 清 0
LL_GPIO_TogglePin(GPIOA, GPIO_PIN_0); //PA0 IO 翻转
}
}
//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(GPIOA, &GPIO_Init);
}
代码清单 6.2 IWDG 看门狗初始化函数、GPIO 初始化函数。
//IWDG 初始化函数
void User_IWDG_Init(IWDG_TypeDef *Instance)
{
IWDG_InitTypeDef iwdg_init;
//IWDG RCU Reset Enable
__LL_RCU_RegWrite_Unlock(RCU);
__LL_RCU_IWDG_Rst_En(RCU);
__LL_RCU_RegWrite_Lock(RCU);
//User IWDG Init, Reset period set to 1s
iwdg_init.mode = IWDG_MODE_RESET; //IWDG->CR_b.MODE 寄存器
iwdg_init.pre_div = IWDG_PRE_DIV_4; //IWDG->PSCR_b.PSC 寄存器
iwdg_init.reload_val = 8000; //IWDG->RLR_b.RLV 寄存器
LL_IWDG_Init(Instance, &iwdg_init);
LL_IWDG_Start(Instance); //IWDG->KEYR_b.KEY 寄存器
}
int main(void)
{
SystemClock_Config();
LL_Init();
User_Debug_Init(USER_DBG_IFC_ITM);
User_GPIO_Init();
LL_GPIO_TogglePin(GPIOA, GPIO_PIN_0); //PA0 IO 翻转
User_IWDG_Example(IWDG);
while (1) {
delay_ms(10);
LL_IWDG_Refresh(IWDG); //喂狗
}
}
7.1中断模式
图 7.1 实际测出 LSI 时钟输出频率为 31.71KHz,按 4 分频得到 IWDG 的实际频率为 7.9275KHz,计数 800 次的时间为 100.91ms,由于确切的时序仍然依赖于 APB 接口时钟与 RC 振荡器时钟之间的相位差,因此总会有一个完整的 RC 周期是不确定的。图 7.2 MCU 的复位时间为 101.18ms 是符合设计要求的。IWDG 在未重载导致超时后,图 7.3 IWDG_SR 寄存器中的 TOIF 将会置位,并触发中断,PA2 翻转。
不喂狗测试:
图 7.4 实际测出 LSI 时钟输出频率为 31.71KHz,按 4 分频得到 IWDG 的实际频率为 7.9275KHz,计数 800 次的时间为 100.91ms,由于确切的时序仍然依赖于 APB 接口时钟与 RC 振荡器时钟之间的相位差,因此总会有一个完整的 RC 周期是不确定的。图 7.5 MCU 的复位时间为 101.06ms 是符合设计要求的。IWDG 在未重载导致超时后,PA2 翻转。
喂狗测试:
在 while 循环里每 10ms 喂一次狗,PA2 除初始化拉高后,再无电平变化,图 7.6 说明 MCU 没有复位。
7.3 RLV 重装测试
RLV 重装操作不等待 SR 寄存器 RLVUPD 置位,马上进行下一笔操作的测试。图 7.7 实际复位前的运行时间是 200ms 左右,也就是系统每 200ms 复位一次,RLV 生效的值为第二笔写入的 200,而第一笔写入的 100 并未生效。
原因:RLV 写入一笔后需要同步生效,在未生效之前再写入 RLV,此时又会开始重新同步生效,所以无论连续写多少次,生效的都是最后一笔。
解决方法:等待 SR 寄存器 RLVUPD 置 0 后,再进行重载操作。
7.4 PSC 写操作测试
PSC 写操作,不等待 SR 寄存器 PSCUPD 置位,马上进行下一笔操作的测试。图 7.8 实际复位前的运行时间是 25ms 左右,也就是系统每 25ms 复位一次,PSC 生效的值为 0,最小分频 4 分频,测试结果得到生效的 PSC 既不是第一笔写入的 32 分频,也不是第二笔写入的 64 分频。
原因:第一次写入 PSC 后,模块内部会进行时钟同步,此时若同步还没有完成,再次写入,会导致同步异常内部分频检测从 0 变 1 再变 0,因此 PSCUPD 标志位不会变成 0,实际分频也没有生效,如果此时写入第三次,则内部分频检测从 0 变成 0 再变成 1,此 PSCUPD 标志位可以从 1 变成 0,且写入的分频值生效。
解决方法:等待 SR 寄存器 PSCUPD 置位后,再写 PSC。
图 7.8 IWDG 复位时间