☰
05_设备树自定义属性_写入读取验证
2026/10/15 17:19:30 网站建设 项目流程

设备树自定义属性:写入、读取、验证

依据:2026-10-13《设备树自定义属性》录音,以及学习系统“驱动初级 → 平台设备 → 设备树自定义属性”的 DTS、驱动笔记。录音转写的函数名以笔记中的代码为准。这是课程示例整理,未在你的开发板上重新测试。

一句话看懂

DTS 在设备节点里写属性,驱动匹配到这个节点后,在probe()中按“属性名 + 数据类型”读取。compatible决定设备与驱动能否匹配;yh_addr/yh_age/yh_infor是匹配后由驱动自己解析的示例数据。(录音约 00:07—02:14)

修改 DTS → 编译并让板子加载新 DTB → insmod 模块 → compatible 匹配 → 内核调用 probe(pdev) → pdev->dev.of_node 找到节点 → of_property_read_* 读取属性 → printk → dmesg 查看

1. DTS 写了什么

老师沿用上一节的yhai-led-gpiod节点,再加三个自定义属性:

yhai-led-gpiod { compatible = "yhai,led_gpiod"; status = "okay"; gpios = <&gpio TEGRA_GPIO(J, 7) GPIO_ACTIVE_HIGH>; yh_addr = "chenddu"; yh_age = <32>; yh_infor = <12 34 0x66>; };
属性DTS 类型和本例值驱动用什么读取
yh_addr字符串"chenddu";只是演示字符串,并非 GPIO 物理地址。of_property_read_string()
yh_age一个 32 位整数32。of_property_read_u32()
yh_infor三个 32 位整数:12、34、0x66。of_property_read_u32_array(..., 3)

属性名由示例驱动约定;内核不会自动理解yh_age的业务含义。实际项目中的设备专用属性应有清楚的 binding 文档,并按约定使用厂商前缀;这里的yh_*是课堂练习名。Linux 设备树 binding 建议

2. 驱动如何找到并读出这三个值

平台总线先用compatible = "yhai,led_gpiod"匹配驱动的of_device_id,成功才调用led_gpiod_probe(struct platform_device *pdev)。进入probe()后:

structdevice_node*np=pdev->dev.of_node;constchar*name;u32 age;u32 info[3];if(!of_property_read_string(np,"yh_addr",&name))printk("yh_addr=%s\n",name);if(!of_property_read_u32(np,"yh_age",&age))printk("yh_age=%u\n",age);if(!of_property_read_u32_array(np,"yh_infor",info,3))printk("yh_infor=%u %u 0x%x\n",info[0],info[1],info[2]);
写法为什么这样写
pdev->dev.of_nodepdev是指针,用->取其成员;dev是内嵌结构体,用.取of_node。得到的np指向本次匹配的设备树节点。
&name字符串读取函数要写回一个字符串指针,所以传指针变量的地址。成功后name指向设备树中的字符串;不是新分配给你的一块内存。
&age把一个 32 位整数写入age,需要传变量地址。
info, 3info指向数组首元素;3表示本次读三个u32元素。
!of_property_read_*()这些函数成功返回0,所以!0为真才打印;失败返回负错误码。

%u按十进制打印无符号整数,%x按十六进制打印,所以最后一个数会显示为0x66(若按示例0x%x格式打印)。读取 API 会按类型解析设备树数据,驱动不用自己拆 DTB 的原始字节。Linux OF 属性读取 API(录音约 02:14—07:36)

3. 验证时看什么

  1. **先更新 DTB:**保存 DTS,编译dtbs,把生成的 DTB 放到板子实际启动所用的位置并重新启动。仅重新编译.ko不会让旧 DTB 出现新属性。
  2. **再加载驱动:**用匹配板上运行内核的构建目录编译模块,在板上sudo insmod ./led.ko,然后sudo dmesg | tail -n 30。
  3. **看结果:**日志中应分别出现yh_addr对应chenddu、yh_age对应32、yh_infor的三项值12/34/0x66,以及包含led_gpiod_probe的信息。老师原代码逐项打印数组,空格和0x前缀取决于具体printk格式。printk()不一定直接出现在命令行。(录音约 07:00—07:36)

**不要只看最后的probe ok 2:**老师代码把三个属性都写在独立的if里。即使某个属性不存在或类型不对,那个if只会跳过打印,probe()仍可能返回0。如果实际驱动必须依赖该属性,就检查返回值并在失败时返回错误;如果属性可选,当前写法适合演示。

这节笔记里的led_gpiod_probe()只读取并打印属性,没有调用上一节的gpiod_get()点灯。DTS 中保留gpios并不意味着这一版示例驱动已经控制 LED。找不到probe日志时,先核对当前加载的 DTB、节点status与两处compatible;能进probe但缺少属性日志时,再核对属性名、类型及数组长度。

一分钟复述

设备树节点可以写驱动约定的属性。平台驱动通过compatible匹配后,内核把pdev传给probe();pdev->dev.of_node指向该节点。我按属性类型分别调用of_property_read_string/u32/u32_array,返回 0 才说明读成功。改了 DTS 要让板子加载新 DTB,查看dmesg才能确认读到了值。

上一节:GPIO 通用化。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询