linux 中断设备树 dts写法参考例程

/ {
    interrupt-parent = <&intc>;

    intc: interrupt-controller {
        compatible = "my_intc";
        #interrupt-cells = <1>;
        interrupt-controller;
        reg = <0x80000000 0x1000>;
    };

    my_device: my-device {
        compatible = "my_device";
        reg = <0x81000000 0x1000>;
        interrupts = <0 2>;
    };
};

在这个示例中,根节点("/")有一个属性“interrupt-parent”,它指向了一个名为“intc”的中断控制器节点。该中断控制器节点被声明为一个中断控制器("interrupt-controller")并且具有一个"compatible"属性,用于匹配驱动程序。还定义了一个寄存器范围("reg"属性),表示该中断控制器的地址范围。

另外,还有一个名为“my_device”的设备节点,也有一个"compatible"属性,并指定了该设备的寄存器范围。此外,还有一个"interrupts"属性,它描述了与该设备相关的两个中断,第一个数值0表示中断的编号,第二个数值2表示中断的触发类型(即边沿或电平触发)。

通过这种方式,操作系统可以使用中断设备树中的信息来分配和管理系统中的中断资源,并确保各个设备之间的中断不会冲突。

在设备树中配置中断通常需要以下步骤:

  1. 在设备节点中添加 interrupt-parent 属性,指定中断控制器(IRQ controller)所在的设备节点。

  2. 在设备节点中添加 interrupts 属性,描述中断信息,包括中断编号、中断触发类型等。

  3. 在驱动程序中解析设备树中的 interrupt-parentinterrupts 属性,并注册中断处理函数。

下面是一个简单的例程,用于演示如何在设备树中配置和使用中断。假设我们要为一个 GPIO 设备添加中断支持。设备树中对应的节点可以写成这样:

gpio {
    compatible = "my_gpio_device";
    gpio-number = <10>;
    interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
    interrupt-parent = <&gpio_controller>;
};

其中,compatible 属性指定设备的兼容性字符串,gpio-number 属性指定 GPIO 的编号,interrupts 属性描述中断信息,interrupt-parent 属性指定中断控制器所在的设备节点。

接下来,在设备驱动程序中解析中断信息,并注册中断处理函数:

#include <linux/interrupt.h>
#include <linux/of.h>

static int my_gpio_probe(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct resource *res;
    int irq;

    // 获取 GPIO 编号和中断信息
    u32 gpio_num;
    const u32 *irqs;
    int num_irqs;
    if (of_property_read_u32(dev->of_node, "gpio-number", &gpio_num))
        return -EINVAL;
    num_irqs = of_irq_count(dev->of_node);
    if (num_irqs < 1)
        return -EINVAL;
    irqs = devm_kzalloc(dev, sizeof(u32) * num_irqs, GFP_KERNEL);
    if (!irqs)
        return -ENOMEM;
    if (of_irq_get(dev->of_node, 0, &irq))
        return -EINVAL;

    // 注册中断处理函数
    res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    if (!res)
        return -EINVAL;
    irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
    if (devm_request_irq(dev, irq, my_gpio_irq_handler,
                         IRQF_TRIGGER_HIGH, dev_name(dev), pdev))
        return -EINVAL;

    // 其他初始化操作
    // ...

    return 0;
}

这个例程中,我们首先使用 of_property_read_u32()of_irq_count() 函数从设备树节点中获取 GPIO 编号和中断信息。然后,我们使用 irq_set_irq_type() 函数设置中断触发类型为高电平,并使用 devm_request_irq() 函数注册中断处理函数。

最后,在 probe() 函数中完成其他初始化操作,就可以使设备支持中断了。需要注意的是,这只是一个简单的例程,实际情况下可能会更加复杂。

中断类型

// 常用的五个触发类型
enum {
	IRQ_TYPE_NONE		= 0x00000000,
	IRQ_TYPE_EDGE_RISING	= 0x00000001,
	IRQ_TYPE_EDGE_FALLING	= 0x00000002,
	IRQ_TYPE_EDGE_BOTH	= (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING),
	IRQ_TYPE_LEVEL_HIGH	= 0x00000004,
	IRQ_TYPE_LEVEL_LOW	= 0x00000008,
	...
	}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全职编程-叶秋然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值