发 帖  
原厂入驻New
[分享]

MM32 独立看门狗与窗口看门狗

2017-11-9 16:12:10  1560
分享
本帖最后由 MMCU5721167 于 2017-11-9 16:34 编辑

来源 灵动MM32
  MM32有两看门狗:独立看门狗(IWDG)和窗口看门狗(WWDG)。两看门狗均可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,将触发一个中断(仅适用于窗口型看门狗)或产生系统复位。
  独立看门狗,英文:Independent watchdog(IWDG)。独立的看门狗是基于一个可编程的 12位的递减计数器和一个 8 位的预分频器,它由一个内部独立的 40KHz 的振荡器提供时钟;因为这个振荡器独立于主时钟,所以它可运行于停机和待机模式。它可被当成看门狗用于发生问题时复位整个系统,或作为一个自由定时器为应用程序提供超时管理。通过选项字节可配置成软件或硬件的启动看门狗。在调试模式下,计数器可以被冻结。
  窗口看门狗,英文:Window watchdog(WWDG),它由主时钟驱动,从 APB1 时钟分频后得到的时钟驱动。窗口看门狗内有一个 7 位的递减计数器,并可设置成自由运行。它可以被当成看门狗用于在发生问题时复位整个系统。具有早期预警中断功能;在调试模式下,计数器可以被冻结。
  IWDG 最适合应用于那些需要看门狗作为一个能够在主程序外完全独立工作的模块,并且对时间精度要求低的场合。而WWDG 最适合那些要求看门狗在精确计时窗口起作用的应用程序。

              独立看门狗框图                    
62.jpg

  配置独立看门狗有4个32位的寄存器,分别为键寄存器KR、重装载寄存器RLR、状态寄存器SR和预分频寄存器PR。
  IWDG_PR 和 IWDG_RLR 寄存器具有写保护功能,要修改这两个寄存器的值,必须先向IWDG_KR 寄存器中写入 0x5555。以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护,重装载操作(即写入 0xAAAA)也会启动写保护功能。
  IWDG操作流程:往IWDG的键寄存器(IWDG_KR)中写入 0xCCCC就会开始启动独立看门狗,此时计数器开始从其装载值开始递减计数,这些位具有写保护设置,只有当状态寄存器IWDG_SR中的RVU位为0时,才能对重装载寄存器的12位重装载值进行再次修改,当重装载值正在进行更新时,RVU位由硬件置‘1’,当重装载更新结束后,此位由硬件清‘0’(最多需要5个40KHz的振荡器周期)。当计数器计数到末尾 0x000 时,会产生一个复位信号(IWGD_RESET),复位系统。只要在键寄存器IWDG_KR中写入0xAAAA,IWDG_RLR中的重装载值就会被重新加载到计数器,从而避免产生看门狗复位。
  可以通过设置预分频寄存器的[2:0]位来选择计数器时钟的预分频因子,从而改变提供给递减计数器的时钟频率,这些位具有写保护设置,只有当状态寄存器IWDG_SR中的PVU位为0时,才能对预分频因子进行再次修改,类似的当预分频值正在更新时,PVU位由硬件置‘1’,预分频值更新结束后再由硬件清‘0’(最多需要5个40KHz的振荡器周期)

看门狗超时时间(40KHz的输入时钟(LSI ))
63.jpg
独立看门狗超时时间的具体为公式为:

64.png

例程中关键的两个函数是启动看门狗的函数Write_Iwdg_ON和喂狗函数Write_Iwdg_RL。
1、启动函数:Write_Iwdg_ON
void Write_Iwdg_ON(unsigned short int IWDG_Prescaler,unsigned short int Reload)
{
/*启动内部低速时钟,等待时钟就绪*/
RCC_LSICmd(ENABLE);                          //1
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET);//2
   
/*设置时钟预分频*/     
PVU_CheckStatus();                             //3
IWDG_WriteAccessCmd(0x5555);                 //4
IWDG_SetPrescaler(IWDG_Prescaler);             //5
   
/*设置重载寄存器值*/  
RVU_CheckStatus();                            //6
IWDG_WriteAccessCmd(0x5555);                 //7
IWDG_SetReload(Reload&0xfff);                    //8
   
/*装载并使能计数器*/  
IWDG_ReloadCounter();                        //9
IWDG_Enable();                              //10
}
1和2处函数启动内部低速(LSI)时钟并等待时钟就绪。

3处函数PVU_CheckStatus()的功能是读取IWDG_SR寄存器的PVU位,直到PVU位为0时函数才结束。

4处函数IWDG_WriteAccessCmd(0x5555)的功能是向键寄存器中写入0x5555,以允许软件对预分频寄存器的写入操作。

5处即写入设定的预分频值。例程中定义了与预分频值有关的几个宏,以方便软件书写,并增加代码的可读性。
#define IWDG_Prescaler_4            ((uint8_t)0x00)
#define IWDG_Prescaler_8            ((uint8_t)0x01)
#define IWDG_Prescaler_16           ((uint8_t)0x02)
#define IWDG_Prescaler_32           ((uint8_t)0x03)
#define IWDG_Prescaler_64           ((uint8_t)0x04)
#define IWDG_Prescaler_128          ((uint8_t)0x05)
#define IWDG_Prescaler_256          ((uint8_t)0x06)

6处函数RVU_CheckStatus()的功能是读取IWDG_SR寄存器的RVU位,直到PVU位为0时函数才结束。

7处函数IWDG_WriteAccessCmd(0x5555)的功能是向键寄存器中写入0x5555,以允许软件对重装载寄存器的写入操作。

8处即写入设定的重装载值。

9处函数IWDG_ReloadCounter实现的功能是重装载递减计数器的值,即是所说的喂狗函数,具体实现就是向键寄存器中写入0xAAAA的值。

10处函数IWDG_Enable功能是启动独立看门狗,具体实现是向键寄存器中写入0xCCCC的值。
2、喂狗函数:Write_Iwdg_RL
void Write_Iwdg_RL()
{
IWDG_ReloadCounter();
}
喂狗函数即简单的调用了重装载函数。
3、主函数:
int main(void)
{
   
delay_init();                    //1
uart_initwBaudRate(115200);     //2
   
printf("uart ok!\r\n");           //3
   
Write_Iwdg_ON(IWDG_Prescaler_32,0x7ff);//超时时间约为1.6s
while(1)//
{
delay_ms(160);      //4
Write_Iwdg_RL();    //5
}
}
这里略过需要包含的头文件,这里直接介绍主函数的内容;

1处初始化延时函数,是为了在4处调用了函数delay_ms();

2处初始化uart,波特率为115200;波特率表征了UART传输数据的速率。

3处通过调用初始化uart后提供的接口函数printf打印提示信息;

4 处开启独立看门狗 第一个形参为预分频系数,第二个形参为重装载计数值;

5 处喂狗函数函数,注释以后芯片会不断复位;
实验结果对比:

注释喂狗函数,程序一直复位,串口不断打印提示信息。

65.png

未注释喂狗函数,程序不再不断复位,串口只打印一次提示信息

66.png
窗口看门狗框图
67.jpg

  WWDG有三个寄存器,控制寄存器CR、配置寄存器CFR,状态寄存器SR。
  如果启动了看门狗并且允许中断,当递减计数器等于 0x40 时产生早期唤醒中断(EWI),它可以被用于重装载计数器以避免 WWDG 复位。
  如上图,除非CFR寄存器中递减计数器的值在CR寄存器的T6 位(上图右下侧)变成 0 前被刷新,看门狗电路在达到预置的时间周期时后(即递减计数器的值变为0x40),会产生一个 MCU复位。在递减计数器达到设定的窗口寄存器数值之前,如果 7 位的递减计数器数值被刷新,那么也将产生一个 MCU 复位。这说明了递减计数器需要在一个有限的时间窗口中被刷新,WWDG才不会产生复位信号,这是WWDG与IWDG主要的区别
WWDG超时时间计算与具体复位原理还可以参考下图:

68.jpg
WWDGde 的计数时钟为(PCLK1/4096)/x,x为预分频系数。
  类似的要改变窗口看门狗的超时时间可以修改预分频值与重装载值,但他们没有写保护的功能,与独立看门狗相比程序会少配置一部分。
调用函数WWDG_SetPrescaler可以修改预分频值,这里也预先定义了一些有关预分频系数的宏:
#define WWDG_Prescaler_1    ((uint32_t)0x00000000)
#define WWDG_Prescaler_2    ((uint32_t)0x00000080)
#define WWDG_Prescaler_4    ((uint32_t)0x00000100)
#define WWDG_Prescaler_8    ((uint32_t)0x00000180)

  调用函数WWDG_Enable可以修改重装载值并启动窗口看门狗,这里的重装载值要求小于窗口值并大于0x40,不然窗口看门狗会立即产生复位信号。
1、启动函数Wwdg_reset_ON
void Wwdg_reset_ON(unsigned char ucTcnt,unsigned char ucWcnt)
{
/*使能窗口看门狗时钟*/
RCC_APB1PeriphclockCmd(RCC_APB1Periph_WWDG, ENABLE);    //1
/*WWDG_Prescaler_x,x为1,2,4,8,WWDG counter clock = (PCLK1/4096)/x */
WWDG_SetPrescaler(WWDG_Prescaler_8);  //2
WWDG_SetWindowValue(ucWcnt);        //3
/*为看门狗自减计数器赋值,为7位数据且数值为0x40~0x7f之间*/
WWDG_Enable(ucTcnt);  .//4
}

1处开启窗口看门狗的时钟,WWDG的时钟时挂载在APB1上。

2处调用函数WWDG_SetPrescaler,设置WWDG的预分频系数。

3处调用函数WWDG_SetWindowValue,设置WWDG的窗口值。

4处设定重装载值,并启动看门狗。
2、喂狗函数WWDG_SetCounter
void WWDG_SetCounter(uint8_t Counter)
{
/* Check the parameters */
assert_param(IS_WWDG_COUNTER(Counter));
/* Write to T[6:0] bits to configure the counter value, no need to do
a read-modIFy-write; writing a 0 to WDGA bit does nothing */
WWDG->CR = Counter & BIT_Mask;
}
  这里的函数即先检查形参是否满足重装载计数值的取值范围,后将符合要求的数值写入WWDG的重装载计数器。
3、主函数
int main(void)
{
delay_init();                 //1
uart_initwBaudRate(115200);  //2
printf("WWDG_Reset ok!\r\n");        //3
Wwdg_reset_ON(0x7e,0x7f);  //4
while(1)                                       
{
//WWDG_SetCounter(0x7e);//5
delay_ms(1);             //6
}
}
略过需要包含的头文件,直接介绍主函数的内容;
1处初始化延时函数,是为了在6处调用了函数delay_ms();

2处初始化uart,波特率为115200;

3处通过调用初始化uart后提供的接口函数printf打印提示信息;

4 开启窗口看门狗,第一个形参为  重装载计数值,第二个形参为窗口值;这里要注意的是重装载计数值必须小于窗口值,不然程序会立即复位,因为在窗口之外调用了重装载函数。
5 重装载函数,注释以后芯片会不断复位;
实验结果对比:

注释重转载函数,程序一直复位,串口不断打印提示信息

69.png

未注释重装载函数,程序不再不断复位,串口只打印一次提示信息

70.png

小结:
1、 IWDG和WWDG区别:
(1)独立看门狗没有中断,窗口看门狗有中断。
(2)独立看门狗有硬件软件之分,窗口看门狗只能软件控制。
(3)独立看门狗只有下限,窗口看门狗有下限和上限。
(4)独立看门狗是12位递减的。窗口看门狗是7位递减的。
(5)独立看门狗是用的内部的大约40KHz振荡器,窗口看门狗是用的系统时钟APB1。

2、 在程序调试阶段不要开启看门狗功能,在客户支持时很多客户在调试程序过程中开启了看门狗然后进入debug,由于程序执行断点的时间超过了喂狗时间,最后会复位或者进入Hardfault,导致程序仿真出现问题。

3、 在配置独立看门狗时,如果在应用程序中使用多个重装载值或预分频值,则必须在 RVU 位被清除后才能重新改变预装载值,在 PVU 位被清除后才能重新改变预分频值。然而,在预分频和/或重装值更新后,不必等待 RVU 或 PVU复位,可以继续执行下面的代码。(即使在低功耗模式下,次写操作仍会被继续执行完成)
4、 在系统复位后,窗口看门狗总是处于关闭状态,设置 WWDG_CR 寄存 器的 WDGA 位能够开启看门狗,随后它不能再被关闭,除非发生复位。

0
2017-11-9 16:12:10   评论 分享淘帖

只有小组成员才能发言,加入小组>>

1682个成员聚集在这个小组

加入小组

创建小组步骤

快速回复 返回顶部 返回列表