linux驱动:(22)中断节点和中断函数

目录

中断过程

中断上下文

注意

中断节点

步骤

中断函数

获取设备节点的中断号函数

获取对应io口的终端号

申请中断函数

中断梳理函数

释放对应中断


中断过程

  • 中断请求
  • 中断响应
  • 保护现场
  • 中断处理
  • 恢复现场
  • 中断返回
  • 中断屏蔽

中断上下文

中断的存在可以极大的提高 CPU 的运行效率,但是中断会打断内核进程中的正常调度和运行,所以为保证系统实时性,中断服务程序必须足够简短,但实际应用中某些时候发生中断时必须处理大量的事物,这时候如果都在中断服务程序中完成,则会严重降低中断的实时性基于这个原因,linux 系统提出了一个概念:把中断服务程序分为两部分:中断上文和中断下

  • 中断上文:完成尽可能少切比较急的任务,中断上文的特点就是响应速度快。
  • 中断下文:处理中断剩余的大量比较耗时间的任务,而且可以被新的中断打断

注意

  • 中断上文越快越好,中断下文可以做比较耗时间的事情,但是不能死循环。
  • 以前的可以嵌套,现在的不可以嵌套
  • 如果中断简单,可以只写上文

中断节点

如果一个设备需要用到中断功能,开发人员就需要在设备树中配置好中断属性信息,因为设备树是用来描述硬件信息的,然后Linux内核通过设备树配置的中断属性来配置中断功能。

我们只需要关系怎么在设备树中指定中断,怎么在代码中获得中断就可以。其他的事情,比如设备树中的中断控制器,这些都是由原的 BSP 工程师帮我们写好了,我们不需要来修改他。

比如,在 xxxx.dtsi,文件,其中的 inc 节点就是xxxx 的中断控制器节点:

复制代码
intc: interrupt-controller@00a0100{
    compatible = "arm,cortex-a7-gic";
    #interrupt-cells = <3>;//表示他的子节点是用3个cells来描述中断的
    interrupt-controller;//表示中断控制器
    reg = < 0x00a0100 0x1000>,
          < 0x00a02000 0x100>;
};
  • intc就是中断控制器,因为节点属性中有一个interrupt-controller;

  • #interrupt-cells = <3>表示他的子节点是用3个cells来描述中断的

    gpio1: gpio@0x09c000{
    compatible = "fsl,imx6ul-gpio","fsl,imx35-gpio";
    reg = <0x0209c000 0x4000>;
    interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
    <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <2>;
    };

  • 上面的中断节点的子节点可以为gpio中断,我们分析一下gpio中断

  • gpio中断节点里面也有interrupt-controller;中断控制器属性

  • interrupts 属性中一个<>括号里面有三个参数,因为他的上一个节点intc中#interrupt-cells属性等于 <3>,这是对应的

    • 第一个参数;中断类型,共享中断和私有中断
    • 第二个参数;中断编号
    • 第三个参数;触发类型 在linux/irq.h中定义
  • #interrupt-cells = <2>;表示如果想用这个gpio节点就要用两个cells来描述这个节点

    key{
    #address-cells =<1>;
    #size-cells = <1>;
    compatible = "key";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_key>;
    key-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>;//KEY 0
    interrupt_parent = <&gpio1>
    interrupts = <18 IRQ_TYPE_EDGE_BOTH>;//双边沿触发
    status = "okay";
    }

  • 现在这个是接在上面gpio中断节点上面的外设,是一个按键中断,通过中断来获取按键的键值

  • compatible是与驱动名字name匹配的

  • pinctrl和gpio子系统

    • 第5,6,7行设置为了gpio功能,按键的输入
    • key-gpio要设置为引脚复用gpio
  • 描述中断

    • 第8,9行是描述中断的
    • interrupt_parent表示我们要使用gpio1的中断控制器,因为我们这个按键属于gpio1组
    • interrupts表示设置中断源,这个<>括号里面的参数就要根据中断控制器中的interrupt-cells属性来决定要多少个值
      • 第一个参数;要用的中断,也就是io口号
      • 第二个参数;触发类型 在linux/irq.h中定义

步骤

根据上面分析,如果我们要设置gpio中断,就只需要两步,

  • 第一步是将io设置成gpio
  • 第二步是用interrupt_parent和interrupts来描述中断并绑定什么中断控制器

中断函数

获取设备节点的中断号函数

编写驱动的时候需要用到中断号,每一个中断都有中断号,我们用到中断号,中断信息已经写到了设备树里面,因此可以通过 irq_of_parse_and_map 函数从 interupts 属性中提取到对应的设备号,函数原型如下:

复制代码
unsigned int irq_of_parse_and_map(sturct device_node *dev,int index)
  • 参数
    • dev:设备节点
    • index:索引号,interupts可能包含多个中断信息,通过index指定要获取的信息
  • 返回值
    • 中断号

获取对应io口的终端号

复制代码
int gpio_to_irq(unsigned int gpio)
  • 参数
    • gpio:要获取的gpio编号
  • 返回值
    • gpio对应的中断号

申请中断函数

同 GPI0 一样,在Linux内核里面,如果我们要使用某个中断也是需要申请的

复制代码
int reguest_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,const char *name,void *dev)
  • 参数
    • irq:要申请中断的中断号
    • handler:中断处理函数
    • flags:中断标志位,在linux/interrupt.h中定义
    • name:自定义中断名字,启动后可以在/proc/interrupts中看到
    • dev:传递给中断函数的第二个参数
  • 返回值
    • 0成功,负值失败,-EBUSY已经被申请了

中断梳理函数

复制代码
irqreturn_t(*irq_handler_t)(int,void *)
  • 参数
    • 第一个参数:要中断处理函数要相应的中断号
    • 第二个参数:通用指针,要与传递进来参数的类型保持一致,用于区分共享中断的不同设备,也可以指向设备数据结构
  • 返回值
    • irqreturn_t是一个枚举类型,返回一般形式是return IRQ_RETVAL(IRQ_HANDLED)

      复制代码
      enum irqreturn{
          IRQ_NONE = (0 << 0),
          IRQ_HANDLED = (1 << 0),
          IRQ_WAKE_THREAD = (1 << 1),
      };
      typedef enum irqreturn irqreturn_t

释放对应中断

中断使用完成以后就要通过 free_irq 函数释放掉相应的中断。 如果中断不是共享的,那么 free_irq 会删除中断处理函数并且禁止中断

复制代码
void free_irq(unsigned int irq,void *dev)
  • 参数
    • irq:要释放的中断号
    • dev:如果中断设置为共享(IRQF_SHARED)的话, 此参数用来区分具体的中断。 共享中断只有在释放最后中断处理函数的时候才会被禁止掉。
相关推荐
Johny_Zhao3 小时前
OpenClaw安装部署教程
linux·人工智能·ai·云计算·系统运维·openclaw
YuMiao17 小时前
gstatic连接问题导致Google Gemini / Studio页面乱码或图标缺失问题
服务器·网络协议
chlk1232 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑2 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件2 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
碳基沙盒2 天前
OpenClaw 多 Agent 配置实战指南
运维
深紫色的三北六号2 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash2 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI3 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行3 天前
Linux和window共享文件夹
linux