linux中断

来源:互联网 发布:vb.net 反向tab 编辑:程序博客网 时间:2024/05/17 01:12

 

项目开发过程中需要对八个外设中断进行中断处理, 试用request_irq函数挂载过程中出现了中断号与硬件中断对应出错的问题,通过分析内核,得到些心得并找了点资料,记录如下,以供共享。

在设备驱动过程中,用户可以试用request_irq函数将外设的中断服务例程挂载到外部中断处理程序中。外部中断处理程序,可以直接处理硬件中断,但是request_irq函数试用软件中断号进行挂载,因此linux必然采用了某种方式进行软硬件中断的映射。

linux使用结构体:
struct irq_map_entry irq_map[NR_IRQS];
完成软件与硬件的中断号映射,一般系统自动查找可用的软件号以对应请求的硬件中断号。

在使用open firmware的系统中,驱动程序在执行ruquest_irq之前要先进行软硬件中断号的映射,具体通过函数:
irq_of_parse_and_map(struct device_node * dev, int index);
实现,具体函数调用过程如下:
irq_create_of_mapping(struct device_node * controller, u32 * inspec, unsigned int intsize);
      irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq);

程序除了进行软硬件中断号的映射外还需要初始后相应结构。

下面看看与中断相关的另外几个主要数据结构:

1、结构体:struct irq_desc(include/linux/irq.h)

de>27 struct irq_desc;
 28 typedef void fastcall (*irq_flow_handler_t)(unsigned int irq, 
 29 struct irq_desc *desc);
 153struct irq_desc {
 154 irq_flow_handler_t handle_irq; /*指向一个函数,下面会用到*/
 155 struct irq_chip *chip; /* 下面会介绍这个结构体*/
 156 struct msi_desc *msi_desc;
 157 void *handler_data;
 158 void *chip_data;
 159 struct irqaction *action; /* IRQ action lis下面会介绍 */
 160 unsigned int status; /* IRQ status */
 161
 162 unsigned int depth; /* nested irq disables */
 163 unsigned int wake_depth; /* nested wake enables */
 164 unsigned int irq_count; /* For detecting broken IRQs */
 165 unsigned int irqs_unhandled;
 166 unsigned long last_unhandled;/*Aging timer for unhandled count*/
 167 spinlock_t lock;
 168#ifdef CONFIG_SMP
 169 cpumask_t affinity;
 170 unsigned int cpu;
 171#endif
 172#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
 173 cpumask_t pending_mask;
 174#endif
 175#ifdef CONFIG_PROC_FS
 176 struct proc_dir_entry *dir;
 177#endif
 178 const char *name;
 179} ____cacheline_internodealigned_in_smp;
180 extern struct irq_desc irq_desc[NR_IRQS];
typedef struct irq_desc irq_desc_t;
de>

这 个结构体用来描述中断源,数组irq_desc[NR_IRQS](NR_IRQS=225)中每一项都对应一个相应的中断源,他的每一项对应着中断向量 表中的一项,即该数组的第一项对应着中断向量表中的第32项(中断向量号为0x20),往下依次对应。中断向量表一共有256项。
部分成员解释:
status:或者是0,或者是从一个特定的集合中抽取的一个标志位(不太清楚)。这些标志位代表了IRQ的状态--是否被禁止,有关IRQ的设备当前是否正被自动检测等。
chip:是一个指向hw_interrupt_type(或者irq_chip)的指针。下面对此有介绍。
action:是一个指向由irqaction结构体组成的一个单向链表的头的指针。若一个IRQ只被一个中断源使用,那么该链表的长度就是1,当有多个设备共享一个中断源时,该链表就会由多个irqaction结构体组成,下面对此有介绍。
depth:irq_desc_t的当前用户的个数,主要用来保证事件正在处理的过程中IRQ不会被禁止。

2、结构体:struct irqaction(include/linux/interrupt.h)

de>struct irqaction {
  61 irq_handler_t handler;
  62 unsigned long flags;
  63 cpumask_t mask;
  64 const char *name;
  65 void *dev_id;
  66 struct irqaction *next;//指向下一个本结构

  67 int irq;
  68 struct proc_dir_entry *dir;
  69};
de>

这个结构体包含了处理一种中断所需要的各种信息,它代表了内核接受到特定IRQ之后应该采取的操作。
主要成员:
handler—该指针所指向的函数就是在中断服务程序,当中断发生时内核便会调用这个指针指向的函数。
flags: 该标志位可以是0,也可以是:SA_INTERRUPT(表示此中断处理程序是一个快速中断处理程序,在2.6中默认情况下没有这个标 志)SA_SAMPLE_RANDOM(表示这个中断对内核池有贡献,我理解为就是在中断时产生一些随机数,这些随机数被用来作为加密密匙,因为中断是随 机发生的,如果某种中断是有频率的被产生,那么它就不要设置此标志位,还有就是那种设备容易被攻击也不应该设置此标志位)SA_SHIRQ(此标志位表示 允许多个中断服务程序共享一个中断号,如不设则一个程序对应一个中断线)。
mask:在x86上不会用到。
name:产生中断的硬件的名字.
dev_id:该标志位主要在共享中断号时使用,即你设置flags=SA_SHIRQ时,有多个中断服务程序共享一个中断号时,内核就需要知道在用完中断程序后该删除那个中断服务程序。不共享时此成员为null。
next:如果flags=SA_SHIRQ,那么这就是指向对列中下一个struct irqaction结构体的指针,否则为空。
irq:不用说这就是中断号了。

3 结构体:struct hw_interrupt_type(include/linux/irq.h)

de>#define hw_interrupt_type irq_chip
typedef struct irq_chip hw_irq_controller;
  99struct irq_chip {
 100 const char *name;
 101 unsigned int (*startup)(unsigned int irq);
 102 void (*shutdown)(unsigned int irq);
 103 void (*enable)(unsigned int irq);
 104 void (*disable)(unsigned int irq);
 105
 106 void (*ack)(unsigned int irq);
 107 void (*mask)(unsigned int irq);
 108 void (*mask_ack)(unsigned int irq);
 109 void (*unmask)(unsigned int irq);
 110 void (*eoi)(unsigned int irq);
 111
 112 void (*end)(unsigned int irq);
 113 void (*set_affinity)(unsigned int irq, cpumask_t dest);
 114 int (*retrigger)(unsigned int irq);
 115 int (*set_type)(unsigned int irq, unsigned int flow_type);
 116 int (*set_wake)(unsigned int irq, unsigned int on);
 117
 118 /* Currently used only by UML, might disappear one day.*/
 119#ifdef CONFIG_IRQ_RELEASE_METHOD
 120 void (*release)(unsigned int irq, void *dev_id);
 121#endif
 122 /*
 123 * For compatibility, ->typename is copied into ->name.
 124 * Will disappear.
 125 */

 126 const char *typename;
 127};
de>

此结构体用来描述中断控制器,它是一个抽象的中断控制器,其成员是一系列指向函数的指针。
typename:给相应的控制器起一个便于理解的名字。
startup:允许从给定的控制器的IRQ所产生的事件。(基本上与enable相同)
shutdown:禁止从给定的控制器的IRQ所产生的事件。(基本上与disable相同)
以上三个结构体的关系可以用下面一张图来说明:
 
图 3:IRQ 结构之间的关系
IRQ结构之间的关系

数 组irq_desc_t用来描述中断的相关信息,它有225项,每一项代表一个中断源,其中字段irq(注意这个字段就是上图中的handler字段), 此结构体用来描述中断控制器,action字段用来描述处理一种中断所需要的各种信息,它代表了内核接受到特定IRQ之后应该采取的操作。