设备树中的结点之of api
发布时间:2026/8/22 2:18:47 作者:尧图编辑部 阅读量:1,286

一、设备树代码片段 xxx.dtsmy_demo_device { compatible demo,mydev; reg 0x12340000 0x1000; /* 物理基地址 长度 */ interrupts 5 IRQ_TYPE_EDGE_RISING; clock-frequency 12000000; status okay; gpios gpio0 10 GPIO_ACTIVE_HIGH; child_node { test-value 0x10 0x20 0x30; str-prop hello_dt; }; };二、常用OF API 驱动示例代码头文件必须包含#include linux/of.h #include linux/of_address.h #include linux/of_irq.h #include linux/of_gpio.h #include linux/platform_device.h完整platform 驱动示例static int mydev_probe(struct platform_device *pdev) { struct device *dev pdev-dev; struct device_node *np dev-of_node; struct device_node *child_np; u32 val, buf[3]; resource_size_t phys_addr; int irq, gpio, ret; const char *str; // 1. 判断设备树节点是否存在 if (!np) { dev_err(dev, no device tree node\n); return -ENODEV; } // 2. 读取 u32 单个属性 clock-frequency ret of_property_read_u32(np, clock-frequency, val); if (!ret) dev_info(dev, clock-frequency %u\n, val); // 3. 读取 u32 数组子节点 test-value child_np of_get_child_by_name(np, child_node); if (child_np) { of_property_read_u32_array(child_np, test-value, buf, 3); dev_info(dev, array: %x %x %x\n, buf[0], buf[1], buf[2]); of_node_put(child_np); // 【重要】用完释放节点引用 } // 4. 读取字符串属性 ret of_property_read_string(np, str-prop, str); if (!ret) dev_info(dev, str-prop: %s\n, str); // 5. 获取 reg 物理地址 of_address_to_resource struct resource res; ret of_address_to_resource(np, 0, res); if (!ret) { phys_addr res.start; dev_info(dev, reg phys addr: %pa\n, phys_addr); } // 6. 获取中断号 irq of_irq_get(np, 0); if (irq 0) dev_info(dev, irq num: %d\n, irq); // 7. 获取 GPIO gpio of_get_named_gpio(np, gpios, 0); if (gpio 0) dev_info(dev, gpio num: %d\n, gpio); // 8. 判断属性是否存在 if (of_property_read_bool(np, status)) { dev_info(dev, has status property\n); } return 0; } static int mydev_remove(struct platform_device *pdev) { dev_info(pdev-dev, remove\n); return 0; } static const struct of_device_id mydev_of_match[] { { .compatible demo,mydev }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, mydev_of_match); static struct platform_driver mydev_driver { .probe mydev_probe, .remove mydev_remove, .driver { .name mydev-driver, .of_match_table mydev_of_match, }, }; module_platform_driver(mydev_driver); MODULE_LICENSE(GPL); MODULE_DESCRIPTION(DT OF API demo);三、高频OF API 分类速查1.节点查找of_find_node_by_name(NULL, child_node); // 按名字查找节点 of_find_node_by_path(/my_demo_device); // 按完整路径查找 of_get_child_by_name(np, xxx); // 获取子节点 of_node_put(np); // 释放节点必须配对防止内存泄漏2.属性读取of_property_read_u8() / u16 / u32 / u64 of_property_read_u32_array() // 读取数组 of_property_read_string() // 读字符串 of_property_read_bool() // 判断属性是否存在无value属性3.地址、中断、GPIO专用OF 封装of_address_to_resource() // reg - resource of_iomap() // 直接映射reg 得到虚拟地址 of_irq_get() // 解析 interrupts of_get_named_gpio() // 解析 gpios 属性