Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4523944
  • 博文数量: 1148
  • 博客积分: 25453
  • 博客等级: 上将
  • 技术积分: 11949
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 21:14
文章分类

全部博文(1148)

文章存档

2012年(15)

2011年(1078)

2010年(58)

分类: LINUX

2012-01-01 15:28:16

相关章节 linux设备驱动开发详解 p196 linux中断编程


1.申请中断IRQ
  1. int requset_irq(unsigned int irq,irq_handler_t handler,unsigned long irqflags,const char *devname                                                                                  ,void *dev_id)
irq:是要申请的中断号,中断号对应的就是中断控制器上IRQ线的编号
handler:向系统登记的中断处理函数(顶半部),是一个回调函数,中断发生时,系     统调用这个函数,dev_id参数将被传递给它。
irqflags:中断处理的属性。,可以指定中断的触发方式以及处理方式
           触发方式:IRQF_TRIGGER_RISING IRQF_TRIGGER_FAILLING等
           处理方式:IRQF_DISABLED表明中断处理程序时快速处理程序,快速处                      理程序将被调用时屏蔽所有中断,慢速处理程序则不会屏                      蔽其他设备的驱动。
                     IRQF_SHARED:表示多个设备共享中断,dev_id在中断共享                      时会用到,一般设置为这个设备的设备结构体或者NULL。
 
    request_irq()返回0表示成功,返回-EINVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。

*devname: 请求中断的设备的名称,可以在/proc/interrupts中查看到具体设备的           名称,与此同时也可以查看到这个设备对应的中断号已经请求次数,甚           至中断控制器的名称

顶半部handler的类型irq_handle_t
  1. typedef irqreturn_t (*irq_handler_t)(int ,void *)
  2. typedef int irqreturn_t

2. 释放IRQ
  1. viod free_irq(unsigned int irq,void *dev_id)
参数的定义域request_irq相同


3. 使能和屏蔽中断
  1. void disable_irq(int irq);
  2. void disable_irq_nosync(int irq);
  3. void enable_irq(int irq);
disable_irq_nosync()与disable_irq()区别是,nosync()立即返回,而disable_irq等待目前的中断处理完成。由于disable_irq()会等待指定的中断被处理完,因此如果在n号中断的顶半部调用disable_irq(n),会引起系统的死锁,这种情况下,只能调用disable_irq_nosync();  

//屏蔽、使能本cpu中所有中断
void local_irq_disable();
void local_irq_enbale();                     
===================================================================

程序附件代码: first_interrupt.rar   将rar修改为tar.bz2
  1. #include <linux/init.h>//init __init
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>//MODULE_LICENSE
  4. #include <linux/moduleparam.h>//module_param
  5. #include <linux/interrupt.h>
  6. #include <linux/stat.h>//S_IRUGO
  7. #include <linux/slab.h>//kmalloc

  8. static int irq = 1;//保存中断号irq
  9. static char *devname = NULL;//保存中断名称*devname
  10. module_param(irq,int,00644);//S_IRUGO=00444
  11. module_param(devname,charp,00644);

  12. //定义一个结构体,在request_irq函数中的 void *dev_id经常设置为结构体或NULL
  13. struct dev_info{
  14.     int irq_id;
  15.     char *dev_name;
  16. };
  17. struct dev_info *mydev_info = NULL;

  18. //声明中断处理函数(顶半部)
  19. static irqreturn_t myirq_handler(int irq,void *dev);

  20. static int __init myirq_init(void)
  21. {
  22.     printk("Module is working...\n");
  23.     //分配struct dev_info 结构体内存
  24.     mydev_info = kmalloc(sizeof(struct dev_info),GFP_KERNEL);
  25.     if(!mydev_info)
  26.     {
  27.         printk("kmalloc failed..\n");
  28.         return -1;
  29.     }
  30.     memset(mydev_info,0,sizeof(struct dev_info));
  31.     mydev_info->irq_id = irq;
  32.     //分配结构体struct dev_info->char *dev_name 内存
  33.     mydev_info->dev_name = kmalloc(10,GFP_KERNEL);
  34.     if(!mydev_info->dev_name)
  35.     {
  36.         printk("kmalloc 1 failed..\n");
  37.         return -1;
  38.     }
  39.     mydev_info->dev_name = devname;

  40.     //return 0 == success
  41.     if(request_irq(irq,&myirq_handler,IRQF_SHARED,devname,mydev_info))
  42.     {
  43.         printk("%s request IRQ:%d failed\n",devname,irq);
  44.         return -1;
  45.         //return -EIO;
  46.     }
  47.     printk("%s request IRQ:%d success..\n",devname,irq);
  48.     return 0;
  49. }

  50. static void __exit myirq_exit(void)
  51. {
  52.     printk("unloading my module..\n");
  53.     free_irq(irq,mydev_info);//
  54.     printk("freeing IRQ %d\n",irq);
  55. }
  56. static irqreturn_t myirq_handler(int irq, void *dev)
  57. {
  58.     struct dev_info mydev;
  59.     static int count = 1;
  60.     mydev = *(struct dev_info *)dev;

  61.     printk("key:%d\n",count);
  62.     printk("devname:%s,devid:%d\n is working..\n",mydev.dev_name,mydev.irq_id);
  63.     printk("ISR is leaving\n");
  64.     count++;
  65.     return IRQ_HANDLED;
  66. }

  67. module_init(myirq_init);
  68. module_exit(myirq_exit);

  69. MODULE_LICENSE("GPL");

使用方法:
1.cat /proc/interrupts 查看中断号,以确定一个即将要共享的中断号。本程序因为是与键盘共享中断号,因此irq=1
2.插入内核
 sudo insmod ./interrupt.ko irq=1 devname=ywxirq
3.再次 查看 /proc/interuppts  cat /proc/interrupts | grep ywx
4. dmesg查看内核日志文件  dmesg | tail -20
5 sudo rmmod interrupt

可以看到,内核模块加载后,我们所写的中断处理程序时被自动调用的,主要是该中断线上有键盘所发出的中断请求,因此内核会执行该中断线上的所有中断处理程序,当然就包括我们上诉我们所写的那个中断处理程序。

=======================================================

参考资料:
1.edsionte's Linuxworld|新手区http://edsionte.com/techblog/archives/1521                     


显示如下:
  1. root@ywx:/home/ywx/desktop/module/edi/interrupt/first_interrupt# dmesg | tail -10
  2. [11966.016756] key:169
  3. [11966.016764] devname:ywxirq,devid:1
  4. [11966.016765] is working..
  5. [11966.016767] ISR is leaving
  6. [11967.111634] key:170
  7. [11967.111643] devname:ywxirq,devid:1
  8. [11967.111644] is working..
  9. [11967.111646] ISR is leaving
  10. [11967.119801] unloading my module..
  11. [11967.119830] freeing IRQ 1

阅读(1786) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~