一般的 MCU都会内置两个内置了两个看门狗(独立看门狗和窗口看门狗),为软件系统增加了更加安全的检测机制。IWDG由专门的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效,使得它能够工作于低功耗模式下。IWDG 最适合应用于那些需要看门狗作为一个正在主程序外,能够完全独立工作,并且对时间精度要求低的场合。
IWDG看门狗的原理是:MCU系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种情况的发生。看门狗的作用就是在一定时间内(通过递减计数器实现)没有接收喂狗信号(表示 MCU 未正常运行),便实现处理器的自动复位重启(发送复位信号) 。
从IWDG看门狗的功能框图来看,它分为两个部分,配置寄存器在1.8V供电区,计数器的核心部分以及复位信号在VDD供电区(这使得即使在停机/待机模式下计数器也能计数) ;由于处在不同的电源域,每次加载新数据时都需检测状态位。
1. IWDG超时时间计算及喂狗
IWDG的工作流程为:在键值寄存器(IWDG_KR)中写入 0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值 0xFFF 递减计数。当计数器计数到末尾 0x000 时,会产生一个复位信号(IWDG_RESET)。无论何时,只要键寄存器 IWDG_KR 中被写入 0xAAAA, IWDG_RLR 中的值就会被重新加载到计数器中从而避免产生看门狗复位。IWDG_PR 和 IWDG_RLR 寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR 寄存器中写入 0x5555。将其他值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入 0xAAAA)也会启动写保护功能。
以下为看门狗超时时间说明表:
结合上表,正确的计算IWDG看门狗超时时间的公式为:
Tout=(4 * 2^PR * (RL+1) ) / 40 ms
其中 Tout 为看门狗溢出时间(单位为 ms) ;PR为看门狗时钟预分频值(IWDG_PR 值),范围为 0~7,0对应4分频,1对应8分频,......所以时间计算公式要乘以4;RL 为看门狗的重装载值(IWDG_RLR 的值)。
注意事项:看门狗的时钟不是准确的 40KHz,所以在喂狗的时候,最好不要太晚了,否则有可能发生看门狗复位!
2. IWDG中断做延时功能
为了满足某些场合的需求,可将IWDG产生的复位更改配置为产生中断,从而实现类似定时器的更新中断功能。
在初始化IWDG的时候,需要将LSI时钟开启,将IWDG->CR bit0位置为“溢出后产生中断 ”,以下为还需要注意的初始化代码片段:
- IWDG_WriteAccessCmd(0x5555);
- IWDG_SetPrescaler(IWDG_Prescaler);
- PVU_CheckStatus();//看门狗预分频更新状态位检测,该语句必须置于以上两句之后而不能在其前!!!
- IWDG_WriteAccessCmd(0x5555);
- IWDG_SetReload(Reload & 0xfff);
- RVU_CheckStatus();//看门狗计数器重装载值更新状态位检测,该语句必须置于以上两句之后而不能在其前!!!
以下为看门狗中断服务程序中要注意的代码片段:
- void WWDG_IRQHandler(void)
- {
- LED2_OFF();//用作调试,指示延时时间
- IWDG_ClearIT();//IWDG->CR bit1 清除IWDG中断标志
- Write_Iwdg_ON(IWDG_Prescaler_4,992);//必须重新配置并开启看门狗!!!
- EXTI_ClearFlag(EXTI_Line24);//清除外部中断线标志,以实际芯片的映射为准
- LED2_ON();
- }
注意事项:IWDG看门狗的时钟不是准确的 40KHz,且进出中断都会消耗时间,不建议用此方式来做精准的延时!
3. IWDG硬件看门狗模式
在某些严苛的应用环境下软件看门狗可能都已经跑飞或者无法正常生效,就需要开启硬件看门狗来作为系统稳定运行的保障。MM32 MCU的IWDG具有软件看门狗和硬件看门狗模式,默认状态下为软件看门狗模式。如果用户在选择字节中启动了‘硬件看门狗’功能,在系统上电复位后,看门狗会自动开始运行而不需要软件开启看门狗;硬件看门狗开启后如同软件看门狗一样,需要及时做喂狗处理,否则系统会产生复位;该模式开启后,在调试程序时也无法停止和关闭看门狗,想要关闭则必须对选项字节对应位进行修改或者擦除。
以下为可供参考的实现功能的样例代码片段:
- RCC_LSICmd(ENABLE);//LSI启动并且等待LSI起振标志位置位
- while ((RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)&&temp<250)
- {
- temp++;
- //delay_ms(10);
- }
- if(temp>=250)return 1;//LSI启动超时,出错返回
- if (FLASH->OBR & FLASH_OBR_WDG_SW) //若为软件看门狗,首次运行会进这里
- {
- //Write_Iwdg_ON(IWDG_Prescaler_32,0xFFF); //可根据实际需求改变预分频值和重载值
- FLASH_Unlock();
- FLASH_UserOptionByteConfig(OB_IWDG_HW,OB_STOP_NoRST,OB_STDBY_NoRST);//改用硬件看门狗,写法一
- //FLASH_ProgramOptionHalfWord(0x1ffff802,0,0x00FE);//改用硬件看门狗,写法二
- FLASH_Lock();
- NVIC_SystemReset(); //复位以生效Flash的操作
- }
注意事项: 建议不同版本的芯片都将LSI启动以保证硬件看门狗正常开启!
4. IWDG与低功耗模式
在开发中经常会用到独立看门狗(IWDG)和低功耗模式,看门狗是为了检测和解决由软件错误引起的故障,低功耗模式是为了在CPU不需要继续运行时进入到休眠模式用以节省电能。其中独立看门狗的时钟由独立的RC振荡器提供,即使在主时钟出现故障时,也仍然有效,因此可以在停止和待机模式下工作。
IWDG可以在低功耗模式下正常计数,它的复位能够使系统退出Standby模式。
IWDG与Stop低功耗模式共存的解决思路有——进Stop低功耗模式之前把LSI时钟关闭,这样就关掉了看门狗的时钟使得看门狗不工作;系统如果具备RTC功能,可以使用闹钟定时喂狗,喂完狗再继续休眠。比如看门狗复位的时间间隔为10s。那么在进入休眠模式前设置RTC闹钟中断时间为5s。这样每隔5s唤醒一次喂一次狗,便可以很好的解决这个问题。
5. 使用高速振荡器时钟计算内部LSI时钟频率
在使用内部LSI时钟作为RTC的计数时钟源时,考虑到LSI的频率为40KHz左右但不准确,在设置RTC的预分频值时可能需要先计算到较为准确的LSI时钟频率。通过IWDG复位的协助可以实现此功能,以下为大致思路: