当前位置: 首页 > news >正文

linux设备树dts文件详解

1、什么是设备树?

(1)设备树(dt:device tree)是linux内核采用的参数表示和传递技术,在系统引导启动阶段进行设备初始化的时候,将设备树中描述的硬件信息传递给操作系统;
(2)dts(device tree source):设备树源文件,描述设备信息的;
(3)dtc(device tree compiler):设备树编译/反编译/调试工具;
(4)dtb(device tree binary):二进制设备树镜像;
(5)dtsi(device tree source include):功能类似设备树文件的头文件,可以被dts文件通过include引用,dtsi文件一般是描述共性部分;

2、设备树解决什么问题

(1)在设备驱动源码中,分为驱动代码和设备代码,驱动代码是操作硬件的方法,设备代码是硬件资源、数据,当驱动代码和设备代码匹配时就会调用驱动的probe函数,probe函数会利用设备代码的资源去初始化设备;
(2)设备树之前,设备代码都是直接写在内核源码中的,以platform_device结构体的形式存在,驱动代码和设备代码也是在platform总线上匹配,当需要修改设备资源时,就需要修改内核源码;
(3)设备树技术将设备的硬件资源信息就写在dts文件中,需要修改就修改dts文件,不必在修改内核源码;
(4)不采用设备树技术:内核源码中会充斥大量设备硬件描述信息,导致内核源码不停增多,但是增多的硬件描述信息代码和内核功能并不相关;
(5)采用设备树技术之后:设备的硬件描述信息都在dts文件中,修改方便,但是内核要增加解析dts文件格式的代码;

3、设备树怎么工作

图片:dts文件格式转换

(1)驱动开发者根据硬件编写/修改dts文件,使得将来驱动代码能匹配到合适的设备硬件信息;
(2)编译内核时,kernel会先编译出dtc,然后再用dtc将dts文件编译成dtb;
(3)uboot启动kernel时,将内核镜像和dtb都重定位到内存,并告诉内核dtb的所在内存地址;
(4)内核启动初期调用内部函数解析dtb,得到硬件信息后再组装成硬件函数,最后去和驱动代码进行匹配;

4、设备树源码dts文件格式讲解

4.1、dts文件在内核源码中的存放位置

arm架构:arch/arm/boot/dts目录中

4.2、dts文件格式简介

(1)注释用/* */,注意#开头的不是注释
(2)分号是段落块之间的分隔符,{}和[]和<>是段落块的封装符号,和C语言语言类似
(3)/dts-v1/节点,表示dts的版本号,目前都是v1
(4)/{}是根节点root node,理论上只应该有一个根节点,有说法dtc会合并所有root node为同一个
(5)dts是树状的多节点组织,基本单元是node,除root外其他node都有parent,还可以有child

4.3、节点格式

4.3.1、格式定义

[label:] <node-name> [@<unit-address>]{[property][child nodes][child nodes]......
};

4.3.2、格式解读

(1)[]:表示该项可以省略,<>:表示不可省略;
(2)[label:]:label是标签名,为了方便访问节点,后面可以直接通过&label来访问该节点。
(3)node-name:节点名称。根节点的名称必须是/
(4)[@unit-address]:unit-address是设备地址,如cpu node就是0、1这种,reg node就是0x12010000这种;

4.3.3、示例代码

cpus {/* 下面三项是cpus节点的属性 */#address-cells = <1>;#size-cells = <0>;enable-method = "hisilicon,hi3516dv300";/* 下面是子节点 */cpu@0 {device_type = "cpu";compatible = "arm,cortex-a7";clock-frequency = <HI3516DV300_FIXED_1000M>;reg = <0>;};
};

(1)cpus是cpu的父节点,从形式来能直观的看出来,cpu节点是被cpus节点的大括号括起来的;
(2)cpus节点省略了标签名和设备地址,只有节点名称;

5、节点属性分析

5.1、GPIO属性格式

/{gpx1:gpx1{controller;#gpio-cells=<2>;};key@11400c24{compatible="fs4412,key";reg=<0x11400c24 0x4>;intn-key=<&gpx1 2 2>;}
}

(1)gpio-controller:说明该节点描述的是一个gpio控制器;
(2)#gpio-cells:描述gpio使用节点的属性一个cell的内容;

5.2、compatible属性格式

uart0: uart@120a0000 {compatible = "arm,pl011", "arm,primecell";reg = <0x120a0000 0x1000>;interrupts = <0 6 4>;clocks = <&clock HI3516DV300_UART0_CLK>;clock-names = "apb_pclk";status = "disabled";
};/* 在驱动中对应的结构体*///struct device_driver->of_match_table->compatiblestruct of_device_id {char	name[32];char	type[32];char	compatible[128];const void *data;
};

(1)compatible属性是用于设备节点和设备驱动匹配用的,在内核描述驱动的structdevice_driver结构体中,compatible变量中就会保存用于匹配的字符串,当设备节点和驱动的
compatible相同时就匹配成功;
(2)compatible后面可以有多个字符串,优先匹配靠前的字符串,靠前的字符串匹配不上才会匹配后面的字符串;

5.3、model属性格式

/ {model = "Tyr DEMO Board";compatible = "hisilicon,hi3516dv300";memory {device_type = "memory";reg = <0x82000000 0x20000000>;};
};

(1)model是描述模块信息的,一般只有根节点才有,标明设备树文件对应的开发板的名称;
(2)在内核的启动打印中可以看到model的值:“OF: fdt:Machine model: Tyr DEMO Board”;

5.4、status属性格式

&uart0 {status = "okay";
};
状态值含义
okey表示设备是可操作的
disabled表示当前不可操作,但是后续是可以更改为可操作性的
fail、failed表示有严重错误,几乎不可能再可操作了

(1)status描述设备信息状态,在设备树文件中可以根据需求设置模块的状态,功能就是开启/关闭某个模块;
(2)在dtsi文件中,默认都是关闭模块的,在开发板对应的dts文件中自己去打开需要的模块;

5.5、reg属性格式

clock: clock@12010000 {compatible = "hisilicon,hi3516dv300-clock";#address-cells = <1>;	/* 表示reg里面的数据address占用一个字长*/#size-cells = <1>;		/* 表示reg里面的数据size占用一个字长,注意字长不是字节*/#clock-cells = <1>;#reset-cells = <2>;reg = <0x12010000 0x1000>;	/*起始地址是0x12010000,长度是0x1000*/
};

(1)reg属性:配置某个硬件模块对应的地址范围信息;
(2)#address-cells属性:表示reg里面的数据address占用的字长,注意字长不是字节;
(3)#size-cells:表示reg里面的数据size占用的字长,注意字长不是字节;
(4)reg = <address1 length1 address2 length2 …>:address一般用来表示起始地址,length一般表示持续长度;

5.6、中断属性格式

gic: interrupt-controller@10300000 {compatible = "arm,cortex-a7-gic";#interrupt-cells = <3>;	/*表示interrupts用三个cell来描述中断*/#address-cells = <0>;interrupt-controller;	/*标明gic节点是中断控制器*//* gic dist base, gic cpu base , no virtual support */reg = <0x10301000 0x1000>, <0x10302000 0x100>;};ipcm: ipcm@045E0000 {compatible = "hisilicon,ipcm-interrupt";interrupt-parent = <&gic>;	/*父节点是gic节点*/interrupts = <0 10 4>;	/*<中断域 中断 触发方式>*/reg = <0x10300000 0x4000>;	status = "okay";
};

(1)interrupt-controller:无值属性,表示这是个中断控制器node
(2)#interrupt-cells:这是中断控制器节点的属性,用来标识这个控制器需要几个cell做中断描述符
(3)interrupt-parent:标识此设备节点属于哪一个中断控制器,如果没有这个属性,会自动依附父节点
(4)interrupts :一个中断标识符列表,表示每一个中断输出信号

6、特殊节点

6.1、chosen子节点

6.1.1、chosen子节点功能介绍

chosen {stdout-path = "serial0:115200n8";
};

(1)chosen子节点不对应真实的设备,是用来描述内核启动参数的,对应于uboot启动内核时传递的bootargs参数;
(2)上面是摘抄的内核dts文件中的chosen子节点,里面只设置了stdout-path属性,也就是把输出设置成串口0,波特率是115200;
(3)dts文件中设置的属性会被覆盖点,具体就是uboot在启动内核时,会将bootargs启动参数转换成chosen子节点的属性,替换掉dts文件中设置的属性;

6.1.2、chosen子节点在内核中的体现

~ # ls /proc/device-tree/chosen/
bootargs  name
~ # 
~ # cat /proc/device-tree/chosen/bootargs 
mem=1408M console=ttyS0,115200 root=/dev/mmcblk0p7 rootfstype=squashfs rootwait
~ # 
~ # cat /proc/device-tree/chosen/name 
chosen
~ # 

6.2、aliases子节点

	aliases {serial0 = &uart0;gpio0 = &gpio_chip0;gpio1 = &gpio_chip1;gpio2 = &gpio_chip2;······};

aliases就是别名的意思,aliases节点主要功能就是给节点定义别名,为了方便访问节点。不过我们在节点命名的时候可以加上label标签,直接通过&label引用标签来访问也很方便,aliases节点内部其实也是通过引用标签名来定义别名;

7、节点相关操作

7.1、节点引用和内容替换

gpio_chip1: gpio_chip@120d1000 {compatible = "arm,pl061", "arm,primecell";reg = <0x120d1000 0x1000>;interrupts = <0 17 4>;clocks = <&clock  HI3516DV300_SYSAPB_CLK>;clock-names = "apb_pclk";#gpio-cells = <2>;status = "disabled";
};/*引用gpio_chip1节点*/
&gpio_chip1 {status = "okay";	/*替换status属性内容*/
};

对于已经定义好的节点,我们通过引用节点的方式,重新定义某些属性,效果上看就是替换掉某些属性的值;

7.2、合并节点内容

/{node{key1=value1;}
}/{node{key2=value2;}
}//合并的结果
/{node{key1=value1;key2=value2;}
}

有时候我们需要增加硬件描述的信息,这时候就可以在后面创新定义该节点,最后解析的时候会把同名节点不同的部分进行合并;

http://www.lryc.cn/news/570916.html

相关文章:

  • matlab axis函数_MATLAB二维图形
  • HTML网页一键变黑白色调
  • Source Insight的入门使用
  • 网页鼠标点击特效案例收集
  • 如何使用十进制range()步长值?
  • python升级pip怎么出错了_Python,开启吐槽模式,新手必看!
  • linux命令chm app,Linux常用命令全集
  • 拼音缩写是啥意思_NMSL?AWSL?这些拼音缩写到底是啥意思?
  • Package name is not valid . ‘import‘ is not a valid Java identifier
  • mysql修改密码笔记
  • 如何用计算机cmd算数,计算命令:怎么在CMD的计算器命令是什么?
  • 小四哥的故事——访中联绿盟陈庆
  • 山寨qq java_MTK手机QQjava版本山寨qq2009通用版
  • 服务器重装
  • 计算机网络——用telnet登录qq邮箱给人发邮件
  • 1.2数组的基本算法设计
  • Minecraft-服务器领地(Residence插件)
  • 状态模式State Pattern
  • Myeclipse 10安装与激活
  • 性能测试——性能测试-常见性能指标-总体概况
  • 1KB快捷方式病毒的解决方法
  • C# 零基础搭建一个简单的Asp.Net Core WebAip服务
  • 当他成为SKY ——李晓峰
  • 5.5.2_2并查集的进一步优化
  • Cult3D高级教程——1.技术综合篇
  • sql脚本导入sql_学习SQL:SQL脚本
  • 16进制颜色代码对照表
  • Eighth season eighth episode,Monica got a stripper in her bachelorette party??????
  • foxmail6.0需要下载证书才能发送邮件的解决
  • 无线路由器接入局域网的三种方式