为何我的程序从设备树获取的address-cells/size-cells值不符合预期?
libfdt中fdt_address_cells/fdt_size_cells返回父节点值而非-FDT_BAD_NCELLS的问题解析
问题场景
使用libfdt库操作设备树时遇到异常:
- 设备树里
reserved-memory节点定义了#address-cells = <0x02>和#size-cells = <0x02>,其子节点some-block未单独指定这两个属性 - 调用
fdt_address_cells()获取some-block的地址单元数返回0x2,调用fdt_size_cells()返回0x1 - 根据
libfdt.h的函数描述,预期节点未指定对应属性时应返回-FDT_BAD_NCELLS,实际结果与预期不符
对应的设备树代码:
reserved-memory { #address-cells = <0x02>; #size-cells = <0x02>; some-block { reg = <0x00 0xaa000000 0x00 0xbb00000>; no-map; compatible = "somevendor,something"; }; }
原因解析
你对fdt_address_cells()和fdt_size_cells()的行为存在误解:这两个函数并非仅检查当前节点的属性,而是遵循设备树的属性继承规则——如果当前节点未定义#address-cells或#size-cells,会自动向上递归查找父节点的对应属性,直到找到有效属性或遍历至根节点。只有当整个路径都找不到对应属性时,才会返回-FDT_BAD_NCELLS。
针对你的场景:
some-block未定义#address-cells,因此继承父节点reserved-memory的#address-cells = <0x02>,所以fdt_address_cells()返回0x2是符合函数实际逻辑的,并非错误。- 关于
fdt_size_cells()返回0x1的异常,大概率是因为:- 实际dtb文件中
reserved-memory节点的#size-cells = <0x02>未被正确编译生效 - 或
reserved-memory的父节点(如根节点)定义了#size-cells = <0x1>,且reserved-memory的#size-cells属性存在解析问题,导致函数向上继承了更上层的属性值
- 实际dtb文件中
验证与排查步骤
- 使用
fdt_getprop()直接查询some-block节点的#address-cells和#size-cells属性,确认其确实不存在(返回NULL) - 检查
reserved-memory节点的对应属性是否在dtb中正确存在:const fdt32_t *prop = fdt_getprop(fdt, reserved_memory_nodeoff, "#size-cells", NULL); if (prop) { printf("#size-cells value: 0x%x\n", fdt32_to_cpu(*prop)); } - 若
reserved-memory的#size-cells属性正确,检查libfdt版本是否存在相关bug,尝试升级至稳定版本
内容的提问来源于stack exchange,提问作者bob_vance
相关产品推荐
相关产品推荐

