RK 看门狗 WatchDog
看门狗 又叫 watchdog timer 是为了能够防止程序跑飞而使用的一种机制
若系统正常 喂狗的程序会正常的进行 一旦系统出现死机、异常等现象 喂狗会停止 系统在一定的时间内没有收到喂狗 就自动重启 恢复到正常状态
其实就是一个定时器电路 一般有一个输入,叫喂狗,一个输出到MCU的RST端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给 WDT 清零,
如果超过规定时间不喂狗(一般在程序跑飞时),WDT 定时超过,就会给出一个复位信号到MCU,使MCU复位. 防止MCU死机.
Platform: RK3288
OS: Android 5.1.1
Kernel: 3.10.0
1.1.设备树 看门狗配置
dtsi片段并不能说明全部-设备树语法是分层的,因此属性(尤其是status)可能仍会被包含基本SoC的板级.dts覆盖. dtsi文件
kernel\arch\arm\boot\dts\rk3288-tb_zk_r322_V3.dts
&watchdog {
status = "okay";
//rockchip,irq = <0>;
rockchip,atboot = <0>;
};
kernel\arch\arm\boot\dts\rk3288.dtsi
watchdog: wdt@2004c000 {
compatible = "rockchip,watch dog";
reg = <0xff800000 0x100>;
clocks = <&pclk_pd_alive>;
clock-names = "pclk_wdt";
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
rockchip,irq = <1>;
rockchip,timeout = <60>;
rockchip,atboot = <1>;
rockchip,debug = <0>;
status = "disabled";
};
1.2.kernel\drivers\watchdog\rk29_wdt.c
a.rk29_wdt_set_heartbeat 定时器设定一个中断的时间间隔maxtime 22s
wdt_clock = devm_clk_get(&pdev->dev, "pclk_wdt");
/* timeout unit second */
int rk29_wdt_set_heartbeat(int timeout)
{
unsigned int count = 0;
unsigned int torr = 0, acc = 1, maxtime = 0;
unsigned int freq = clk_get_rate(wdt_clock);
if (timeout < 1)
return -EINVAL;
//0x80000000 is the max count of watch dog
maxtime = 0x80000000 / freq + 1;
if(timeout > maxtime)
timeout = maxtime;
count = timeout * freq;
count /= 0x10000;
while(acc < count){
acc *= 2;
torr++;
}
if(torr > 15){
torr = 15;
}
DBG("%s:torr:%d, count:%d, maxtime:%d s\n", __func__, torr, count, maxtime);
wdt_writel(torr, RK29_WDT_TORR);
return 0;
}
b.rk29_wdt_keepalive 喂狗
/* functions */
void rk29_wdt_keepalive(void)
{
if (wdt_base)
wdt_writel(0x76, RK29_WDT_CRR);
}
c. rk29_wdt_probe 中断申请函数request_irq详解
rk29_wdt_proberk29_wdt_probe 中断申请 系统回调函数
ret = request_irq(wdt_irq->start, rk29_wdt_irq_handler, 0, pdev->name, pdev);
/* interrupt handler code */
static irqreturn_t rk29_wdt_irq_handler(int irqno, void *param)
{
DBG("RK29_wdt:watchdog timer expired (irq)\n");
rk29_wdt_keepalive();
return IRQ_HANDLED;
}
d.rk29_wdt_ioctl
WDIOC_KEEPALIVE :喂狗
WDIOC_SETTIMEOUT :设置超时值
WDIOC_GETTIMEOUT :获取超时值
static long rk29_wdt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
int new_margin;
DBG("%s\n", __func__);
switch (cmd) {
case WDIOC_GETSUPPORT:
return copy_to_user(argp, &rk29_wdt_ident,
sizeof(rk29_wdt_ident)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
return put_user(0, p);
case WDIOC_KEEPALIVE:
DBG("%s:rk29_wdt_keepalive\n", __func__);
rk29_wdt_keepalive();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, p))
return -EFAULT;
if (rk29_wdt_set_heartbeat(new_margin))
return -EINVAL;
rk29_wdt_keepalive();
return put_user(tmr_margin, p);
case WDIOC_GETTIMEOUT:
return put_user(tmr_margin, p);
default:
return -ENOTTY;
}
}
1.3.JNI ioctl系统调用来控制设备
#define XH_WATCHDOG "/dev/watchdog"
#define WDIOC_APP_WDT_CTL 100
static void watchdog_close(JNIEnv *env, jobject obj, jint fd)
{
write(fd, "V", 1);
ioctl(fd, WDIOC_APP_WDT_CTL, NULL);
close(fd);
}
static void watchdog_feed(JNIEnv *env, jobject obj, jint fd)
{
write(fd, "a", 1);
}
static jint watchdog_open(JNIEnv *env, jobject obj)
{
int fd=0;
int timeout=0;
timeout=40;
fd=open(XH_WATCHDOG, O_RDWR,0);
if(fd>0)
{
ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
ioctl(fd, WDIOC_APP_WDT_CTL, &timeout);
}
return fd;
}


浙公网安备 33010602011771号