60 秒回答模板

设备树里的 reg 不是固定几个数字,而是由父节点的 #address-cells 和 #size-cells 决定每个资源条目占多少个 32 位 cell。所谓 64 位地址空间里看到四个数字,常见是父节点 #address-cells = 2、#size-cells = 2,所以一个 reg entry 由 2 个 cell 表示地址、2 个 cell 表示长度:第一个是地址高 32 位,第二个是地址低 32 位,第三个是 size 高 32 位,第四个是 size 低 32 位。每个 cell 是 32 位 big-endian 编码。驱动一般不手工解析这四个数,而是用 platform_get_resource、of_address_to_resource 等接口获得 resource,再 ioremap。还要注意 ranges 会做父子地址转换,多个资源会连续写多组 cell。

考点 编码公式
难度 真实面经题
回答目标 说明自己理解设备树 reg 属性的通用编码规则,而不是死背某个例子。

深入解析

01

cell 是基本编码单位

设备树把整数属性编码成一个个 32 位 cell。地址和长度要用几个 cell,不由当前节点自己决定,而由父 bus 节点的 #address-cells 和 #size-cells 决定。

02

四个数字是常见组合

当父节点要求 2 个地址 cell 和 2 个 size cell 时,一个资源就是 addr_hi、addr_lo、size_hi、size_lo。它表达的是 64 位起始地址和 64 位资源大小。

03

不要忽略 ranges 转换

子总线里的地址可能不是 CPU 物理地址,需要通过 ranges 属性转换到父总线地址空间。驱动使用内核接口可以自动处理很多这类转换。

04

多个资源按组排列

如果设备有多个寄存器区域,reg 会连续放多组 address+size。解析时必须按父节点 cell 数成组读取,不能按固定四个数硬切。

易错点

  • 把四个数字固定解释成四个寄存器地址。
  • 不知道 cell 是 32 位,也不知道数量由父节点属性决定。
  • 忽略 size 部分,把后两个数字也当成地址。
  • 手工解析 reg,不考虑 ranges 和多资源条目。

面试官追问

如果 #size-cells 是 1 呢?

那一个资源的长度只占 1 个 32 位 cell;例如 address-cells 为 2、size-cells 为 1 时,一个 reg entry 就是 3 个数字。

驱动为什么最好不用硬编码下标解析 reg?

不同总线 cell 数和 ranges 规则不同,硬解析容易错;内核 resource 接口能按设备树规则处理地址和长度。

如果面试官让你现场排查,你会先看哪些证据?

我会先看 dmesg 和返回码,再查 /sys 下设备、驱动和资源状态,必要时加 trace/ftrace 或最小日志,先证明问题出在设备生成、匹配、资源获取、回调路径还是用户态交互。