linux中断处理体系结构

本人喜欢用代码+伪代码的方式写笔记。文中的花括号可能是方便记录而已。

如:

hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module)
{
    问:怎么获得模块信息的?
    答:hardware\libhardware\Hardware.c

    ...........

}

原创分析, 转载请注明出处:http://www.cnblogs.com/langlang/

作者email: dayhappyhappy@163.com

 

重要的数据结构
struct irq_desc {
    irq_flow_handler_t    handle_irq; /*当前中断处理函数入口*/
    struct irq_chip        *chip;        /*底层的硬件访问*/
    struct irqaction①    *action;    /*用户提供的中断处理函数链表 */
    unsigned int        status;        /* IRQ status */
    const char        *name;  /*中断名称*/
} ____cacheline_internodealigned_in_smp;

struct irqaction ①{
    irq_handler_t handler;    //中断处理函数
    unsigned long flags;    /*中断标志:是否共享中断,电平触发,边缘触发。。。*/
    const char *name;        /*/pro/interrupts 下显示*/
    void *dev_id;
    struct irqaction *next;  /*链表  指向下一个*/
    int irq;                /*中断号*/
    struct proc_dir_entry *dir;
    irq_handler_t thread_fn;
    struct task_struct *thread;
    unsigned long thread_flags;
};


void __init start_kernel(void)//linux c语言入口
{
    setup_arch(char **cmdline_p);
    init_IRQ();
    {
        //初始化状态
        for (irq = 0; irq < NR_IRQS; irq++)
            irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;

        init_arch_irq();
        {
            1.ask:    不同架构的处理器中断初始化函数是不一样的,该函数中怎么去处理?
            1.answer: 在arch\arm\kernel\Setup.c中
            struct machine_desc * mdesc = setup_machine(machine_arch_type);
            init_arch_irq = mdesc->init_irq;
            mdesc->init_irq在哪里定义?
            架构相关: arch\arm\mach-s3c2440\mach-smdk2440.c
            MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
                .phys_io    = S3C2410_PA_UART,
                .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
                .boot_params    = S3C2410_SDRAM_PA + 0x100,
                .map_io        = tct_hammer_map_io,
                .init_irq    = s3c24xx_init_irq,//
                .init_machine    = tct_hammer_init,
                .timer        = &s3c24xx_timer,
            MACHINE_END
            2.ask:    s3c24xx_init_irq 做了什么处理?
            2.answer: arch\arm\plat-s3c24xx\Irq.c
            for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
                //(1)设置芯片 
                set_irq_chip(irqno, &s3c_irq_chip);
                {
                    struct irq_desc *desc = irq_to_desc(irq);
                    desc->chip = chip;//填充chip
                }
                //(2)设置处理函数
                set_irq_handler(irqno, handle_edge_irq);
                {
                    __set_irq_handler(irq, handle, 0, NULL);
                    __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
                                                const char *name)
                    {
                        desc->handle_irq = handle;  //处理函数
                        desc->name = name; //NULL
                    }
                }
                //(3)IRQF_VALID表示可以使用它们了
                set_irq_flags(irqno, IRQF_VALID); 
            }
            set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
            {
                __set_irq_handler(irq, handle, 1, NULL);
            }
            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);
        }
    }
}

用户注册中断过程分析
include\linux\Interrupt.h
static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
        const char *name, void *dev)
{
    return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
request_threaded_irq 分析
kernel\irq\Manage.c
/**
 *    request_threaded_irq - allocate an interrupt line
 *    @irq: Interrupt line to allocate
 *    @handler: Function to be called when the IRQ occurs.
 *          Primary handler for threaded interrupts
 *          If NULL and thread_fn != NULL the default
 *          primary handler is installed
 *    @thread_fn: Function called from the irq handler thread
 *            If NULL, no irq thread is created
 *    @irqflags: Interrupt type flags
 *    @devname: An ascii name for the claiming device
 *    @dev_id: A cookie passed back to the handler function
 
*/
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
             irq_handler_t thread_fn, unsigned long irqflags,
             const char *devname, void *dev_id)
{
    struct irqaction *action;     //中断处理程序
    struct irq_desc *desc;        //中断描述数组
    action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);

    action->handler = handler;//中断处理程序
    action->thread_fn = thread_fn;
    action->flags = irqflags;
    action->name = devname;
    action->dev_id = dev_id;
    desc = irq_to_desc(irq);//获取到相应的中断描述
    __setup_irq(irq, desc, action);
    __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
    {
        old_ptr = &desc->action;
        old = *old_ptr;
        do {
            old_ptr = &old->next;
            old = *old_ptr;
        } while (old); //找到用户中断处理函数的最后一个
        *old_ptr = new;
        
        irq_chip_set_defaults(desc->chip);
        //设置触发方式
        __irq_set_trigger(desc, irq,new->flags & IRQF_TRIGGER_MASK);
        new->irq = irq;
        //启动中断
        desc->chip->startup(irq);
    }
}



当IRQ中断发生时:C语言入口函数asm_do_IRQ
void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
    generic_handle_irq(irq);
    {
        generic_handle_irq_desc(irq, irq_to_desc(irq));
        {
            //irq 中断号 , irq_to_desc(irq)中断描述
            desc->handle_irq(irq, desc);
            1.ask 这是怎么处理的?
            2.answer 例子: desc初始化的时候
            set_irq_handler(irqno, handle_edge_irq); //执行的是handle_edge_irq
            void handle_edge_irq(unsigned int irq, struct irq_desc *desc)
            {
                do {
                    struct irqaction *action = desc->action;
                    handle_IRQ_event(irq, action);
                    {
                        do {
                            //★ 逐个调用用户在action链表中注册的处理函数
                            ret = action->handler(irq, action->dev_id);
                            action = action->next;
                        }while (action);
                    }
                }while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
            }
        }
    }

posted @ 2012-04-18 21:59  朗笑江湖  阅读(1351)  评论(0编辑  收藏  举报