看门狗扫盲

下面以STM32为例介绍

独立看门狗

在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,(造成各种寄存器和内存的数据混乱,导致程序指针错误,不在程序区,取出错误的程序指令等)造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog)。

看门狗是一个定时器电路, 一般有一个输入,叫喂狗,一个输出到MCU的RST端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给WDT清零,如果超过规定的时间不喂狗,(一般在程序跑飞时,不在程序正常的状态),WDT 定时超过,就会给出一个复位信号到MCU,使MCU复位,防止MCU死机。所以,看门狗的作用就是防止程序发生死循环,或者说程序跑飞。

独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它仍有效。换句话说,独立看门狗拥有自己的时钟源。假如PLL崩溃了,负责运行程序的硬件单元ALU就无法工作,也就无法喂狗。独立看门狗依然能够正常工作,检测到其计数值为0,认为软件故障,则触发系统复位。

注:看门狗命令在程序的中断中拥有最高的优先级。

场景

独立看门狗适合应用于需要看门狗作为一个在主程序之外能够完全独立工作,并且对时间精度要求低的场合。

以STM32为例:

image-20200822145753829

STM32F4的独立看门狗由内部专门的 32Khz 低速时钟(LSI)驱动,即使主时钟发生故障,它也仍然有效。这里需要注意独立看门狗的时钟是一个内部RC时钟,所以并不是准确的32Khz,而是在15~47Khz 之间的一个可变化的时钟,只是我们在估算的时候,以 32Khz 的频率来计算,独立看门狗对时间的要求不是很精确,所以,时钟有些偏差都是接受的范围。

当通过对关键字寄存器 (IWDG_KR) 写入值 0xCCCC 启动独立看门狗时,计数器开始从复位值 0xFFF 递减计数。当计数器计数到终值 (0x000) 时会产生一个复位信号( IWDG 复位)。任何时候将关键字 0xAAAA 写到 IWWDG_KR 寄存器中, IWDG_RLR 的值就会被重载到计数器,从而避免产生看门狗复位。

寄存器访问保护
IWDG_PR 和 IWDG_RLR 寄存器具有写访问保护。若要修改寄存器,必须首先对 IWDG_KR寄存器写入代码 0x5555,而写入其他值则会破坏该序列,从而使寄存器访问保护再次生效。这意味着重装载操作(即写入 0xAAAA)也会启动写保护功能。注:状态寄存器指示预分频值和递减计数器是否正在被更新。

  1. 在键值寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗。此时计数器开始从其复位值0xFFF递减,当计数器值计数到尾值0x000时会产生一个复位信号(IWDG_RESET)。

  2. 无论何时,只要在键值寄存器IWDG_KR中写入0xAAAA(通常说的喂狗), 自动重装载寄存器IWDG_RLR的值就会重新加载到计数器,从而避免看门狗复位。

  3. 如果程序异常,就无法正常喂狗,从而系统复位。

    image-20200822150407952

独立看门狗配置流程

添加支持独立看门狗的库函数文件:stm32f4xx_iwdg.c

1
2
3
4
5
6
7
8
9
10
11
12
13
void Iwdg_Init(void)
{
//1、 取消寄存器写保护:
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//2、设置独立看门狗的预分频系数,确定时钟:125HZ (32000/256=125)
IWDG_SetPrescaler(IWDG_Prescaler_256);
//3、设置看门狗重装载值,确定溢出时间:2s
IWDG_SetReload(250);
//4、使能看门狗
IWDG_Enable();
//5、喂狗
IWDG_ReloadCounter();
}

在裸机代码实现喂狗,放在定时器里面,因为定时器与看门狗是使用不同的时钟源,允许这么做!

image-20200913213928315

如果有实时的操作系统,可以在任务里面添加喂狗动作,如果操作系统崩溃了,能够检测到软件的错误,触发CPU的复位。

窗口看门狗

窗口看门狗通常被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在T6位变成0前被刷新,看门狗电路在达到预置的时间周期时,会产生一个MCU复位。如果在递减计数器达到窗口寄存器值之前刷新控制寄存器中的递减计数器值,也会产生MCU复位。这意味着必须在限定的时间窗口内刷新计数器。

WWDG主要特性

  • 可编程的自由运行递减计数器
  • 复位条件
    • 当递减计数器值小于0x40时复位(如果看门狗已激活)。
    • 在窗口之外重载递减计数器时复位(如果看门狗已激活)。
  • 提前唤醒中断(EWI):当递减计数器等于0x40时触发( 如果已使能且看门狗已激活)
image-20200913214821839

窗口看门狗配置流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//窗口看门狗的时钟频率1281Hz,每进行减一计数,所花的时间
T=1/f=1/1281Hz≈780us

//从127减到80,要进行47次的计数,所花的时间
T=780us * (127-80) =36.66ms

//从127减到64,要进行64次的计数,所花的时间
T=780us * (127-64+1) =49.92ms


/* 窗口看门狗的配置 */
/* 使能窗口看门狗的时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);

/* 窗口看门狗的时钟 = (PCLK1 (42MHz)/4096)/8 = 1281 Hz (~780 us) */
WWDG_SetPrescaler(WWDG_Prescaler_8);

/* 设置窗口的上限值为80 */
WWDG_SetWindowValue(80);

/* 设置计数值的初值为127,则窗口看门狗的最大超时时间 = 780 us * 64 = 49.92 ms
这个时候窗口刷新时间如下
~780 * (127-80) = 36.66ms < refresh window < ~780 * 64 = 49.9ms */
WWDG_Enable(127);

//WWDG NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //窗口看门狗中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//清空提前唤醒中断标志位
WWDG_ClearFlag();

//使能提前唤醒中断
WWDG_EnableIT();

//看门狗中断服务函数
void WWDG_IRQHandler(void)
{
if(WWDG_GetFlagStatus()==SET)
{
//进行喂狗
WWDG_SetCounter(127);

//清空提前唤醒中断标志位
WWDG_ClearFlag();
}
}
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2025 wrd
  • 访问人数: | 浏览次数:

      请我喝杯咖啡吧~

      支付宝
      微信