watchdog概述
看门狗一般应用于系统异常或者核心应用异常,一定时间内发出复位信号,以复位整个系统。
我将分三个层次来说明:
1 寄存器层
2 驱动层
3 应用层
1 寄存器层
hi3516dv300有2个watchdog模块;
WatchDog 0 基址:0x1205_0000。
WatchDog 1 基址:0x1205_1000
watchdog寄存器概览
偏移地址 | 名称 | 描述 |
---|---|---|
0x0000 | WDG_LOAD | 计数初值寄存器 |
0x0004 | WDG_VALUE | 计数器当前值寄存器 |
0x0008 | WDG_CONTROL | 控制寄存器 |
0x000C | WDG_INTCLR | 中断清除寄存器 |
0x0010 | WDG_RIS | 原始中断寄存器 |
0x0014 | WDG_MIS | 屏蔽后中断寄存器 |
0x0C00 | WDG_LOCK | LOCK 寄存器 |
计数时钟频率配置
watchdog计数时钟为3MHz时钟。
time=val*1/fclk
time:watchdog计数时间
val:watchdog计数初值
fclk:watchdog计数时钟频率
watchdog的计数时间time范围为0s~1400s
系统初始化配置
系统上电复位后wat计数器处于停止计数状态。
- 写寄存器WDG_LOAD,设定计数初值
- 写寄存器 WDG_CONTROL,打开中断屏蔽并启动 WatchDog 计数。
- 写寄存器 WDG_LOCK,给 WatchDog 上锁,防止软件错误修改 WatchDog 的配置。
中断处理过程处理
收到watchdog发出的中断后,要清除其中断状态,并使其载入计数初值重新开始计数,该过程可以表述为喂狗。如果计数器的计数值第二次计数递减到0时,CPU还没有清除watchdog中断,则watchdog将发出复位信号WDG_RSTN,系统将重启。
- 写寄存器WDG_LOCK,固定值0x1ACC_E551,为watchdog开锁。
- 写寄存器WDG_INTCLR,清除watchdog的中断状态,同时也是watchdog自动载入计数初值重新开始计数。
- 写寄存器WDG_LOCK,除0x1ACC_E551以外的任何值,给watchdog上锁。
开启关闭watchdog
写寄存器WDG_CONTROL[inten]控制位:
0: 关闭watchdog
1:开启watchdog
2 驱动层
这里我不贴出所有代码,sdk中有该驱动源码,位置为Hi3516CV500_SDK_V2.0.1.1/smp/a7_linux/drv/interdrv/wdt/hi_wdt.c
/* define watchdog IO */
#define HIWDT_BASE 0x12051000
#define HIWDT_REG(x) (HIWDT_BASE + (x))
#define HIWDT_LOAD 0x000
#define HIWDT_VALUE 0x004
#define HIWDT_CTRL 0x008
#define HIWDT_INTCLR 0x00C
#define HIWDT_RIS 0x010
#define HIWDT_MIS 0x014
#define HIWDT_LOCK 0xC00
#define HIWDT_UNLOCK_VAL 0x1ACCE551
#ifndef MHZ
#define MHZ (1000*1000)
#endif
static unsigned long rate = 3*MHZ;
// 设置喂狗超时时间
static inline void hidog_set_timeout(unsigned int nr)
{
unsigned long cnt = (~0x0UL)/rate; /* max cnt */
unsigned long flags;
osal_spin_lock_irqsave(&hidog_lock, &flags);
if( nr==0 || nr>cnt)
cnt=~0x0;
else
cnt = nr*rate;
/* unlock watchdog registers */
hiwdt_writel(HIWDT_UNLOCK_VAL, HIWDT_L