• linux驱动注册注销中断处理函数


    linux-3.14版本; 

    1. request_irq

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

     作用:向内核注册一个中断处理函数;

     参数1:IRQ号,用于决定构造的struct irqaction结构体对象被插入到哪个链表;

    参数2:typedef irqreturn_t (*irq_handler_t)(int, void *); 指向中断处理函数的函数指针;

    参数3:IRQF_开头的中断相关标志; 常见的几种;如下:

    1. #define IRQF_TRIGGER_NONE 0x00000000
    2. #define IRQF_TRIGGER_RISING 0x00000001 //上升沿触发
    3. #define IRQF_TRIGGER_FALLING 0x00000002 //下降沿触发
    4. #define IRQF_TRIGGER_HIGH 0x00000004 //高电平触发
    5. #define IRQF_TRIGGER_LOW 0x00000008 //低电平触发
    6. #define IRQF_SHARED 0x00000080 //共享中断必须设置的标志
    7. #define __IRQF_TIMER 0x00000200 //定时器专用中断标志

     参数4:该中断在/proc中的名字;

    参数5:区别共享中断中不同设备所对应的struct irqaction结构体对象;共享中断必须传一个非NULL实参,非共享中断可以为NULL;

    返回值:成功返回0; 失败返回负数;

    2.  free_irq

    void free_irq(unsigned int irq, void *dev_id) 

     作用: 注销一个中断处理函数;

    参数1:IRQ号;

    参数2:共享中断必须传一个有requist_irq参数5相同的非NULL实参; 

     

     3. 内核源码阅读笔记

     request_irq调用request_threaded_irq,然后又调用__setup_irq函数;

    1. //以下代码块必须以原子方式执行
    2. raw_spin_lock_irqsave(&desc->lock, flags);
    3. //遍历irq所在irqaction链表,遍历到末尾结束;
    4. old_ptr = &desc->action;
    5. old = *old_ptr;
    6. if (old) {
    7. /* add new interrupt at end of irq queue */
    8. do {
    9. /*
    10. * Or all existing action->thread_mask bits,
    11. * so we can find the next zero bit for this
    12. * new action.
    13. */
    14. thread_mask |= old->thread_mask;
    15. old_ptr = &old->next;
    16. old = *old_ptr;
    17. } while (old);
    18. shared = 1;
    19. }
    20. ...
    21. //将新的通过irq构造的struct irqaction对象加入链表尾
    22. new->irq = irq;
    23. *old_ptr = new;//加入链表尾部
    24. if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
    25. desc->istate &= ~IRQS_SPURIOUS_DISABLED;
    26. __enable_irq(desc, irq, false);//使能中断
    27. }
    28. raw_spin_unlock_irqrestore(&desc->lock, flags);
    29. //在proc下生成信息
    30. register_irq_proc(irq, desc);
    31. new->dir = NULL;
    32. register_handler_proc(irq, new);
    33. free_cpumask_var(mask);
    34. return 0;//成功返回0

    free_irq函数调用kfree(__free_irq(irq, dev_id)); 其中__free_irq函数返回找到的struct irqaction;

    1. static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
    2. {
    3. raw_spin_lock_irqsave(&desc->lock, flags);
    4. action_ptr = &desc->action;
    5. //遍历irq所在的action链表,通过dev_id找到对应的struct irqaction对象
    6. for (;;) {
    7. action = *action_ptr;
    8. if (!action) {
    9. WARN(1, "Trying to free already-free IRQ %d\n", irq);
    10. raw_spin_unlock_irqrestore(&desc->lock, flags);
    11. return NULL;
    12. }
    13. if (action->dev_id == dev_id)
    14. break;
    15. action_ptr = &action->next;
    16. }
    17. ...
    18. raw_spin_unlock_irqrestore(&desc->lock, flags);
    19. unregister_handler_proc(irq, action); //注销/proc下相关信息
    20. ...
    21. return action; //找到返回该对象,然后kfree掉;
    22. }

  • 相关阅读:
    论文投稿前需要检查下参考文献
    web前端期末大作业:基于HTML+CSS+JavaScript实现网上鲜花店网站设计(14页)
    Linux ARM平台开发系列讲解(CAN) 2.14.1 CAN基础协议分析
    JavaScript基础
    golang如何使用指针灵活操作内存?unsafe包原理解析
    TCP-4次挥手小记
    如何在ubnutu上安装docker
    MySQL8.0 安装卸载validate_password插件 和 validate_password组件
    牛客网输入输出练习c++ 个人版题解
    Redis从理论到实战:用Redis解决缓存穿透、缓存击穿问题(提供解决方案)
  • 原文地址:https://blog.csdn.net/qq_39048131/article/details/126167619