linux驱动之中断(一) — 设备树中描述中断

  • Post author:
  • Post category:linux



本文仅介绍如何在Linux驱动中使用中断


linux中的中断不可嵌套(中断不可打断其他中断)

不宜在中断中做耗时长的事情

耗时的事情应当放在中断下半部中

中断下半部是可以被其他中断打断的, 而且可以用线程来执行

内核对中断下半部有三种方式 1,软中断 2, tasklet(用软中断实现,会被其他中断打断) 3,工作队列(将tasklet丢到工作队列中, 由线程来执行) 4,线程化中断(中断函数线程化)

linux需要读取设备树来得到外设的中断信息



标题如何在设备树中描述中断信息

参考文档

内核Documentation\devicetree\bindings\interrupt-controller\interrupts.txt

  • 中断控制器(

    看得懂dtsi中的中断控制器节点

    )

    中断控制器的参考文档Documentation/devicetree/bindings/arm/gic.txt

    设备树中 中断控制器节点中必须有一个属性:interrupt-controller属性 表明它是“中断控制器”。
1 intc: interrupt-controller@00a01000 { 
2     compatible = "arm,cortex-a7-gic"; 
3     #interrupt-cells = <3>; 
4     interrupt-controller; 
5     reg = <0x00a01000 0x1000>, 
6            <0x00a02000 0x100>; 
7 };
1  gpio5: gpio@020ac000 { 
2      compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio"; 
3      reg = <0x020ac000 0x4000>; 
4      interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>, 
5               <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; 
6      gpio-controller; 
7      #gpio-cells = <2>; 
8      interrupt-controller; 
9      #interrupt-cells = <2>; //注意这里把cell变成了2 引用这个中断控制器只要两个cell即可
10 };

第一个 cells:中断类型,0表示 SPI中断,1表示 PPI中断。

第二个 cells:中断号,对于 SPI中断来说中断号的范围为 0~987,对于 PPI中断来说中断

号的范围为 0~15。 并不是随便取值, 需要参考芯片手册里gpio对应的中断号

在这里插入图片描述

第三个 cells:标志,bit[3:0]表示中断触发类型,

1 = low-to-high edge triggered,上升沿触发

2 = high-to-low edge triggered,下降沿触发

4 = active high level-sensitive,高电平触发

8 = active low level-sensitive,低电平触发

可以或运算同时包含

描述一个外设并应用中断(

必须会写

)

1 fxls8471@1e { 
2     compatible = "fsl,fxls8471"; 
3     reg = <0x1e>; 
4     position = <0>; 
5     interrupt-parent = <&gpio5>; 
6     interrupts = <0 8>; 
7 };

interrupt-parent属性指定用使用哪个中断控制器

interrupts 指定中断号 触发方式



获取设备树中的中断号的函数


对于platform_device


一个节点能被转换为platform_device,如果它的设备树里指定了中断属性,那么可以从platform_device中获得“中断资源”,函数如下,可以使用下列函数获得IORESOURCE_IRQ资源,即中断号

/**
 * platform_get_resource - get a resource for a device
 * @dev: platform device
 * @type: resource type   // 取哪类资源?IORESOURCE_MEM、IORESOURCE_REG
*                      // IORESOURCE_IRQ等
 * @num: resource index  // 这类资源中的哪一个?
 */
struct resource *platform_get_resource(struct platform_device *dev,
				       unsigned int type, unsigned int num);


对于I2C设备、SPI设备


对于I2C设备节点,I2C总线驱动在处理设备树里的I2C子节点时,也会处理其中的中断信息。一个I2C设备会被转换为一个i2c_client结构体,中断号会保存在i2c_client的irq成员里

对于SPI设备节点,SPI总线驱动在处理设备树里的SPI子节点时,也会处理其中的中断信息。一个SPI设备会被转换为一个spi_device结构体,中断号会保存在spi_device的irq成员里


调用of_irq_get获得中断号


如果你的设备节点既不能转换为platform_device,它也不是I2C设备,不是SPI设备,那么在驱动程序中可以自行调用of_irq_get函数去解析设备树,得到中断号


对于GPIO作为中断


可以使用int gpio_to_irq(unsigned int gpio)

或gpiod_to_irq获得中断号。


通用的获得中断号, 适用任意节点


编写驱动的时候需要用到中断号,我们用到中断号,中断信息已经写到了设备树里面,因

此可以通过 irq_of_parse_and_map函数从 interupts属性中提取到对应的设备号,函数原型如下:

unsigned int irq_of_parse_and_map(struct device_node *dev, int index)

dev:设备节点。

index:索引号,interrupts属性可能包含多条中断信息,通过 index指定要获取的信息。



版权声明:本文为qq_40684669原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。