zoukankan      html  css  js  c++  java
  • 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);
                }
            }
        }

  • 相关阅读:
    MD文件利用标题等级进行分割代码实现
    IDEA插件-Git Commit Template
    IDEA插件-Translation
    IDEA使用-Debug回到上一步
    Java语法糖详解
    MySQL 事务的隔离级别初窥
    Java异常体系概述
    ssh-copy-id三步实现SSH免密登录
    深入理解ThreadLocal
    使用Guava RateLimiter限流入门到深入
  • 原文地址:https://www.cnblogs.com/langlang/p/2456020.html
Copyright © 2011-2022 走看看