二十、设备树

前言

前面我们使用struct resource结构体来描述硬件资源,这是以前ARM Linux社区没有引入设备树时的做法,这种方法会在Linux内核源码里面引入大量的板级文件,使得内核源码臃肿。为了改变这种情况,ARM Linux社区后来引入设备树,使用设备树来描述板级硬件资源。

相关概念

设备树源文件为.dts(文本文件),经过设备树编译程序dtc编译后得到设备树文件.dtb(二进制文件)。设备树文件用于描述一个板子上的硬件资源(包括SOC以及外设等),所以一块板子对应着一个设备树文件。对于可复用的公共部分(比如SOC),可以将其设备树信息提取出来形成一个.dtsi(类似于C语言中的头文件),这样其它的.dts就可以直接使用#include对其进行包含。

设备树知识点

  1. 设备树从根节点/开始写,每个节点的格式如下:
    label:name@address {

    };

  2. 节点中可以包含属性和子节点,类似树形结构

  3. 如果想引用某个节点,可以使用&label

  4. 设备树里面相同的节点会自动合并

  5. 系统启动的时候,会去解析设备树,然后可在/proc/device-tree目录下查看设备树信息

一些常用属性

compatible: 兼容属性。设备节点下的compatible用于匹配驱动,根节点下的compatible用于查询内核是否支持此CPU。
#address-cells: 子节点中reg属性中地址的字长
#size-cells: 子节点中reg属性中大小的字长
reg: 用于描述地址空间
ranges:父地址空间映射到子地址空间(比如PCI),空间地址和大小的字长也遵循#address-cellssize-cells的规则;如果值为空,则不进行地址映射。

绑定文档

绑定文档可以提供设备树属性描述参考,位于Linux内核源码中Documentations/devicetree/bindings目录中。

设备树相关操作函数(OF操作函数)

OF函数是指Linux内核中一系列以of_开头的函数,可以用于从设备树中获取信息用于写驱动,它们的声明位于include/linux/of.h中。

  1. 查找设备节点常用函数
c 复制代码
//使用name属性查找
struct device_node *of_find_node_by_name(struct device_node *from,
	const char *name);

// 使用compatible属性查找
struct device_node *of_find_compatible_node(struct device_node *from,
	const char *type, const char *compat);
	
// 使用路径查找
struct device_node *of_find_node_by_path(const char *path);

// 查找父节点和子节点
struct device_node *of_get_parent(const struct device_node *node);
struct device_node *of_get_next_parent(struct device_node *node);
struct device_node *of_get_next_child(const struct device_node *node,
					     struct device_node *prev);
  1. 提取属性的常用函数
c 复制代码
// 获取给定节点的给定属性
struct property *of_find_property(const struct device_node *np,
					 const char *name,
					 int *lenp);
					 
// 获取给定节点的给定属性的元素数量(比如数组中元素的个数)
int of_property_count_elems_of_size(const struct device_node *np,
				const char *propname, int elem_size);

// 从u32数组中读取给定索引号元素的值
int of_property_read_u32_index(const struct device_node *np,
				       const char *propname,
				       u32 index, u32 *out_value);
// 读取整个数组
int of_property_read_u8_array(const struct device_node *np,
			const char *propname, u8 *out_values, size_t sz);
int of_property_read_u16_array(const struct device_node *np,
			const char *propname, u16 *out_values, size_t sz);
int of_property_read_u32_array(const struct device_node *np,
				      const char *propname,
				      u32 *out_values,
				      size_t sz);
// 读取字符串
int of_property_read_string(struct device_node *np,
				   const char *propname,
				   const char **out_string);

这里再补充一个跟内存映射相关的OF函数,其定义位于include/linux/of_address.h中:

c 复制代码
// 从reg属性中获取寄存器地址并映射为虚拟地址
void __iomem *of_iomap(struct device_node *np, int index);
相关推荐
UCH1HA7 小时前
MySQL主从复制与读写分离
linux·mysql·集群
Xの哲學7 小时前
Linux 文件系统一致性: 从崩溃恢复到 Journaling 机制
linux·服务器·算法·架构·边缘计算
学烹饪的小胡桃7 小时前
WGCAT工单系统 v1.2.7 更新说明
linux·运维·服务器·网络·工单系统
别多香了8 小时前
系统批量运维管理器 paramiko
linux·运维·服务器
习惯就好zz8 小时前
在 Ubuntu 18.04 旧系统上部署新版 GitHub Actions Runner 的终极方案
linux·ubuntu·github·cicd·action
杨云龙UP8 小时前
Linux LVM 在线扩容标准操作流程_20260102
linux·运维·服务器·centos·ux
warton888 小时前
ubuntu24.04 安装mysql8.0.36
linux·运维·mysql
范纹杉想快点毕业9 小时前
嵌入式通信核心架构:从状态机、环形队列到多协议融合
linux·运维·c语言·算法·设计模式
白驹过隙^^9 小时前
VitrualBox及ubuntu系统安装
linux·运维·ubuntu
可爱又迷人的反派角色“yang”9 小时前
k8s(一)
linux·运维·网络·云原生·容器·kubernetes