在驱动中定义中断

来源:互联网 发布:mp3编辑软件 编辑:程序博客网 时间:2024/04/30 09:11
1. 中断
        
        涉及头文件:

            #include <linux/interrupts>    
    
        中断的注册

        int
        request_irq(
            unsigned int irq,
            irq_handler_t handler,
            unsigned long flags,
            const char *name,
            void *dev
        );

        @irq: 中断号

            外部中断号:

            a. irqnum gpio_to_irq(gpio);

                   EXYNOS4X12_GPM4();
            //arm/mach-exynos/include/mach/gpio.h

            b. IRQ_EINT(eintnum);

            //arm/plat-samsung/include/plat/irqs.h

            内部中断:

            arch/arm/mach-exynos/include/mach/irqs.h

        @handler: 中断处理函数
        
        typedef irqreturn_t (*irq_handler_t)(int, void *);

        中断处理函数的返回值:IRQ_HANDLED, IRQ_NONE;
        
        型参:第一个int对应的是发生中断的中断号。
              第二个void*型的实参是注册中断时的第5个参数dev。

        @flags: 注册中断的标记

        #define IRQF_TRIGGER_NONE    0x00000000
        #define IRQF_TRIGGER_RISING    0x00000001            
        #define IRQF_TRIGGER_FALLING    0x00000002   //
        #define IRQF_TRIGGER_HIGH    0x00000004    //高电平
        #define IRQF_TRIGGER_LOW    0x00000008   //低电平
        #define IRQF_TRIGGER_MASK    (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \
        
        #define IRQF_SHARED        0x00000080


        @name: 中断的名字    

        @dev: 传给中断处理函数的第二参数的实参

        中断的共享


        2. 中断的下半部    

    -------------------------------------------------------------------
    实现中断的下半部机制1: tasklet 机制

    涉及到的核心结构体:

    struct tasklet_struct
    {
        struct tasklet_struct *next;
        unsigned long state;
        atomic_t count;
        void (*func)(unsigned long); //下半部的任务函数
        unsigned long data;         //下半部的任务函数需要的参数
    };

    使用步骤:

    首先,实例化一个struct tasklet_struct的对象,代表下半部将被内核调度器调度的任务。

    a. struct tasklet_struct task;
    
      tasklet_init(&task, service_bh, dev);

    b. DECLARE_TASKLET(task, service_bh, dev); //task是给tasklet起的名字,service_bh是执行tasklet时调用的函数,dev是一个用来传递给tasklet函数的ul类型的值

    其次,在中断处理函数(上半部)中将下半部的任务交给调度器调度

    tasklet_schedule(&task);


    最后,如果写的是驱动模块,需要在模块的出口移除下半部的任务

    
    tasklet_kill(&task);


    -------------------------------------------------------------------

    中断下半部的实现机制2: 工作队列机制

    涉及到的核心结构体:

    struct work_struct {
        atomic_long_t data;
        struct list_head entry;
        work_func_t func;      //下半部的任务函数
    #ifdef CONFIG_LOCKDEP
        struct lockdep_map lockdep_map;
    #endif
    };

    //下半部任务函数的类型:
    typedef void (*work_func_t)(struct work_struct *work);


    实现步骤:

    首先,实例化对象

    方法1,
        struct work_struct work;
        INIT_WORK(&work, service_bh);

    
    方法2,
        DECLARE_WORK(work, service_bh);                    \


    其次,在中断的上半部将下半部的任务交给调度器调度

        schedule_work(&work);

    最后,驱动模块的出口需要等待下半部的任务完成

        flush_work(&work);


0 0
原创粉丝点击