Chinaunix首页 | 论坛 | 博客
  • 博客访问: 523428
  • 博文数量: 235
  • 博客积分: 1209
  • 博客等级: 少尉
  • 技术积分: 1417
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-19 19:59
文章分类

全部博文(235)

文章存档

2012年(107)

2011年(128)

分类:

2012-01-10 22:53:50

   写中断处理函数的时候,没写函数的返回值,make正常编译通过,但是运行过程中总是有错误,突然查找资料,发现一片很及时的文章拿来与大家共享。

1.中断的注册与释放:

在 , 实现中断注册接口:

 

  1. int request_irq(unsigned int irq,
  2. irqreturn_t (*handler)(int, void *,
  3. struct pt_regs *),
  4. unsigned long flags,
  5. const char *dev_name,
  6. void *dev_id);

  7. void free_irq(unsigned int irq, void *dev_id);

 

函数参数说明

unsigned int irq:所要注册的中断号
irqreturn_t (*handler)(int, void *, struct pt_regs *):中断服务程序的入口地址。
unsigned long flags:与中断管理有关的位掩码选项,有三组值:
1. SA_INTERRUPT :快速中断处理程序,当使用它的是后处理器上所有的其他中断都被禁用。
2. SA_SHIRQ :该中断是在设备之间可共享的
3. SA_SAMPLE_RANDOM :这个位表示产生的中断能够有贡献给 /dev/random
和 /dev/urandom 使用的加密池.(此处不理解)
const char *dev_name:设备描述,表示那一个设备在使用这个中断。

void *dev_id:用作共享中断线的指针. 它是一个独特的标识, 用在当释放中断线时以及可能还被驱动用来指向它自己的私有数据区(来标识哪个设备在中断) 。这个参数在真正的驱动程序中一般是指向设备数据结构的指针.在调用中断处理程序的时候它就会传递给中断处理程序的void *dev_id。(这是我的理解)如果中断没有被共享, dev_id 可以设置为 NULL, 但是使用这个项指向设备结构不管如何是个好主意. 我们将在"实现一个处理"一节中看到 dev_id 的一个实际应用。

中断号的查看可以使用下面的命令:“cat /proc/interrupts”。

/proc/stat 记录了几个关于系统活动的低级统计量, 包括(但是不限于)自系统启动以来收到的中断数. stat 的每一行以一个文本字串开始, 是该行的关键词; intr 标志是我们在找的.

第一个数是所有中断的总数, 而其他每一个代表一个单个 IRQ 线, 从中断 0 开始. 所有的计数跨系统中所有处理器而汇总的. 这个快照显示, 中断号 4 已使用 1 次, 尽管当前没有安装处理. 如果你在测试的驱动请求并释放中断在每个打开和关闭循环, 你可能发现 /proc/stat 比 /proc/interrupts 更加有用.

以下是一个统计中断时间间隔的中断服务程序。

 

  1. irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  2. {
  3. static long mytime=0;
  4. static int i=0;
  5. struct net_device *dev=(struct net_device *)dev_id;

  6. if(i==0){
  7. mytime=jiffies;
  8. }else
  9. if(i<20){
  10. mytime =jiffies- mytime;
  11. printk("Request on IRQ %d time %d\n",irq , mytime);
  12. mytime=jiffies;
  13. printk("Interrupt on %s -----%d \n",dev->name,dev->irq);
  14. }

  15. i++;
  16. return IRQ_HANDLED;
  17. }

 

这个函数实现的只是对两次发生中断的时间间隔的统计,时间单位是毫秒

函数参数说明:int irq :在这里很明显传递过来的是中断号

void *dev_id :这个传递来的是设备的id号,可以根据这个设备id号得到相应设备的数据结构,进而的到相应设备的信息和相关数据。下面以提取网路数据为例来说明一下。

struct net_device *dev=( struct net_device *)dev_id; (这里的dev_id的值是注册中断的时候宏传递过来的,是注册中断函数的最后一个参数。特别说明)

在这之后就可以用dev->name; dev->irq;等得到网络设备的信息了,当然提取ip数据报还得进行一些其它的工作。

struct pt_regs *regs :它指向一个数据结构,此结构保存的是中断之前处理器的寄存器和状态。主要用在程序调试。

 

关于中断处理函数的返回值:中断程序的返回值是一个特殊类型—irqreturn_t。但是中断程序的返回值却只有两个—IRQ_NONE和IRQ_HANDLED。

 

  1. /* irqreturn.h */

  2. #ifndef _LINUX_IRQRETURN_H

  3. #define _LINUX_IRQRETURN_H

  4. typedef int irqreturn_t;

  5. /*

  6. * For 2.4.x compatibility, 2.4.x can use

  7. *

  8. * typedef void irqreturn_t;

  9. * #define IRQ_NONE

  10. * #define IRQ_HANDLED

  11. * #define IRQ_RETVAL(x)

  12. *……此处我删去了部分关紧要的内容

  13. * To mix old-style and new-style irq handler returns.

  14. *

  15. * IRQ_NONE means we didn't handle it.

 

* 中断程序接收到中断信号后发现这并不是注册时指定的中断原发出的中断信号.

*此时返回次值

 

  1. * IRQ_HANDLED means that we did have a valid interrupt and handled it.

 

* 接收到了准确的中断信号,并且作了相应正确的处理

 

  1. * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled)

  2. */

  3. #define IRQ_NONE (0)

  4. #define IRQ_HANDLED (1)

  5. #define IRQ_RETVAL(x) ((x) != 0) //这个宏只是返回0或非0



  6. #endif
阅读(1137) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~