arm linux 下中断流程简要分析初始化
0; i < 4; i++) {
pend = __raw_readl(S3C2410_INTPND);
if (pend == 0 || pend == last)
break;
__raw_writel(pend, S3C2410_SRCPND);
__raw_writel(pend, S3C2410_INTPND);
printk("irq: clearing pending status %08x/n", (int)pend);
last = pend;
}
last = 0;
for (i = 0; i < 4; i++) {
pend = __raw_readl(S3C2410_SUBSRCPND);
if (pend == 0 || pend == last)
break;
printk("irq: clearing subpending status %08x/n", (int)pend);
__raw_writel(pend, S3C2410_SUBSRCPND);
last = pend;
}
/* register the main interrupts */
/*注册主要的中断*/
irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers/n");
for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
/* set all the s3c2410 internal irqs */
switch (irqno) {
/* deal with the special IRQs (cascaded) */
case IRQ_EINT4t7:
case IRQ_EINT8t23:
case IRQ_UART0:
case IRQ_UART1:
case IRQ_UART2:
case IRQ_ADCPARENT:
set_irq_chip(irqno, &s3c_irq_level_chip);
set_irq_handler(irqno, do_level_IRQ);
break;
case IRQ_RESERVED6:
case IRQ_RESERVED24:
/* no IRQ here */
break;
default:/*IRQ_WDT就是这条通路*/
//irqdbf("registering irq %d (s3c irq)/n", irqno);
set_irq_chip(irqno, &s3c_irq_chip); /*为中断号设置chip*/
set_irq_handler(irqno, do_edge_IRQ); /*设置中断例程*/
set_irq_flags(irqno, IRQF_VALID);/*设置中断ready的标记*/
}
}
/* setup the cascade irq handlers */
set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
/* external interrupts */
for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
irqdbf("registering irq %d (ext int)/n", irqno);
set_irq_chip(irqno, &s3c_irq_eint0t4);
set_irq_handler(irqno, do_edge_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
irqdbf("registering irq %d (extended s3c irq)/n", irqno);
set_irq_chip(irqno, &s3c_irqext_chip);
set_irq_handler(irqno, do_edge_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
/* register the uart interrupts */
irqdbf("s3c2410: registering external interrupts/n");
for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
irqdbf("registering irq %d (s3c uart0 irq)/n", irqno);
set_irq_chip(irqno, &s3c_irq_uart0);
set_irq_handler(irqno, do_level_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
irqdbf("registering irq %d (s3c uart1 irq)/n", irqno);
set_irq_chip(irqno, &s3c_irq_uart1);
set_irq_handler(irqno, do_level_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
irqdbf("registering irq %d (s3c uart2 irq)/n", irqno);
set_irq_chip(irqno, &s3c_irq_uart2);
set_irq_handler(irqno, do_level_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
irqdbf("registering irq %d (s3c adc irq)/n", irqno);
set_irq_chip(irqno, &s3c_irq_adc);
set_irq_handler(irqno, do_edge_IRQ);
set_irq_flags(irqno, IRQF_VALID);
}
irqdbf("s3c2410: registered interrupt handlers/n");
}
上面这个函数结合s3c2410的data sheet很好理解,就是注册各个必要的中断,注意这里为每个中断号注册的中断例程只是个整体的函数,该函数只是处理一些共性的操作如清中断标记位等,他会进一步调用我们注册的中断例程来处理特定的中断。如何注册中断会在后面分析。
这个初始化函数调用了很多与中断相关的函数,我们逐个分析:
先看set_irq_chip
kernel/irq/chip.c:
/
*set_irq_chip - set the irq chip for an irq
*@irq:irq number
*@chip:pointer to irq chip description structure
*/
/*为某个中断号设置一个chip*/
int set_irq_chip(unsigned int irq, struct irq_chip *chip)
{
struct irq_desc *desc;
unsigned long flags;
if (irq >= NR_IRQS) {
printk(KERN_ERR "Trying to install chip for IRQ%d/n", irq);
WARN_ON(1);
return -EINVAL;
}
if (!chip)
chip = &no_irq_chip;
d
armlinux中断流程初始 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)