zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

     

  • 相关阅读:
    Ajax基本案例详解之$.getjson的实现
    Ajax基本案例详解之$.getjson的实现
    Ajax传递json数据
    Ajax传递json数据
    Ajax基本案例详解之load的实现
    多节点日志数据 数据集成
    crontab 问题分析
    不留文档的某某离开后 审计服务器操作历史
    /cloudmonitor.log 主机监控
    网关会对开发者的接口非业务调用错误做统一处理
  • 原文地址:https://www.cnblogs.com/crushgirl/p/15723798.html
Copyright © 2011-2022 走看看