news 2026/4/15 6:31:19

从设备树到驱动:platform_get_resource如何解析reg与irq资源

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从设备树到驱动:platform_get_resource如何解析reg与irq资源

1. 设备树与驱动开发的基础概念

在嵌入式Linux开发中,设备树(Device Tree)和驱动程序的配合使用是一个非常重要的环节。设备树就像是一张硬件地图,它详细描述了系统中所有硬件设备的配置信息。而驱动程序则是操作这些硬件的软件接口。

我刚开始接触设备树时,常常困惑于硬件描述和驱动代码之间是如何衔接的。特别是在处理内存映射(reg)和中断(irq)这类关键资源时,经常遇到驱动无法正确获取资源的问题。后来通过研究platform_get_resource这个关键API,才真正理解了内核是如何把设备树中的硬件描述转换成驱动可用的资源。

设备树中关于资源描述最常见的有两种:

  • reg属性:描述设备的内存映射区域,包括起始地址和长度
  • interrupts属性:描述设备使用的中断号

举个例子,一个简单的设备树节点可能长这样:

my_device { compatible = "vendor,my-device"; reg = <0x10000000 0x1000>; interrupts = <15>; };

这个节点描述了一个设备,它的寄存器空间从0x10000000开始,大小是0x1000字节,使用的中断号是15。驱动需要获取这些信息才能正确操作硬件。

2. platform_get_resource的工作原理

2.1 资源获取的基本流程

platform_get_resource是驱动开发者最常用的API之一,它的作用是从platform_device中获取指定的资源。在实际项目中,我发现这个API背后其实隐藏着复杂的处理逻辑。

先来看一个典型的使用场景:

struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Failed to get MEM resource\n"); return -ENODEV; }

这段代码尝试获取platform_device的第一个内存资源。内核处理这个请求的完整流程可以分为几个关键步骤:

  1. 内核启动时解析设备树,创建platform_device结构体
  2. 将设备树中的reg和interrupts属性转换为标准的resource结构
  3. 驱动调用platform_get_resource获取这些资源
  4. 内核根据资源类型和索引返回对应的resource结构

2.2 内存资源的解析细节

对于内存资源(IORESOURCE_MEM),内核主要通过of_address_to_resource函数来完成转换。这个函数会处理设备树中的reg属性,将其转换为resource结构。

我曾在调试一个PCIe驱动时,发现设备无法正常工作,最终发现是因为reg属性解析出错。通过深入研究,发现of_address_to_resource内部会调用__of_address_to_resource,这个函数做了几件重要的事情:

  1. 解析reg属性的地址和大小
  2. 处理地址映射和转换(如果需要)
  3. 设置resource结构的start和end字段
  4. 处理可选的reg-names属性

一个典型的reg属性可能包含多个地址范围:

reg = <0x10000000 0x1000>, // 寄存器区域1 <0x20000000 0x2000>; // 寄存器区域2

驱动可以通过索引来获取不同的区域:

res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); // 获取第一个区域 res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); // 获取第二个区域

3. 中断资源的处理机制

3.1 中断号的获取与转换

中断资源的处理比内存资源更为复杂。在设备树中,中断通常通过interrupts属性描述,但驱动最终需要的是Linux内核的虚拟中断号。

platform_get_irq是获取中断号的主要接口,它的典型用法如下:

int irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "Failed to get IRQ resource\n"); return irq; }

这个函数背后调用了of_irq_get来完成实际的转换工作。我曾在调试一个GPIO中断时发现,设备树中定义的中断号与驱动获取到的并不相同。这是因为内核在启动过程中会对中断号进行重新映射。

3.2 中断资源的早期处理

在内核启动的早期阶段,of_platform_bus_create函数会处理设备树节点,创建对应的platform_device。对于中断资源,它会调用of_irq_to_resource_table函数:

static void of_device_alloc(struct device_node *np, ...) { // 处理内存资源 for (i = 0; i < num_reg; i++, res++) { rc = of_address_to_resource(np, i, res); WARN_ON(rc); } // 处理中断资源 if (of_irq_to_resource_table(np, res, num_irq) != num_irq) pr_debug("not all legacy IRQ resources mapped for %s\n", np->name); }

这个函数最终会调用of_irq_get来获取实际的中断号,并填充resource结构。值得注意的是,对于中断资源,resource的start和end字段都会被设置为相同的中断号。

4. PCIe设备树资源的特殊处理

4.1 ranges属性的解析

PCIe设备的资源处理有其特殊性,主要体现在设备树中的ranges属性上。一个典型的PCIe节点可能包含如下定义:

pcie0: pcie@0xd4288000 { #address-cells = <3>; #size-cells = <2>; reg = <0xd4210000 0x800>, <0xd4288000 0x1000>; reg-names = "pciephy", "pciectrl"; ranges = <0x81000000 0 0 0xE0010000 0 0x00010000 0x82000000 0 0xE0020000 0xE0020000 0 0x04000000>; interrupts = <18>; };

ranges属性描述了PCI地址空间到CPU地址空间的映射关系。在内核中,这个属性的解析是通过of_pci_range_parser_init和for_each_of_pci_range函数完成的。

4.2 PCIe资源转换实例

在PCIe主机控制器驱动中,通常会看到这样的资源处理代码:

struct of_pci_range range; struct of_pci_range_parser parser; if (of_pci_range_parser_init(&parser, np)) { dev_err(pp->dev, "missing ranges property\n"); return -EINVAL; } for_each_of_pci_range(&parser, &range) { unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; if (restype == IORESOURCE_IO) { // 处理I/O空间 of_pci_range_to_resource(&range, np, &pp->io); pp->io.start = range.pci_addr + global_io_offset; pp->io.end = pp->io.start + range.size - 1; } if (restype == IORESOURCE_MEM) { // 处理内存空间 of_pci_range_to_resource(&range, np, &pp->mem); pp->mem.start = range.cpu_addr; pp->mem.end = pp->mem.start + range.size - 1; } }

这段代码展示了如何将设备树中的ranges属性转换为驱动可用的资源信息。for_each_of_pci_range宏会遍历所有的地址范围,根据flags字段区分I/O空间和内存空间,然后分别处理。

5. 实际开发中的经验与技巧

5.1 常见问题排查

在开发过程中,经常会遇到资源获取失败的情况。根据我的经验,可以从以下几个方面排查:

  1. 检查设备树节点:确认reg和interrupts属性是否正确定义
  2. 验证compatible字符串:确保驱动和设备树的compatible匹配
  3. 检查资源索引:platform_get_resource的索引要从0开始顺序使用
  4. 查看内核启动日志:搜索设备节点名,看是否有资源分配错误

我曾经遇到过一个案例,驱动无法获取中断资源,最终发现是因为设备树中的interrupt-parent设置不正确。这种情况下,内核日志通常会给出相关提示。

5.2 调试技巧

为了更直观地了解资源分配情况,可以使用以下方法:

  1. 查看/sys文件系统

    cat /sys/devices/platform/<device>/resource

    这个文件会显示设备的所有资源信息

  2. 使用devicetree编译器

    dtc -I fs /sys/firmware/devicetree/base

    可以查看内核实际使用的设备树

  3. 添加调试打印:在驱动probe函数中添加资源信息的打印

dev_info(&pdev->dev, "Registers: %pr\n", platform_get_resource(pdev, IORESOURCE_MEM, 0)); dev_info(&pdev->dev, "IRQ: %d\n", platform_get_irq(pdev, 0));

5.3 性能优化建议

在处理大量资源时,需要注意以下几点:

  1. 避免重复获取资源:在probe函数中获取资源后保存到设备私有数据结构中
  2. 合理使用devm_接口:自动管理资源释放,减少错误可能性
  3. 注意资源冲突:特别是中断共享时,要正确设置IRQF_SHARED标志

在开发一个复杂的多功能设备驱动时,我最初每次操作都重新获取资源,导致性能下降。后来改为在probe时一次性获取并保存所有资源,性能得到了显著提升。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 6:27:11

静态语言与动态语言基础:核心区别对比

文章目录 前言一、先搞懂&#xff1a;什么是静态语言&#xff1f;什么是动态语言&#xff1f;1.1 一句话核心定义1.2 2026年主流语言分类&#xff08;真实可查&#xff09;静态类型语言&#xff08;代表&#xff09;动态类型语言&#xff08;代表&#xff09; 二、底层核心区别…

作者头像 李华
网站建设 2026/4/15 6:26:09

企业文件外发最后一公里失控怎么办

文件发给客户的那一刻&#xff0c;你以为工作结束了&#xff1f; 太天真了。 某工程公司的项目经理老周跟我讲过一件事。他们给甲方发了一份标书&#xff0c;报价 480 万&#xff0c;文件通过邮件附件发出。三天后&#xff0c;甲方一个基层办事员把文件转发给了自己的供应商&qu…

作者头像 李华
网站建设 2026/4/15 6:09:24

‌现货库存TMDS1204RNQR‌ 是TI推出的一款高性能 HDMI 2.1 混合转接驱动器,专为支持 ‌高达 12Gbps 数据速率‌ 的视频传输系统设计,广泛适用于高清显示设备与扩展应用

‌TMDS1204RNQR‌ 是德州仪器&#xff08;TI&#xff09;推出的一款高性能 HDMI 2.1 混合转接驱动器&#xff0c;专为支持 ‌高达 12Gbps 数据速率‌ 的视频传输系统设计&#xff0c;广泛适用于高清显示设备与扩展应用。核心产品特性&#xff1a;✅ ‌高速数据支持‌&#xff1…

作者头像 李华
网站建设 2026/4/15 6:07:47

深入解析:pandas为何依赖openpyxl及常见报错处理

1. 为什么pandas读取xlsx文件需要openpyxl&#xff1f; 第一次用pandas处理Excel文件时&#xff0c;我也被这个报错搞懵过。明明只是简单调用了pd.read_excel()&#xff0c;怎么就突然要求安装openpyxl了&#xff1f;这得从xlsx文件的本质说起。 xlsx是Office 2007之后采用的开…

作者头像 李华
网站建设 2026/4/15 6:06:11

从理论到实践:深入剖析LightGaussian如何实现3DGS的极致压缩与加速

1. LightGaussian为何能成为3DGS压缩的颠覆者 去年还在为3D高斯泼溅&#xff08;3DGS&#xff09;的存储问题头疼的我&#xff0c;第一次看到LightGaussian论文时差点从椅子上跳起来。这个来自德克萨斯大学奥斯汀分校和厦门大学团队的工作&#xff0c;直接把3DGS模型从782MB压缩…

作者头像 李华
网站建设 2026/4/15 6:04:12

VSCode插件开发:Hunyuan-MT Pro翻译工具扩展

VSCode插件开发&#xff1a;Hunyuan-MT Pro翻译工具扩展 1. 引言 在日常开发工作中&#xff0c;我们经常需要查阅英文文档、理解错误信息或者与海外团队沟通。频繁切换浏览器进行翻译不仅打断编码思路&#xff0c;还严重影响开发效率。想象一下&#xff0c;当你正在专注编写代…

作者头像 李华