![]() |
|
||||||||||||||
| | 首页 | 新闻 | 文库 | 方案 | 技术 | 独家 | 座谈 | 下载 | 图库 | 开发板 | 仿真器 | 邮购 | VIP | 芯片 | 客户评价 | 论坛 | | ||
|
||
|
|||||
| uclinux-2008r1-rc8(bf561)的中断处理(9):irq_chip | |||||
作者:快乐虾 文章来源:http://blog.csdn.net/lights_joy 点击数: 更新时间:2008-5-26 ![]() |
|||||
|
内核使用一个称为irq_chip的结构体来描述中断控制器,对中断的操作(启用/禁用某个中断源)将通过irq_chip的回调函数进行,此结构体的定义位于include/linux/irq.h:
/**
* struct irq_chip - hardware interrupt chip descriptor
*
* @name: name for /proc/interrupts
* @startup: start up the interrupt (defaults to ->enable if NULL)
* @shutdown: shut down the interrupt (defaults to ->disable if NULL)
* @enable: enable the interrupt (defaults to chip->unmask if NULL)
* @disable: disable the interrupt (defaults to chip->mask if NULL)
* @ack: start of a new interrupt
* @mask: mask an interrupt source
* @mask_ack: ack and mask an interrupt source
* @unmask: unmask an interrupt source
* @eoi: end of interrupt - chip level
* @end: end of interrupt - flow level
* @set_affinity: set the CPU affinity on SMP machines
* @retrigger: resend an IRQ to the CPU
* @set_type: set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
* @set_wake: enable/disable power-management wake-on of an IRQ
*
* @release: release function solely used by UML
* @typename: obsoleted by name, kept as migration helper
*/
struct irq_chip {
const char *name;
unsigned int (*startup)(unsigned int irq);
void (*shutdown)(unsigned int irq);
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
void (*ack)(unsigned int irq);
void (*mask)(unsigned int irq);
void (*mask_ack)(unsigned int irq);
void (*unmask)(unsigned int irq);
void (*eoi)(unsigned int irq);
void (*end)(unsigned int irq);
void (*set_affinity)(unsigned int irq, cpumask_t dest);
int (*retrigger)(unsigned int irq);
int (*set_type)(unsigned int irq, unsigned int flow_type);
int (*set_wake)(unsigned int irq, unsigned int on);
/* Currently used only by UML, might disappear one day.*/
#ifdef CONFIG_IRQ_RELEASE_METHOD
void (*release)(unsigned int irq, void *dev_id);
#endif
/*
* For compatibility, ->typename is copied into ->name.
* Will disappear.
*/
const char *typename;
};
对系统中的每一个中断,都必须有一个与它相关的irq_chip进行操作(irq_desc->chip)。
uclinux将bf561的中断分为3类,使用了3个不同的irq_chip来对它们进行控制。
第一类是内部中断,即中断0到中断6,内核使用下述结构体进行控制:
static struct irq_chip bfin_core_irqchip = {
.ack = ack_noop,
.mask = bfin_core_mask_irq,
.unmask = bfin_core_unmask_irq,
};
对于这类中断,对它进行mask和unmask操作时必须直接操作IMASK。
第二类中断是没有共用的外部中断,内核使用下述结构体进行控制:
static struct irq_chip bfin_internal_irqchip = {
.ack = ack_noop,
.mask = bfin_internal_mask_irq,
.unmask = bfin_internal_unmask_irq,
.mask_ack = bfin_internal_mask_irq,
.disable = bfin_internal_mask_irq,
.enable = bfin_internal_unmask_irq,
#ifdef CONFIG_PM
.set_wake = bfin_internal_set_wake,
#endif
};
对于这类中断,直接操作SIC_IMASK。
第三类中断是共用的外部中断,如PF0-PF7就共用一个中断源,此时内核使用下述结构体进行控制:
static struct irq_chip bfin_gpio_irqchip = {
.ack = bfin_gpio_ack_irq,
.mask = bfin_gpio_mask_irq,
.mask_ack = bfin_gpio_mask_ack_irq,
.unmask = bfin_gpio_unmask_irq,
.set_type = bfin_gpio_irq_type,
.startup = bfin_gpio_irq_startup,
.shutdown = bfin_gpio_irq_shutdown,
#ifdef CONFIG_PM
.set_wake = bfin_gpio_set_wake,
#endif
};
对这类中断,需要进行特殊处理,在后面再进行分析。
对于不同中断源的默认处理函数(irq_chip结构体中的handle),内核同样分成了3类。对于PF0-PF47的中断,将调用handle_level_irq进行处理;对于IRQ_PROG0_INTA、IRQ_PROG1_INTA、IRQ_PROG2_INTA这三个由PF口共享的中断则使用bfin_demux_gpio_irq进行处理;对于其它的中断源则使用handle_simple_irq进行处理。
|
|||||
| 文章录入:admin 责任编辑:admin | |||||
| 【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 | |||||
| 网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!) |
| | 本站介绍 | 合作联络 | 欢迎投稿 | 广告业务 | 网站地图 | 设为首页 | 加入收藏 | 友情链接 | 网站公告 | 联系我们 | | |||
|