1.WDG简介
- WDG(Watchdog)看门狗
- 看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性
- 比如硬件故障,我们想读取传感器的数据,结果传感器坏了,总是死等,那程序不就卡死了嘛
- 电磁干扰,这个一般出现在恶劣的环境中,我们都知道,很强的电磁干扰可能会让这些电子元器件失灵,也就是程序跑飞现象,程序不知道跑到哪个奇怪的地方了,那假设你的设备遇到了一阵强电磁干扰,有看门狗的话,干扰过后程序复位,回到证轨,没有看门狗的话,可能受到干扰,程序就永远地卡死在某个地方了
- 对于硬件故障,如果是关键的设备故障,复位也没用的话那看门狗也无法力挽狂澜,因为看门狗就是简单地复位一下
- 对于程序设计漏洞,这里主要针对的是无法预料的漏洞,而不是说,我有看门狗了,我就在程序中,写大量的死循环或者不规划程序,到处跳来跳去,然后卡死了,就用看门狗来托底,这样不太好
- 看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号
- STM32内置两个看门狗
- 独立看门狗(IWDG):独立工作,对时间精度要求较低
- 独立看门狗(Independent WDG),独立运行,就是独立看门狗的时钟是专用的LSI,内部速时钟,即使主时钟出现问题了,看门狗也能正常工作,对时间精度要求较低,就是独立看门狗只有一个最晚时间界限,你喂狗间隔只要不超过这个最晚界限就行了,你说我很快地喂,疯狂地喂,连续不断地喂,那都没问题
- 窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用
- 喂狗的时间有个最晚的界限,也有个最早的界限,必须在这个界限的窗口内喂狗,这也是窗口看门狗,窗口,的得名原因,因为对于独立看门狗来说,可能程序就卡死在喂狗的部分了或者程序跑飞,但是喂狗代码也意外执行了,或者程序有时候很快喂狗,有时候又比较慢喂狗,那这些状态,独立看门狗就检测不到了,但是,窗口看门狗是可以检测到这些问题的,因为它对喂狗的时间窗口,可以卡的很死,快了,慢了,都不行,最后,窗口看门狗使用的是APB1的时钟,它没有专用的时钟,所以不算是独立
- 独立看门狗(IWDG):独立工作,对时间精度要求较低
2.独立看门狗 IWDG
2.1 IWDG框图
与定时器时基单元相似,具有预分频器、计数器、重装寄存器
预分频器之前输入时钟,是LSI,内部低速时钟,时钟频率为40KHZ,之后,时钟进入预分频器进行分频,这个预分频器只有8位,所以它最大只能进行256分频,上面这个预分频寄存器IWDG_PR,可以配置分频系数,这个PR和定时器的PSC是一个意思,它们都是Prescaler的缩写,之后后面,经过预分频器分频之后,时钟驱动递减计数器每来一个时钟,自减一个数,另外这个计数器是12位的,所以最大值是2^12-1=4095,然后,当自减到0之后,产生IWDG复位,正常运行时,为了避免复位呢,我们可以提前在重装载寄存器写一个值,IWDG_RLR,和定时器的ARR是一样的,RLR是Reloader,ARR是Auto Reloader,那当我们预先写好值之后,在运行过程中,我们在这个键寄存器里,写一个特定数据,控制电路,进行喂狗,这时重装值,就会复制到当前的计数器中,这样计数器就会回到重装值,重新自减运行了,然后,这里有个状态寄存器SR,这就是标志电路运行的状态了,其实这个SR里没什么东西就只有两个更新同步位
上面这些寄存器,位于1.8V供电区,下面主要的工作电路,都位于VDD供电区,所以下面写了看门狗功能处于VDD供电区,即在停机和待机模式时仍能常工作,一节我们也说过,独立看门狗,也是唤醒待机模式的四个条件之一
2.2 IWDG键寄存器
为什么能降低干扰呢?你看,独立看门狗工作的环境是什么?是程序可能跑飞,可能受到电磁干扰,程序做出任何操作都是有可能的,如果你只在奇存器中设置一个位,那这一位就有可能会在误操作中变成1,或者变成0,这个概率是比较大的,所以单独设置1位就来执行控制在这里比较危险,这时,我们就可以通过在整个寄存器写入一个特定值,来代替写入一个位的操作,比如,这里键寄存器是16位的,只有在键寄存器写入0xAAAA,这个特定的数,才会执行喂狗操作,这样就会降低误操作的概率,比如这时程序跑飞,胡乱地设置各个寄存器,键寄存器也受到了影响,它可能会变成0000 FFFF 1234等等等等,它可以随机变为任何数,但是它恰好变成0XAAAA这个数概率是非常小的
但是这里,还有PR、SR、和RLR三个寄存器,它们也要有防止误操作的功能,SR是只读的,这个不用保护,剩下的,对PR和RLR的写操作,可以设置一个写保护措施,然后只有在键寄存器写入5555,才能解除写保护,一旦写入其他值,PR和RLR再次被保护,这样PR和RLR,就跟随键寄存器一起被保护了起来,防止误操作,这就是键寄存器设计的用途
2.3 IWDG超时时间
独立看门狗的超时时间也就是定时器的溢出时间,上面这个公式,用的是时间计算,你用频率计算,也是一样的,超时频率,就等于LSl的频率/预分频/重装值,对应定时器的话,就是72M/(PSC+1)/(ARR+1)
那这里通过时间计算呢,LSl是输入时钟,40KHZ,FLSI就是40K,TLSI就是周期,等于40K分之一,1/40k=0.025ms,所以这里是0.025ms,每隔0.025ms,来一个输入时钟,之后输入时钟进行分频,相当于计数时间加倍,加多少倍呢,下面有个PR寄存器和分频系数的对应关系,这里并不是PR写几,就是几+1分频,它只有这几个固定的分频系数,比如PR写入2,那就是16分频,对应上面公式,计数时间就要乘16,最后,RL,就是RLR,计数目标,乘个RL+1,就是最终的超时时间了,比如RL给个99,那这样式子里的各部分值都确定好了,对吧,计算-下,0.025msx16x100,这就是当前这些参数下的超时时间,下面表里各个参数的最短时间和最长时间,为什么是这些值,大家就知道了吧,比如第一行PR写入0时,预分频为4,0.025msx4x1=0.1ms,最长时间,RL给最大0xFFF,即4095,这里RL+1是4096,0.025msx4x4096=409.6ms,对应表里的这个409.6ms
3.窗口看门狗 WWDG
3.1 WWDG框图
窗口看门狗,从功能上来说,和独立看门狗还是比较像的,大体上看只是比独立看门狗多了个最早喂狗时间的限制,但是等会学的时候你就会发现,这个窗口看门狗,无论是框图的设计,还是寄存器的分布和命名规则,或是程序的操作流程,和独立看门狗,都不是一个思路,可能是两个看门狗侧重点不一样吧
这是窗口看门狗的结构,左下角是时钟源部分,这个时钟源是PCLK1,右边这个是预分频器,它这个预分频器名字又变了,叫WDGTB,实际上和独立看门狗的PR,定时器的PSC,都是一个东西,上面这个是6位递减计数器CNT,这个计数器是位于控制寄存器CR里的,计数器和控制寄存器合二为一了,然后窗口看门狗没有重装寄存器,那如何重装计数器进行喂狗呢,这个,我们直接在CNT写入数据就行了,想写多少就写多少,之后上面这一块是窗回值,也就是喂狗的最早时间界限,最后,左边就是输出信号的操作逻辑了,什么情况下会产生复位,就由这几个逻辑门来确定
首先还是从左下角开始看,时钟来源是PCLK1,也就是APB1的时钟,这个时钟默认是36MHZ,所以就是36M的时钟进来,进来之后,还是先经过一个预分频器进行分频,这个和独立看门狗的预分频器,定时器的预分频器都是一个作用,就是灵活地调节后面计数器的时钟频率,同时预分频系数也是计算计数器溢出时间的重要参数,那接着,分频之后的时钟,驱动这个计数器进行计数,这个计数器和独立看门狗一样,也是一个递减计数器,每来一个时钟,自减一次,不过这个计数器比较特殊,从图上看,这里写了T6~T0总共是7个位,但是下面却写的是6位递减计数器,这是为什么呢?那这其实是因为这个计数器只有T5~T0,这6位是有效的计数值,最高位T6,这里用来当作溢出标志位,T6位等于1时,表示计数器没溢出,T6位等于0时,表示计数器溢出,不过对于硬件电路来说,T6位其实也是计数器的一部分,只不过是T6位被单独拎出来当作标志位了而已,比如这个寄存器初始值,我们给111 1111,那么来一个计数脉冲,值减一,变为111 1110,再来一个,变为111 1101,以此类推,不断自减,直到减为100 0000,好,减到这个数时,是一个关键节点,此时包括T6位在内的数,是1000000,转为十六进制是0x40,0x40要特别记一下,等会还会用到,也就是说,此时,如果把T6位也当做计数器的一部分,那计数器的值实际上才减一半,对吧,但是,如果我们把T6位剥离出去,当作溢出标志位,低6位,当作计数器,那此时的状态就是,标志位为1,计数器为00 0000,已经减到0了,再减一次,下一个值是什么呢?就是011 1111,这时最高位T6,由1变为0即代表计数器溢出,这时,最高位T6,就会通过这个线路产生复位信号,这就是这个计数器的工作流程和溢出条件
总结一下,就是,如果你把T6位看作是计数器的一部分,那就是整个计数器,值减到0x40之后溢出,而如果你把T6位当成溢出标志位,低6位当作计数器,那就是,低6位的计数值减到0之后溢出
接着看左边的复位信号输出部分,首先这个WDGA,是窗口看门狗的激活位,也就是使能,WDGA写入1,启用窗口看门狗,使能位作用于这个与门,它的作用,就类似于一个开关,左边是控制信号,右边是输入,上边是输出,控制信号给1,则输出等于输入,开关导通,控制信号给0,则输出等于0,与输入无关,开关断开,那开关右边,就是复位信号的来源了,这里有两个来源,用或门连接,也就是两个来源任意一个,都可以复位,其中下面这一路,来源于溢出标志位T6,当计数器溢出时T6等于0,然后输入进来,这里输入有个小圆圈,代表输入取反,所以0变为1,或门有效,输出1,当最后这个使能位给1,开启看门狗后,这个溢出信号就直接通向复位了,所以,下面这一路的意思就是T6位一旦等于0,就表示计数器溢出,就产生复位信号,那在程序正常运行状态下,我们必须始终保证T6位为1,这样才能避免复位,好,至此,下面这一块实现的功能,和独立看门狗基本是一样的,如果不及时喂狗,6位的计数器减到0后,就产生复位
接下来,喂狗的时间的最早界限,由上面这块来实现,首先,我们需要计算一个最早界限的计数值,写入到这里的W6~W0中,这些值,写入之后是固定不变的,之后这里,一旦我们执行写入CR操作时,这个与门开关就会打开,写入CR,其实就是写入计数器,也就是喂狗,在喂狗时,这个比较器开始工作,一旦它比较,我们当前的计数器T6:0>窗口值W6:0,比较结果就=1,这个1,通过或门,也可以去申请复位,这个1,通过或门,也可以去申请复位,这就是喂狗最早时间窗口的实现流程,就是喂狗的时候,我把当前计数值和我预设的窗口值进行比较,如果发现你的狗余粮还非常充足,你喂的这么频繁,那肯定有问题啊,我就给你复位一下,不让你喂太早了,那这,就是窗口看门狗的全部内容了,喂狗太晚,6位计数器减到0了,复位,喂狗太早,计数器的值超过窗口值了,复位
3.2 WWDG工作特性
- 递减计数器T[6:0]的值小于0x40时,WWDG产生复位
- 递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WDG产生复位(不能提前喂狗)
- 递减计数器T[6:0]等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免WWDG复位
- 0x40,这时T6还是1,还没有溢出,再减一个数,变为0x3F了,才是溢出,所以说,这里的意思就是减至0x40时,产生中断,然后再减一个数,到0xBF时,产生复位,那这样,这个中断其实就是在溢出的前一刻发生,对吧,所以,这个中断也可以称作"死前中断",马上就要溢出复位了,再提醒一下你要不要干点啥,所以在这个早期唤醒中断里我们一般可以用来执行一些紧急操作,比如保存重要数据、关闭危险设备等等,或者,还有一种写法,就是虽然超时喂狗了,但是我可以在中断里执行一些代码进行解决,或者这个任务不是很危险,超时了我就只想做一些提示,不想让它复位了,这样的话,我们就可以在这个早期唤醒中断里直接执行喂狗,阻止系统复位,然后提示一些信息就完事了
- 定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位
纵轴是TT6:01,包含T6位的CNT,递减计数器,喂狗之后,在这个数值往下递减,如果这个计数值还很大,高于这个W[6:0]窗曰值了,你就不能急着喂狗,也就是在这一块,是不允许刷新的,之后,当计数值小于窗口值了,进入到刷新窗口,可以喂狗,当然,喂狗也不能太晚,要在减到3F之前喂,3F这个值,就是T6位刚等于0的时刻,所以下面这里,T6位,在这个时刻变为0,同时复位信号也在这个时刻产生
3.3 WWDG超时时间
超时时间,就是喂狗的最晚时间,这个和刚才独立看门狗的基本一样,这里要多乘一个4096,因为框图PCLK1进来之后,其实是先执行了一个固定的4096分频,这里框图没画出来,实际上是有的,因为36M的频率,还是太快了,先来个固定分频,给降一降,下面分频系数=2^WDGTB,当WDGTB=0时,就是1分频....,这里计算公式里,是T[5:0],是不包含T6位的,这样的话,T[5:0],就是减到0后,溢出,所以超时时间的公式,直接把T[5:0]拿来计算就行了
窗曰时间,就是喂狗的最旱时间,(T[5:0]- W[5:0])是计数器减到窗口值的时间,所以我们拿T[5:01-WI5:0]就可以算出窗口时间了,同时也要注意,这个W[5:0]也是不包含W6这一位的,然后上面这里从这里可以看出,计数器等于窗口值时,就已经可以喂狗了,所以这里公式后面,就不用再+1了