博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字符设备驱动笔记——中断方式按键驱动之linux中断处理结构(五)
阅读量:6159 次
发布时间:2019-06-21

本文共 6203 字,大约阅读时间需要 20 分钟。

一、单片机下的中断处理  1)分辨是哪一个中断  2)调用处理函数  3)清中断二、linux下的中断处理1)/arch/arm/kernel/irq.casmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs){    struct pt_regs *old_regs = set_irq_regs(regs);    struct irq_desc *desc = irq_desc + irq;    /*     * Some hardware gives randomly wrong interrupts.  Rather     * than crashing, do something sensible.     */    if (irq >= NR_IRQS)        desc = &bad_irq_desc;    irq_enter();    desc_handle_irq(irq, desc);    /* AT91 specific workaround */    irq_finish(irq);    irq_exit();    set_irq_regs(old_regs);}2)/kernel/irq/handle.cstatic inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc){    desc->handle_irq(irq, desc);}3)/kernel/irq/chip.c__set_irq_handler{    ...    desc->handle_irq = handle;    ...}4)/include/linux/irq.hstatic inline voidset_irq_handler(unsigned int irq, irq_flow_handler_t handle){    __set_irq_handler(irq, handle, 0, NULL);}5)/arch/arm/plat-s3c24xx/irq.cvoid __init s3c24xx_init_irq(void)6)/arch/arm/plat-s3c24xx/irq.cset_irq_handler(irqno, handle_edge_irq);7)/kernel/irq/chip.c  调用4)  调用3)8)在s3c24xx_init_irq这个函数里面,初始化irq_desc结构体struct irq_desc {    irq_flow_handler_t    handle_irq;        //set_irq_handler(irqno, handle_edge_irq);    struct irq_chip        *chip;               //set_irq_chip(irqno, &s3c_irq_eint0t4);    struct msi_desc        *msi_desc;    void            *handler_data;    void            *chip_data;    struct irqaction    *action;    /* IRQ action list */    unsigned int        status;        /* IRQ status */....9)/kernel/irq/chip.c分析handle_edge_irq:void fastcallhandle_edge_irq(unsigned int irq, struct irq_desc *desc){    const unsigned int cpu = smp_processor_id();    spin_lock(&desc->lock);    desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);    /*     * If we're currently running this IRQ, or its disabled,     * we shouldn't process the IRQ. Mark it pending, handle     * the necessary masking and go out     */    if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||            !desc->action)) {        desc->status |= (IRQ_PENDING | IRQ_MASKED);        mask_ack_irq(desc, irq);        goto out_unlock;    }    kstat_cpu(cpu).irqs[irq]++;            //发生中断的次数    /* Start handling the irq */        //开始处理中断    desc->chip->ack(irq);        //desc->chip chip是之前初始化的s3c_irqext_chip    /* Mark the IRQ currently in progress.*/    desc->status |= IRQ_INPROGRESS;    do {        struct irqaction *action = desc->action;        irqreturn_t action_ret;        if (unlikely(!action)) {    //判断链表是否为空            desc->chip->mask(irq);            goto out_unlock;        }        /*         * When another irq arrived while we were handling         * one, we could have masked the irq.         * Renable it, if it was not disabled in meantime.         */        if (unlikely((desc->status &                   (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==                  (IRQ_PENDING | IRQ_MASKED))) {            desc->chip->unmask(irq);            desc->status &= ~IRQ_MASKED;        }        desc->status &= ~IRQ_PENDING;        spin_unlock(&desc->lock);        action_ret = handle_IRQ_event(irq, action);//真正的处理过程        if (!noirqdebug)            note_interrupt(irq, desc, action_ret);        ......}10)/arch/arm/plat-s3c24xx/irq.cs3c_irqext_chip中的.ackstatic struct irq_chip s3c_irqext_chip = {    .name        = "s3c-ext",    .mask        = s3c_irqext_mask,    .unmask        = s3c_irqext_unmask,    .ack        = s3c_irqext_ack,    .set_type    = s3c_irqext_type,    .set_wake    = s3c_irqext_wake};s3c_irqext_ack分析:static voids3c_irqext_ack(unsigned int irqno){    unsigned long req;    unsigned long bit;    unsigned long mask;    bit = 1UL << (irqno - EXTINT_OFF);    mask = __raw_readl(S3C24XX_EINTMASK);    __raw_writel(bit, S3C24XX_EINTPEND);    req = __raw_readl(S3C24XX_EINTPEND);    req &= ~mask;    /* not sure if we should be acking the parent irq... */    if (irqno <= IRQ_EINT7 ) {        if ((req & 0xf0) == 0)            s3c_irq_ack(IRQ_EINT4t7);    } else {        if ((req >> 8) == 0)            s3c_irq_ack(IRQ_EINT8t23);    }}static inline voids3c_irq_ack(unsigned int irqno){    unsigned long bitval = 1UL << (irqno - IRQ_EINT0);    __raw_writel(bitval, S3C2410_SRCPND);    __raw_writel(bitval, S3C2410_INTPND);}①desc->chip->ack(irq);//上面是清理中断============================================================②handle_edge_irq取出action链表中的成员,执行action->handlerirqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action){    irqreturn_t ret, retval = IRQ_NONE;    unsigned int status = 0;    handle_dynamic_tick(action);    if (!(action->flags & IRQF_DISABLED))        local_irq_enable_in_hardirq();    do {        ret = action->handler(irq, action->dev_id);        if (ret == IRQ_HANDLED)            status |= action->flags;        retval |= ret;        action = action->next;    } while (action);    if (status & IRQF_SAMPLE_RANDOM)        add_interrupt_randomness(irq);    local_irq_disable();    return retval;}总结:按下按键1>cup进入异常处理模式    b vector_irq + ...2>__irq_user3>asm_do_IRQ4>irq_des[irq]以中断号为下标取出一项 ->handle_irq  struct irq_desc {    irq_flow_handler_t    handle_irq;        //set_irq_handler(irqno, handle_edge_irq);                                        //handle_edge_irq取出action链表中的成员,                                        //执行action->handler(自定义实现)    struct irq_chip        *chip;               //set_irq_chip(irqno, &s3c_irq_eint0t4);    //芯片相关的一些操作    ...    }5>handle_irq = handle_edge_irq6>handle_edge_irq的操作:  (1)desc->chip->ack(irq);  (2)handle_IRQ_event(irq, action);  ===========================================================================================自定义异常处理函数action->handler,注册进内核request_irq1./kernel/irq/manage.cint request_irq(unsigned int irq, irq_handler_t handler,        unsigned long irqflags, const char *devname, void *dev_id){    //1)分配了一个结构,结构中的成员指向传递进来的参数    action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);    //2)设置irq    retval = setup_irq(irq, action);}2.setup_irq()函数分析:  1)irq_des[irq] 已irq为下标找到数组项  2)在irq_des[irq]链表里面加入传递进来的参数action  3)desc->chip->settype()设置为中断引脚                          4)desc->chip->startup / desc->chip->enable 使能中断  free_irq(irq, dev_id)  1)从链表中除去  2)禁止中断

 

转载地址:http://gkafa.baihongyu.com/

你可能感兴趣的文章
6.13心得
查看>>
Runtime类
查看>>
eclipse decompiler
查看>>
记一个搜索网盘资源的网站
查看>>
jdk1.7和jdk1.8的String的getByte方法的差异
查看>>
java父子进程通信
查看>>
Android ADB server didn't ACK * failed to start daemon * 简单有效的解决方案
查看>>
Olap学习笔记
查看>>
Codeforces Round #431 (Div. 1)
查看>>
如何进行数组去重
查看>>
将标题空格替换为 '_' , 并自动复制到剪切板上
查看>>
List Collections sort
查看>>
Mysql -- You can't specify target table 'address' for update in FROM clause
查看>>
使用局部标准差实现图像的局部对比度增强算法。
查看>>
2017-2018-1 20165313 《信息安全系统设计基础》第八周学习总结
查看>>
《代码敲不队》第四次作业:项目需求调研与分析
查看>>
菜鸡互啄队—— 团队合作
查看>>
HttpWebRequest的GetResponse或GetRequestStream偶尔超时 + 总结各种超时死掉的可能和相应的解决办法...
查看>>
SparseArray
查看>>
第二章
查看>>