05_设备树自定义属性_写入读取验证

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

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

一句话看懂

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

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

1. DTS 写了什么

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

dts 复制代码
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() 后:

c 复制代码
struct device_node *np = pdev->dev.of_node;
const char *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_node pdev 是指针,用 -> 取其成员;dev 是内嵌结构体,用 . 取 of_node。得到的 np 指向本次匹配的设备树节点。
&name 字符串读取函数要写回一个字符串指针 ,所以传指针变量的地址。成功后 name 指向设备树中的字符串;不是新分配给你的一块内存。
&age 把一个 32 位整数写入 age,需要传变量地址。
info, 3 info 指向数组首元素;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 通用化。

相关推荐
dadaobusi1 小时前
学习: flit vs tlp
网络·网络协议
辛迪聊物业数字化1 小时前
物业数字化选型避坑:3步判断系统是否适配你的业态
数据库
砚底藏山河1 小时前
量化新手误区:因子计算与行情数据的工程化解耦
java·数据库·python·金融
此生决int1 小时前
Linux系统(07)——进程概念(下)
linux·运维·服务器
和裕1 小时前
定制纸箱刀卡、平卡、隔档分别是什么?结构与适用场景区别全解析
大数据·运维·网络·人工智能·算法
巧克力味的桃子1 小时前
复杂网络能控性鲁棒性研究进展
开发语言·网络·php
程序 代码狂人1 小时前
SQL COUNT 统计 NULL 与空字符串 ‘‘ 差异(Oracle & Impala)
数据库·sql·oracle
for_ever_love__1 小时前
MySQL 8.0 表设计规范:从业务建模、约束到索引评审的完整方法
数据库·mysql·表设计·建表规范
迷途之人不知返1 小时前
【基础IO】-3-系统级别的文件操作
linux