文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>ARM Linux对中断的处理--中断管理系统的初始化

ARM Linux对中断的处理--中断管理系统的初始化

时间:2010-06-11  来源:tq08g2z

中断管理系统的初始化

我们先来看一下Linux系统中,中断管理系统的初始化。中断系统的初始化主要由两个函数来完成。在系统初始化的start_kernel()函数 (在文件init/main.c中定义)中可以看到:

asmlinkage void __init start_kernel(void)

{

……

    trap_init();

……

    early_irq_init();

    init_IRQ();

……

}

start_kernel()函数调用early_irq_init()和init_IRQ()两个函数来初始化中断管理系统。

early_irq_init()函数

在start_kernel()函数中调用了early_irq_init()函数,这个函数在kernel/handle.c文件中定义。这个函数将用于管理中断的irq_desc[NR_IRQS]数组的每个元素的部分字段设置为确定的状态,它设置每一个成员的中断号,

int __init early_irq_init(void)

{

    struct irq_desc *desc;

    int count;

    int i;

 

    init_irq_default_affinity();

 

    printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);

 

    desc = irq_desc;

    count = ARRAY_SIZE(irq_desc);

 

    for (i = 0; i < count; i++) {

       desc[i].irq = i;

       alloc_desc_masks(&desc[i], 0, true);

       init_desc_masks(&desc[i]);

       desc[i].kstat_irqs = kstat_irqs_all[i];

    }

    return arch_early_irq_init();

}

init_IRQ()函数

init_IRQ(void)函数是一个特定与体系结构的函数,对于ARM体系结构,在文件arch/arm/kernel/irq.c中定义,这个函数将用于管理中断的irq_desc[NR_IRQS]结构数组各成员的状态字段设置为IRQ_NOREQUEST | IRQ_NOPROBE,也就是未请求和未探测状态。然后调用特定平台的中断初始化的init_arch_irq()函数:

void __init init_IRQ(void)

{

    int irq;

 

    for (irq = 0; irq < NR_IRQS; irq++)

       irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;

    init_arch_irq();

}

而init_arch_irq()实际上是一个函数指针,同样在文件arch/arm/kernel/irq.c中定义:

void (*init_arch_irq)(void) __initdata = NULL;

这个指针由函数setup_arch()初始化,而setup_arch()也是在start_kernel()中调用的。setup_arch()也是一个特定于体系架构的函数,在arch/arm/kernel/setup.c中定义:

void __init setup_arch(char **cmdline_p)

{

……

    init_arch_irq = mdesc->init_irq;

……

}

init_arch_irq指针被初始化为mdesc结构的init_irq成员,这是一个struct machine_desc类型的结构,mach_desc里定义了一些关键的体系架构相关的信息。以mini2440为例,其machine_desc结构的init_irq成员在文件arch/arm/mach-s3c2440/mach-mini2440.c中被赋值为s3c24xx_init_irq函数:

MACHINE_START(MINI2440, "MINI2440")

   /* Maintainer: Michel Pollet <[email protected]> */

   .phys_io = S3C2410_PA_UART,

   .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

   .boot_params = S3C2410_SDRAM_PA + 0x100,

   .map_io     = mini2440_map_io,

   .init_machine   = mini2440_init,

   .init_irq = s3c24xx_init_irq,

   .timer   = &s3c24xx_timer,

MACHINE_END

注:MACHINE_START宏的作用是对mach_desc结构体进行初始化。OK,终于找到了init_IRQ() 函数中调用的init_arch_irq()函数的真正内容,在arch/arm/plat-s3c24xx/irq.c中定义:

/* s3c24xx_init_irq

 *

 * Initialise S3C2410 IRQ system

*/

 

void __init s3c24xx_init_irq(void)

{

    unsigned long pend;

    unsigned long last;

    int irqno;

    int i;

 

#ifdef CONFIG_FIQ

    init_FIQ();

#endif

 

    irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");

 

    /* first, clear all interrupts pending... */

 

    last = 0;

    for (i = 0; i < 4; i++) {

       pend = __raw_readl(S3C24XX_EINTPEND);

 

       if (pend == 0 || pend == last)

           break;

 

       __raw_writel(pend, S3C24XX_EINTPEND);

       printk("irq: clearing pending ext status %08x\n", (int)pend);

       last = pend;

    }

 

    last = 0;

    for (i = 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, handle_level_irq);

           break;

 

       case IRQ_RESERVED6:

       case IRQ_RESERVED24:

           /* no IRQ here */

           break;

 

       default:

           //irqdbf("registering irq %d (s3c irq)\n", irqno);

           set_irq_chip(irqno, &s3c_irq_chip);

           set_irq_handler(irqno, handle_edge_irq);

           set_irq_flags(irqno, IRQF_VALID);

       }

    }

 

    /* setup the cascade irq handlers */

 

    set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);

    set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);

 

    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, handle_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, handle_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, handle_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, handle_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, handle_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, handle_edge_irq);

       set_irq_flags(irqno, IRQF_VALID);

    }

 

    irqdbf("s3c2410: registered interrupt handlers\n");

}

相关阅读 更多 +
排行榜 更多 +
无限Fps

无限Fps

飞行射击 下载
幸存者时间僵尸

幸存者时间僵尸

飞行射击 下载
金属兄弟Metal Brother

金属兄弟Metal Brother

冒险解谜 下载