IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux资料学习笔记-Linux驱动开发篇-Linux设备树 -> 正文阅读

[系统运维]Linux资料学习笔记-Linux驱动开发篇-Linux设备树

目录

1.什么是设备树?

2.DTS、DTB和DTC

3.DTS语法

? ? 1).dtsi头文件

? ? 2)设备节点

? ? 3)标准属性

? ? ? ? ? 1、compatible属性

? ? ? ? ? 2、model属性

? ? ? ? ? 3、status属性

? ? ? ? ? 4、#address-cells和#size-cells属性

? ? ? ? ? 5、reg属性


? ? ? 前面章节中我们多次提到“设备树”这个概念,因为时机未到,所以当时并没有详细的讲解什么

? ? ? 是“设备树”,本章我们就来详细的谈一谈设备树。

? ? ? 掌握设备树是Linux驱动开发人员必备的技能!因为在新版本的Linux中,ARM相关的驱动全部

? ? ? 采用了设备树(也有支持老式驱动的,比较少),最新出的CPU其驱动开发也基本都是基于设备

? ? ? 树的,比如ST新出的STM32MP157、NXP的I.MX8系列等。我们所使用的Linux版本为

? ? ? 4.1.15,其支持设备树,所以正点原子I.MX6U-ALPHA开发板的所有Linux驱动都是基于设备树

? ? ? 的。

? ? ? 本章我们就来了解一下设备树的起源、重点学习一下设备树语法。

1.什么是设备树?

? ? ? 设备树(DeviceTree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做

? ? ? DTS(DeviceTreeSource),这个DTS文件采用树形结构描述板级设备,也就是开发板上的设备

? ? ? 信息,比如CPU数量、内存基地址、IIC接口上接了哪些设备、SPI接口上接了哪些设备等等,

? ? ? 如图1所示:

图1?设备树结构示意图

? ? ? 在图1中,树的主干就是系统总线,IIC控制器、GPIO控制器、SPI控制器等都是接到系统主线

? ? ? 上的分支。IIC控制器有分为IIC1和IIC2两种,其中IIC1上接了FT5206和AT24C02这两个IIC设

? ? ? 备,IIC2上只接了MPU6050这个设备。

? ? ? DTS文件的主要功能就是按照图1所示的结构来描述板子上的设备信息,DTS文件描述设备信

? ? ? 息是有相应的语法规则要求的,稍后我们会详细的讲解DTS语法规则。

? ? ? 在3.x版本(具体哪个版本笔者也无从考证)以前的Linux内核中ARM架构并没有采用设备树。在

? ? ? 没有设备树的时候Linux是如何描述ARM架构中的板级信息呢?在Linux内核源码中大量的

? ? ? arch/arm/mach-xxx和arch/arm/plat-xxx文件夹,这些文件夹里面的文件就是对应平台下的板级

? ? ? 信息。比如在arch/arm/mach-smdk2440.c中有如下内容(有缩减):

90 static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {
91
92 		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
93 					S3C2410_LCDCON5_INVVLINE |
94 					S3C2410_LCDCON5_INVVFRAME |
95 					S3C2410_LCDCON5_PWREN |
96 					S3C2410_LCDCON5_HWSWP,
......
113 };
114
115 static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
116 	.displays = &smdk2440_lcd_cfg,
117 	.num_displays = 1,
118 	.default_display = 0,
......
133 };
134
135 static struct platform_device *smdk2440_devices[] __initdata = {
136 	&s3c_device_ohci,
137 	&s3c_device_lcd,
138 	&s3c_device_wdt,
139 	&s3c_device_i2c0,
140 	&s3c_device_iis,
141 };

? ? ??上述代码中的结构体变量smdk2440_fb_info就是描述SMDK2440这个开发板上的LCD信息的,

? ? ? 结构体指针数组smdk2440_devices描述的SMDK2440这个开发板上的所有平台相关信息。这

? ? ? 个仅仅是使用2440这个芯片的SMDK2440开发板下的LCD信息,SMDK2440开发板还有很多的

? ? ? 其他外设硬件和平台硬件信息。使用2440这个芯片的板子有很多,每个板子都有描述相应板级

? ? ? 信息的文件,这仅仅只是一个2440。

? ? ? 随着智能手机的发展,每年新出的ARM架构芯片少说都在数十、数百款,Linux内核下板级信

? ? ? 息文件将会成指数级增长!这些板级信息文件都是.c或.h文件,都会被硬编码进Linux内核中,

? ? ? 导致Linux内核“虚胖”。就好比你喜欢吃自助餐,然后花了100多到一家宣传看着很不错的自助

? ? ? 餐厅,结果你想吃的牛排、海鲜、烤肉基本没多少,全都是一些凉菜、炒面、西瓜、饮料等小

? ? ? 吃,相信你此时肯定会脱口而出一句“F*k!”、“骗子!”。

? ? ? 同样的,当Linux之父linus看到ARM社区向Linux内核添加了大量“无用”、冗余的板级信息文

? ? ? 件,不禁的发出了一句“This whole ARM thing is a f*cking pain in the ass”。从此以后ARM

? ? ? 社区就引入了PowerPC等架构已经采用的设备树(FlattenedDeviceTree),将这些描述板级硬件

? ? ? 信息的内容都从Linux内中分离开来,用一个专属的文件格式来描述,这个专属的文件就叫做设

? ? ? 备树,文件扩展名为.dts

? ? ? 一个SOC可以作出很多不同的板子,这些不同的板子肯定是有共同的信息,将这些共同的信息

? ? ? 提取出来作为一个通用的文件,其他的.dts文件直接引用这个通用文件即可,这个通用文件就

? ? ? 是.dtsi文件,类似于C语言中的头文件

? ? ? 一般.dts描述板级信息(也就是开发板上有哪些IIC设备、SPI设备等),.dtsi描述SOC级信息(也

? ? ? 就是SOC有几个CPU、主频是多少、各个外设控制器信息等)。

? ? ? 这个就是设备树的由来,简而言之就是,Linux内核中ARM架构下有太多的冗余的垃圾板级信

? ? ? 息文件,导致linus震怒,然后ARM社区引入了设备树。

2.DTS、DTB和DTC

? ? ? 上一小节说了,设备树源文件扩展名为.dts,但是我们在前面移植Linux的时候却一直在使

? ? ? 用.dtb文件,那么DTS和DTB这两个文件是什么关系呢?

? ? ? DTS是设备树源码文件,DTB是将DTS编译以后得到的二进制文件。将.c文件编译为.o需要用

? ? ? 到gcc编译器,那么将.dts编译为.dtb需要什么工具呢?需要用到DTC工具!DTC工具源码在

? ? ? Linux内核的scripts/dtc目录下,scripts/dtc/Makefile文件内容如下:

1 hostprogs-y := dtc
2 always := $(hostprogs-y)
3
4 dtc-objs:= dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
5 			srcpos.o checks.o util.o
6 dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
......

? ? ??可以看出,DTC工具依赖于dtc.c、flattree.c、fstree.c等文件,最终编译并链接出DTC这个主机

? ? ? 文件。如果要编译DTS文件的话只需要进入到Linux源码根目录下,然后执行如下命令:

make all

? ? ? 或者:

make dtbs

? ? ??“make all”命令是编译Linux源码中的所有东西,包括zImage,.ko驱动模块以及设备树,如果只

? ? ? 是编译设备树的话建议使用“make dtbs”命令。

? ? ? 基于ARM架构的SOC有很多种,一种SOC又可以制作出很多款板子,每个板子都有一个对应

? ? ? 的DTS文件,那么如何确定编译哪一个DTS文件呢?我们就以I.MX6ULL这款芯片对应的板子为

? ? ? 例来看一下,打开arch/arm/boot/dts/Makefile,有如下内容:

381 dtb-$(CONFIG_SOC_IMX6UL) += \
382 	imx6ul-14x14-ddr3-arm2.dtb \
383 	imx6ul-14x14-ddr3-arm2-emmc.dtb \
......
400 dtb-$(CONFIG_SOC_IMX6ULL) += \
401 	imx6ull-14x14-ddr3-arm2.dtb \
402 	imx6ull-14x14-ddr3-arm2-adc.dtb \
403 	imx6ull-14x14-ddr3-arm2-cs42888.dtb \
404 	imx6ull-14x14-ddr3-arm2-ecspi.dtb \
405 	imx6ull-14x14-ddr3-arm2-emmc.dtb \
406 	imx6ull-14x14-ddr3-arm2-epdc.dtb \
407 	imx6ull-14x14-ddr3-arm2-flexcan2.dtb \
408 	imx6ull-14x14-ddr3-arm2-gpmi-weim.dtb \
409 	imx6ull-14x14-ddr3-arm2-lcdif.dtb \
410 	imx6ull-14x14-ddr3-arm2-ldo.dtb \
411 	imx6ull-14x14-ddr3-arm2-qspi.dtb \
412 	imx6ull-14x14-ddr3-arm2-qspi-all.dtb \
413 	imx6ull-14x14-ddr3-arm2-tsc.dtb \
414 	imx6ull-14x14-ddr3-arm2-uart2.dtb \
415 	imx6ull-14x14-ddr3-arm2-usb.dtb \
416 	imx6ull-14x14-ddr3-arm2-wm8958.dtb \
417 	imx6ull-14x14-evk.dtb \
418 	imx6ull-14x14-evk-btwifi.dtb \
419 	imx6ull-14x14-evk-emmc.dtb \
420 	imx6ull-14x14-evk-gpmi-weim.dtb \
421 	imx6ull-14x14-evk-usb-certi.dtb \
422 	imx6ull-alientek-emmc.dtb \
423 	imx6ull-alientek-nand.dtb \
424 	imx6ull-9x9-evk.dtb \
425 	imx6ull-9x9-evk-btwifi.dtb \
426 	imx6ull-9x9-evk-ldo.dtb
427 dtb-$(CONFIG_SOC_IMX6SLL) += \
428 	imx6sll-lpddr2-arm2.dtb \
429 	imx6sll-lpddr3-arm2.dtb \
......

? ? ??可以看出,当选中I.MX6ULL这个SOC以后(CONFIG_SOC_IMX6ULL=y),所有使用到

? ? ? I.MX6ULL这个SOC的板子对应的.dts文件都会被编译为.dtb。如果我们使用I.MX6ULL新做了一

? ? ? 个板子,只需要新建一个此板子对应的.dts文件,然后将对应的.dtb文件名添加到

? ? ? dtb-$(CONFIG_SOC_IMX6ULL)下,这样在编译设备树的时候就会将对应的.dts编译为二进制

? ? ? 的.dtb文件。

3.DTS语法

? ? ? 虽然我们基本上不会从头到尾重写一个.dts文件,大多时候是直接在SOC厂商提供的.dts文件上

? ? ? 进行修改。但是DTS文件语法我们还是需要详细的学习一遍,因为我们肯定需要修改.dts文

? ? ? 件。大家不要看到要学习新的语法就觉得会很复杂,DTS语法非常的人性化,是一种ASCII文

? ? ? 本文件,不管是阅读还是修改都很方便。

? ? ? 本节我们就以imx6ull-alientek-emmc.dts这个文件为例来讲解一下DTS语法。关于设备树详细

? ? ? 的语法规则请参考《DevicetreeSpecificationV0.2.pdf》和

? ? ?《Power_ePAPR_APPROVED_v1.12.pdf》这两份文档。

? ? 1).dtsi头文件

? ? ? ? ? ? ? 和C语言一样,设备树也支持头文件,设备树的头文件扩展名为.dtsi。在imx6ull-alientek-

? ? ? ? ? ? ? emmc.dts中有如下所示内容:

12 #include <dt-bindings/input/input.h>
13 #include "imx6ull.dtsi"

? ? ? ? ? ? ? 第12行,使用“#include”来引用“input.h”这个.h头文件。

? ? ? ? ? ? ? 第13行,使用“#include”来引用“imx6ull.dtsi”这个.dtsi头文件。

? ? ? ? ? ? ? 看到这里,大家可能会疑惑,不是说设备树的扩展名是.dtsi吗?为什么也可以直接引用C

? ? ? ? ? ? ? 语言中的.h头文件呢?这里并没有错,.dts文件引用C语言中的.h文件,甚至也可以引

? ? ? ? ? ? ? 用.dts文件,打开imx6ull-14x14-evk-gpmi-weim.dts这个文件,此文件中有如下内容:

9 #include "imx6ull-14x14-evk.dts"

? ? ? ? ? ? ?可以看出,以上代码中直接引用了.dts文件,因此在.dts设备树文件中,可以通过

? ? ? ? ? ? ? “#include”来引用.h、.dtsi和.dts文件。只是,我们在编写设备树头文件的时候最好选

? ? ? ? ? ? ? 择.dtsi后缀。

? ? ? ? ? ? ? 一般.dtsi文件用于描述SOC的内部外设信息,比如CPU架构、主频、外设寄存器地址范

? ? ? ? ? ? ? 围,比如UART、IIC等等。比如imx6ull.dtsi就是描述I.MX6ULL这颗SOC内部外设情况信

? ? ? ? ? ? ? 息的,内容如下:

10 #include <dt-bindings/clock/imx6ul-clock.h>
11 #include <dt-bindings/gpio/gpio.h>
12 #include <dt-bindings/interrupt-controller/arm-gic.h>
13 #include "imx6ull-pinfunc.h"
14 #include "imx6ull-pinfunc-snvs.h"
15 #include "skeleton.dtsi"
16
17 / {
18 		aliases {
19 			can0 = &flexcan1;
......
48 		};
49
50 		cpus {
51 			#address-cells = <1>;
52 			#size-cells = <0>;
53
54 			cpu0: cpu@0 {
55 				compatible = "arm,cortex-a7";
56 				device_type = "cpu";
......
89 			};
90 		};
91
92 		intc: interrupt-controller@00a01000 {
93 			compatible = "arm,cortex-a7-gic";
94 			#interrupt-cells = <3>;
95 			interrupt-controller;
96 			reg = <0x00a01000 0x1000>,
97 				<0x00a02000 0x100>;
98 		};
99
100 	clocks {
101 		#address-cells = <1>;
102 		#size-cells = <0>;
103
104 	ckil: clock@0 {
105 		compatible = "fixed-clock";
106 		reg = <0>;
107 		#clock-cells = <0>;
108 		clock-frequency = <32768>;
109 		clock-output-names = "ckil";
110 	};
......
135 };
136
137 soc {
138 	#address-cells = <1>;
139 	#size-cells = <1>;
140 	compatible = "simple-bus";
141 	interrupt-parent = <&gpc>;
142 	ranges;
143
144 	busfreq {
145 		compatible = "fsl,imx_busfreq";
......
162 	};
197
198 	gpmi: gpmi-nand@01806000{
199 		compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";
200 		#address-cells = <1>;
201 		#size-cells = <1>;
202 		reg = <0x01806000 0x2000>, <0x01808000 0x4000>;
......
216 		};
......
1177 	};
1178 };

? ? ? ? ? ? ?以上代码中第54~89行就是cpu0这个设备节点信息,这个节点信息描述了I.MX6ULL这颗

? ? ? ? ? ? ?SOC所使用的CPU信息,比如架构是cortex-A7,频率支持996MHz、792MHz、

? ? ? ? ? ? ?528MHz、396MHz和198MHz等等。在imx6ull.dtsi文件中不仅仅描述了cpu0这一个节点信

? ? ? ? ? ? ?息,I.MX6ULL这颗SOC所有的外设都描述的清清楚楚,比如ecspi1~4、uart1~8、

? ? ? ? ? ? ?usbphy1~2、i2c1~4等等,关于这些设备节点信息的具体内容我们稍后在详细的讲解。

? ? 2)设备节点

? ? ? ? ? ? ? 设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设

? ? ? ? ? ? ? 备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键值对。以下是从

? ? ? ? ? ? ? imx6ull.dtsi文件中缩减出来的设备树文件内容:

1 / {
2 		aliases {
3 			can0 = &flexcan1;
4 		};
5
6 		cpus {
7 			#address-cells = <1>;
8 			#size-cells = <0>;
9
10 			cpu0: cpu@0 {
11 				compatible = "arm,cortex-a7";
12 				device_type = "cpu";
13 				reg = <0>;
14 			};
15 		};
16
17 		intc: interrupt-controller@00a01000 {
18 			compatible = "arm,cortex-a7-gic";
19 			#interrupt-cells = <3>;
20 			interrupt-controller;
21 			reg = <0x00a01000 0x1000>,
22 					<0x00a02000 0x100>;
23 		};
24 }

? ? ? ? ? ? ? 第1行,“/”是根节点,每个设备树文件只有一个根节点。细心的同学应该会发现,

? ? ? ? ? ? ? imx6ull.dtsi和imx6ull-alientek-emmc.dts这两个文件都有一个“/”根节点,这样不会出错

? ? ? ? ? ? ? 吗?不会的,因为这两个“/”根节点的内容会合并成一个根节点。

? ? ? ? ? ? ? 第2、6和17行,aliases、cpus和intc是三个子节点,在设备树中节点命名格式如下:

node-name@unit-address

? ? ? ? ? ? ? 其中“node-name”是节点名字,为ASCII字符串,节点名字应该能够清晰的描述出节点的

? ? ? ? ? ? ? 功能,比如“uart1”就表示这个节点是UART1外设。“unit-address”一般表示设备的地址或

? ? ? ? ? ? ? 寄存器首地址,如果某个节点没有地址或者寄存器的话“unit-address”可以不要,比如

? ? ? ? ? ? ? “cpu@0”、“interrupt-controller@00a01000”。

? ? ? ? ? ? ? 但是我们在以上代码中我们看到的节点命名却如下所示:

cpu0:cpu@0

? ? ? ? ? ? ? 上述命令并不是“node-name@unit-address”这样的格式,而是用“:”隔开成了两部分,

? ? ? ? ? ? ? ?“:”前面的是节点标签(label),“:”后面的才是节点名字,格式如下所示:

label: node-name@unit-address

? ? ? ? ? ? ??引入label的目的就是为了方便访问节点,可以直接通过&label来访问这个节点,比如通过

? ? ? ? ? ? ? &cpu0就可以访问“cpu@0”这个节点,而不需要输入完整的节点名字。再比如节点

? ? ? ? ? ? ? “intc:interrupt-controller@00a01000”,节点label是intc,而节点名字就很长了,为

? ? ? ? ? ? ? ?“interrupt-controller@00a01000”。很明显通过&intc来访问“interrupt-

? ? ? ? ? ? ? controller@00a01000”这个节点要方便很多!

? ? ? ? ? ? ? 第10行,cpu0也是一个节点,只是cpu0是cpus的子节点

? ? ? ? ? ? ? 每个节点都有不同属性,不同的属性又有不同的内容,属性都是键值对,值可以为空或任

? ? ? ? ? ? ? 意的字节流。设备树源码中常用的几种数据形式如下所示:

? ? ? ? ? ? ? 1.字符串

compatible = "arm,cortex-a7";

? ? ? ? ? ? ? 2.32位无符号整数

reg = <0>;

? ? ? ? ? ? ? ? ? 上述代码设置reg属性的值为0,reg的值也可以设置为一组值,比如:

reg = <0 0x123456 100>;

? ? ? ? ? ? ? 3.字符串列表

? ? ? ? ? ? ? ? ?属性值也可以为字符串列表,字符串和字符串之间采用“,”隔开,如下所示:

compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";

? ? ? ? ? ? ? ? ?上述代码设置属性compatible的值为“fsl,imx6ull-gpmi-nand”和“fsl,imx6ul-gpmi-nand”。

? ? 3)标准属性

? ? ? ? ? ? ? ?节点是由一堆的属性组成,节点都是具体的设备,不同的设备需要的属性不同,用户可

? ? ? ? ? ? ? ?以自定义属性。除了用户自定义属性,有很多属性是标准属性,Linux下的很多外设驱动

? ? ? ? ? ? ? ?都会使用这些标准属性,本节我们就来学习一下几个常用的标准属性。

? ? ? ? ? 1、compatible属性

? ? ? ? ? ? ? ? ? ? ? compatible属性也叫做“兼容性”属性,这是非常重要的一个属性!compatible属性的

? ? ? ? ? ? ? ? ? ? ? 值是一个字符串列表,compatible属性用于将设备和驱动绑定起来。字符串列表用于

? ? ? ? ? ? ? ? ? ? ? 选择设备所要使用的驱动程序,compatible属性的值格式如下所示:

"manufacturer,model"

? ? ? ? ? ? ? ? ? ? ?其中manufacturer表示厂商model一般是模块对应的驱动名字。比如imx6ull-

? ? ? ? ? ? ? ? ? ? ?alientek-emmc.dts中sound节点是I.MX6U-ALPHA开发板的音频设备节点,I.MX6U-

? ? ? ? ? ? ? ? ? ? ?ALPHA开发板上的音频芯片采用的欧胜(WOLFSON)出品的WM8960,sound节点的

? ? ? ? ? ? ? ? ? ? ?compatible属性值如下:

compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

? ? ? ? ? ? ? ? ? ? ?属性值有两个,分别为“fsl,imx6ul-evk-wm8960”和“fsl,imx-audio-wm8960”,其中“fsl”

? ? ? ? ? ? ? ? ? ? ?表示厂商是飞思卡尔,“imx6ul-evk-wm8960”和“imx-audio-wm8960”表示驱动模块名

? ? ? ? ? ? ? ? ? ? ?字。sound这个设备首先使用第一个兼容值在Linux内核里面查找,看看能不能找到与

? ? ? ? ? ? ? ? ? ? ?之匹配的驱动文件,如果没有找到的话就使用第二个兼容值查。

? ? ? ? ? ? ? ? ? ? ?一般驱动程序文件都会有一个OF匹配表,此OF匹配表保存着一些compatible值,如

? ? ? ? ? ? ? ? ? ? ?果设备节点的compatible属性值和OF匹配表中的任何一个值相等,那么就表示设备可

? ? ? ? ? ? ? ? ? ? ?以使用这个驱动。比如在文件imx-wm8960.c中有如下内容:

632 static const struct of_device_id imx_wm8960_dt_ids[] = {
633 	{ .compatible = "fsl,imx-audio-wm8960", },
634 	{ /* sentinel */ }
635 };
636 MODULE_DEVICE_TABLE(of, imx_wm8960_dt_ids);
637
638 static struct platform_driver imx_wm8960_driver = {
639 	.driver = {
640 		.name = "imx-wm8960",
641 		.pm = &snd_soc_pm_ops,
642 		.of_match_table = imx_wm8960_dt_ids,
643 	},
644 	.probe = imx_wm8960_probe,
645 	.remove = imx_wm8960_remove,
646 };

? ? ? ? ? ? ? ? ? ? ? 第632~635行的数组imx_wm8960_dt_ids就是imx-wm8960.c这个驱动文件的匹配

? ? ? ? ? ? ? ? ? ? ? 表,此匹配表只有一个匹配值“fsl,imx-audio-wm8960”。如果在设备树中有哪个节点

? ? ? ? ? ? ? ? ? ? ? 的compatible属性值与此相等,那么这个节点就会使用此驱动文件。

? ? ? ? ? ? ? ? ? ? ? 第642行,wm8960采用了platform_driver驱动模式,关于platform_driver驱动后面会

? ? ? ? ? ? ? ? ? ? ? 讲解。此行设置.of_match_table为imx_wm8960_dt_ids,也就是设置这个

? ? ? ? ? ? ? ? ? ? ? platform_driver所使用的OF匹配表。

? ? ? ? ? 2、model属性

? ? ? ? ? ? ? ? ? ? ? model属性值也是一个字符串,一般model属性描述设备模块信息,比如名字什么

? ? ? ? ? ? ? ? ? ? ? ?的,比如:

model = "wm8960-audio";

? ? ? ? ? 3、status属性

? ? ? ? ? ? ? ? ? ? ? status属性看名字就知道是和设备状态有关的,status属性值也是字符串,字符串是

? ? ? ? ? ? ? ? ? ? ? 设备的状态信息,可选的状态如图2所示:

图2?status属性值表

? ? ? ? ? 4、#address-cells和#size-cells属性

? ? ? ? ? ? ? ? ? ? ? 这两个属性的值都是无符号32位整形,#address-cells和#size-cells这两个属性可以

? ? ? ? ? ? ? ? ? ? ? 用在任何拥有子节点的设备中,用于描述子节点的地址信息。

? ? ? ? ? ? ? ? ? ? ? #address-cells属性值决定了子节点reg属性中地址信息所占用的字长(32位)

? ? ? ? ? ? ? ? ? ? ? #size-cells属性值决定了子节点reg属性中长度信息所占的字长(32位)

? ? ? ? ? ? ? ? ? ? ? #address-cells和#size-cells表明了子节点应该如何编写reg属性值,一般reg属性都是

? ? ? ? ? ? ? ? ? ? ? 和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度,reg属性的格

? ? ? ? ? ? ? ? ? ? ? 式为:

reg = <address1 length1 address2 length2 address3 length3……>

? ? ? ? ? ? ? ? ? ? ? 每个“address length”组合表示一个地址范围,其中address是起始地址,length是地

? ? ? ? ? ? ? ? ? ? ? 址长度,#address-cells表明address这个数据所占用的字长,#size-cells表明length

? ? ? ? ? ? ? ? ? ? ? 这个数据所占用的字长,比如:

1 spi4 {
2 		compatible = "spi-gpio";
3 		#address-cells = <1>;
4 		#size-cells = <0>;
5
6 		gpio_spi: gpio_spi@0 {
7 			compatible = "fairchild,74hc595";
8 			reg = <0>;
9 		};
10 };
11
12 aips3: aips-bus@02200000 {
13 		compatible = "fsl,aips-bus", "simple-bus";
14 		#address-cells = <1>;
15 		#size-cells = <1>;
16
17 		dcp: dcp@02280000 {
18 			compatible = "fsl,imx6sl-dcp";
19 			reg = <0x02280000 0x4000>;
20 		};
21 };

? ? ? ? ? ? ? ? ? ? ? 第3,4行,节点spi4的#address-cells=<1>,#size-cells=<0>,说明spi4的子节点reg

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?属性中起始地址所占用的字长为1,地址长度所占用的字长为0。

? ? ? ? ? ? ? ? ? ? ? 第8行,子节点gpio_spi:gpio_spi@0的reg属性值为<0>,因为父节点设置了

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#address-cells=<1>,#size-cells=<0>,因此addres=0,没有length的值,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?相当于设置了起始地址,而没有设置地址长度。

? ? ? ? ? ? ? ? ? ? ? 第14,15行,设置aips3:aips-bus@02200000节点#address-cells=<1>,#size-

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?cells=<1>,说明aips3:aips-bus@02200000节点起始地址长度所占用

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 的字长为1,地址长度所占用的字长也为1。

? ? ? ? ? ? ? ? ? ? ? ?第19行,子节点dcp:dcp@02280000的reg属性值为<0x02280000 0x4000>,因为

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 父节点设置了#address-cells=<1>,#size-cells=<1>,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? address=0x02280000,length=0x4000,相当于设置了起始地址为

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0x02280000,地址长度为0x40000。

? ? ? ? ? 5、reg属性

? ? ? ? ? ? ? ? ? ? ? reg属性前面已经提到过了,reg属性的值一般是(address,length)对。reg属性一般

? ? ? ? ? ? ? ? ? ? ? 用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息,比如在

? ? ? ? ? ? ? ? ? ? ? ?imx6ull.dtsi中有如下内容:

323 uart1: serial@02020000 {
324 	compatible = "fsl,imx6ul-uart",
325 				"fsl,imx6q-uart", "fsl,imx21-uart";
326 	reg = <0x02020000 0x4000>;
327 	interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
328 	clocks = <&clks IMX6UL_CLK_UART1_IPG>,
329 	<&clks IMX6UL_CLK_UART1_SERIAL>;
330 	clock-names = "ipg", "per";
331 	status = "disabled";
332 };

? ? ? ? ? ? ? ? ? ? ? 上述代码是节点uart1,uart1节点描述了I.MX6ULL的UART1相关信息,重点是第326

? ? ? ? ? ? ? ? ? ? ? ?行的reg属性。其中uart1的父节点aips1:aips-bus@02000000设置了#address-cells=

? ? ? ? ? ? ? ? ? ? ? ?<1>、#size-cells=<1>,因此reg属性中address=0x02020000,length=0x4000。查

? ? ? ? ? ? ? ? ? ? ? 阅《I.MX6ULL参考手册》可知,I.MX6ULL的UART1寄存器首地址为0x02020000,

? ? ? ? ? ? ? ? ? ? ? 但是UART1的地址长度(范围)并没有0x4000这么多,这里我们重点是获取UART1寄

? ? ? ? ? ? ? ? ? ? ? 存器首地址。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-04 20:06:08  更:2021-07-04 20:06:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 1:48:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计