zoukankan      html  css  js  c++  java
  • linux内核中断之看门狗

      一:内核中断

      linux内核中的看门狗中断跟之前的裸板的中断差不多,在编写驱动之前,需要线把内核自带的watch dog模块裁剪掉,要不然会出现错误;在Device Drivers /Watchdog Timer Support /S3C2410 Watchdo

    在内核中,我们处理一个中断,必须先注册一个中断号,注册中断的函数是:

    132 request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
    133         const char *name, void *dev)
    134 {
    135     return request_threaded_irq(irq, handler, NULL, flags, name, dev);
    136 }

      irq是要申请的硬件中断号

      handler 是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev参数将被传递给它。

      flags 是中断处理的属性,若 设置了IRQF_DISABLED ,则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程 序不屏蔽;若设置了IRQF_SHARED ,则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM,表示对系统熵有贡献,对系统获取随机数有好处。

      name设置中断名称通常是设备驱动程序的名称  在cat /proc/interrupts中可以看到此名称。

      dev在中断共享时会用到,一般设置为这个设备的设备结构体或者为NULL

      request_irq()返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。

      在开发板上通过cat /proc/interrupts查看中断有没有注册成功:

      下面代码实现是按键(key1)控制dog,dog控制灯,按键第一次按下灯闪,再次按下灯灭

      

      1 #include <linux/init.h>
      2 #include <linux/module.h>
      3 #include <linux/io.h>
      4 #include <linux/irq.h>
      5 #include <linux/interrupt.h>
      6 #include <linux/clk.h>
      7 #include <linux/gpio.h>
      8 
      9 MODULE_LICENSE("GPL");
     10 MODULE_AUTHOR("bunfly");
     11 
     12 irqreturn_t do_irq(int irq, void *data);
     13 void led_on();
     14 void led_off();
     15 void wt_on();
     16 void wt_off();
     17 
     18 unsigned long gpio_virt;
     19 unsigned long *gpm4con, *gpm4dat;
     20 unsigned long wt_virt;
     21 unsigned long *wtcon, *wtdat, *wtcnt, *wtclrint;
     22 struct clk *wtclk;
     23 int et_irq = 0;
     24 
     25 int bunfly_init()
     26 {
     27     int ret = 0;
     28     et_irq = gpio_to_irq(EXYNOS4_GPX3(2));//EXINT()获取外部中断号
     29     ret = request_irq(et_irq, do_irq, IRQ_TYPE_EDGE_FALLING, "key 1", 2222);//注册按键中断
     30     if(ret < 0) {     //中断号  //处理函数
     31         printk("request_irq error
    ");
     32         return 1;
     33     }
     34 
     35     wtclk = clk_get(NULL, "watchdog");//设置时钟频率
     36     clk_enable(wtclk);
     37     ret = request_irq(IRQ_WDT, do_irq, IRQF_SHARED, "wangcai", 2222);//注册watchdog中断
     38     if(ret < 0) {
     39         printk("request_irq
    ");
     40         return 1;
     41     }
     42     gpio_virt = ioremap(0x11000000, SZ_4K);//led的物理地址到虚拟地址
     43        gpm4con = gpio_virt + 0x02e0;
     44        gpm4dat = gpio_virt + 0x02e4;
     45 
     46     wt_virt = ioremap(0x10060000, SZ_4K);//dog的物理地址到虚拟地址
     47     wtcon = wt_virt + 0x00;
     48     wtdat = wt_virt + 0x04;
     49     wtcnt = wt_virt + 0x08;
     50     wtclrint = wt_virt + 0x0c;
     51 
     52     
     53     return 0;
     54 }
     55 
     56 void bunfly_exit()
     57 {
     58     printk("this is bunfly_exit
    ");
     59 }
     60 
     61 module_init(bunfly_init);
     62 module_exit(bunfly_exit);
     63 
     64 irqreturn_t do_irq(int irq, void *data)
     65 {
     66     if(irq == et_irq) {//判断是否为按键中断
     67         static int flags = 1;
     68         printk("key 1 down
    ");
     69         if(flags) {
     70             wt_on();
     71             flags = 0;    
     72         }
     73         else {
     74             wt_off();
     75             led_off();
     76             flags = 1;                
     77         }    
     78     }
     79     if(irq == IRQ_WDT) {//判断是否为狗中断
     80         *wtclrint = 0;//清中断
     81         static int flags = 1;
     82         if(flags) {
     83             led_on();
     84             flags = 0;
     85         }
     86         else {
     87             led_off();
     88             flags = 1;
     89         }
     90     }
     91 
     92     return IRQ_HANDLED;//处理完成
     93 }
     94 
     95 void led_on()
     96 {
     97     *gpm4con &= ~0xffff;    
     98     *gpm4con |= 0x1111;
     99     *gpm4dat = 0x0;
    100 }
    101 
    102 void led_off()
    103 {
    104     *gpm4con &= ~0xffff;    
    105     *gpm4con |= 0x1111;
    106     *gpm4dat = 0xf;
    107 
    108 }
    109 
    110 void wt_on()
    111 {     
    112     *wtdat = 0x8000;
    113     *wtcnt = 0x8000;
    114     *wtcon = (1 << 2) | (0 << 3) | (1 << 5) | (168 << 8);
    115 }
    116 
    117 void wt_off()
    118 {
    119     *wtcon = 0;
    120 }
  • 相关阅读:
    多态与封装
    [Vue] karme/jasmine/webpack/vue搭建测试环境
    [Vue] vue中setInterval的问题
    hosts文件的作用
    [Nodejs] node写个helloworld
    [JavaScript] Cookie,localStorage,sessionStorage概述
    [Vue] vuex进行组件间通讯
    常用工具网站(记事,图表等)
    npm安装github包的方式
    常用的练习网站
  • 原文地址:https://www.cnblogs.com/wenqiang/p/4803022.html
Copyright © 2011-2022 走看看