什么是设备树?
设备树就是分层次的把外设之类的写出来, 主要是为了解决大量板级文件代码的出现
设备树功能
把板子信息做成独立的文件的格式,文件拓展名是.dts
除了dts还有dtsi 类似代码里面的头文件 ,功能一样的,底层会覆盖上层的属性定义,提高模块的复用性
DTS DTB DTC
.dts相当于.c就是源码文件
编译需要DTC工具(类比gcc) 就是把.dtc编译成.dtb文件 就是可执行文件
make dtbs 编译当前内核所有的.dts文件
make xxxxx.dtb 编译指定的 文件
DTS语法
- DTS 也是以 “/” 开始
- #inclde<> 也是包含头文件 设备树头文件 .dtsi(一款soc共有的信息提取出来 作为一个头文件)
- /dts-v1/; 代表版本1的文件 在dts中有 dtsi中没有
/dts-v1/
- 节点名字 完整的要求 node-name@unit-address 后面一般就是外设的起始地址 有时候是iic的设备地址
- 设备树中这种 intc:interrupt-controller@00a0100 :前面是标签,后面是名字 intc完整的名字就是interrupt-controller@00a0100 标签用&
设备树在系统中的体现
内核启动的时候解析设备树 然后在/proc/device-tree的目录中呈现出来
/{ //根节点下
/* */
chosen{ //一级子节点
};
memory{ //内存
};
resrved-memory{
};
backlight{
};
....
};
&cpu0{ //这种语句是追加
}
节点 aliases 重命名 在/dev中 展示的名称 由这个节点设定
chosen节点 主要目的 把uboot中 bootargs环境变量 传递给linx内核 作为cmd命令行参数
uboot如何向kenerl传递bootargs?
查看 chosen节点发现chosen节点中的 bootargs就是 我们自己修改的bootargs 但是在dbt中的chosen节点并没有包含 bootargs
其实是在uboot中进行设置的 在uboot中的fdt_chosen函数中 会查找chosen节点 并且添加或者创建 bootargs的
使用设备树之后 就不使用机器ID了 使用根节点下的 compatible
绑定信息文档
别人定义好的 然后去devicetree/bindings 去里面查看 绑定信息文档 就可以找到相关的信息定义 只是作为参考
linux 内核 OF 操作函数
1.驱动如何获取节点信息? 驱动如何获取设备树中的设备信息
在驱动中使用OF函数 获取设备树属性 (所有函数都是of_开头的)
2.驱动想要获取设备树节点 首先要先找到节点
Linux内核使用device_node结构体来描述一个节点,此结构体定义在文件include/linux/of.h
/**********查找某个设备节点****************/
of_find_node_by_name(struct device_node *from ,const char *name)
可以of_find_node_by_name(NULL,"XXX") 这个就是从根节点查找 返回值 null 查找失败 (速度慢)
of_find_node_by_type() 不怎么用
of_find_node_by_path(const char *path) 全路径 速度快
of_find_compatible_node(struct device_node *from ,const char *type,const char *compatible):根据device_type和compatible两个属性查找指定节点 type 节点对应的type字符串 就是device_type属性值 可以使用null 忽略 compatible要找的节点对应的compatible属性列表
Linux内核中使用结构体property表示属性,此结构体同样定义在文件include/linux/of.h中
/**************************提取设备属性*********************/
of_find_property(const struct device_node *np(设备节点), const char *name, int *lenp(属性值字节数)):查找指定属性
of_property_count_elems_of_size(const struct device_node *np,const char *propname(需要统计的元素数量的属性名字),int elem_size(元素长度)):获取属性中元素的数量 一般后面的元素长度是sizeof(u32)
of_property_read_u32_index(const struct device_node *np(设备节点),const char *propname,u32 index(要读取的标号),u32 *out_value(读取到的值)):从属性中获取指定标号的u32类型数据值
....