-
一、
dts
产生原因
.
...........................
..................................................
..................................................
.................................
2
二、
dts
基本知识
.
...........................
..................................................
..................................................
.................................
2
2.1 dts
加载过程
.
................................
..................................................
..................................................
......................
2
2.2
dts
描述信息
.
< br>............................................... .................................................. .................................................. .......
3
2.3
dts
组成结构示例
.
.............................................
..................................................
..................................................
.
3
2.4
dts
语法
.
.................................................
..................................................
..................................................
.............
4
2.4.1
compatible
.
...............
..................................................
..................................................
...............................
6
2.4.2 name@unit-address
....
..................................................
..................................................
.............................
6
2.4.3 reg address-cells size-cells
.
...............................
..................................................
..........................................
6
2.4.5 interrupt ..........
..................................................
..................................................
.........................................
9
三、
dts
与驱动
.
...........
..................................................
..................................................
..................................................
.
1
0
四、具体案例
.
................................................ .................................................. .................................................. ................
1
1
4.1 gpio
.
.......
..................................................
..................................................
..................................................
..........
1
2
4.2
interrupt ........................................
..................................................
..................................................
....................
1
2
4.3 pinctl.............................
..................................................
..................................................
.....................................
1
2
4.4 clk ......
..................................................
..................................................
..................................................
..............
1
3
dts
入门
本文目标是了解
dts
基本语法,可以尝试去看内核
dts
中的文件,
p>
follow
去配置。
< br>一、
dts
产生原因
DTS
即
Device
Tree
Source
设备树源码
,
Device
Tree
是一种描述硬件的数据结构,它起源于
OpenFirmware
(OF)
。
它替代
arch/arm/plat-
xxx
和
arch/arm/mach-xxx
中的板级
spec
代码,便于
code
管理。
ARM
平台的相关
code
相关规范调整:
1
、
ARM
的核心代码仍然保存在
arch/arm
目录下
2
、
ARM
SOC core architecture code
保存在
arch/arm
目录下
3
、
ARM SOC
< br>的周边外设模块的驱动保存在
drivers
目录下
p>
4
、
ARM
SOC
的特定代码在
arch/arm/mach-
xxx
目录下
5
、
ARM SOC board
specific
的代码被移除,由
Device
Tree
机制来负责传递硬件拓扑和硬件资源信息。
本质上,
Device
Tree
p>
改变了原来用
hardcode
方式将
p>
HW
配置信息嵌入到内核代码的方法,改用
bootloader
传递一些参数。
如果我们认为
kernel
是一个
b
lack box
,那么其输入参数应该包括:
a.
识别
platform
的信息
b. runtime
的配置参数
c.
设备的拓扑结构以及特性
对于嵌入式系统,在系统启动阶段,
bootloader
会加载内核并将控制权转交给内核,此外,还需要把上述的
三个参数信息传
递给
kernel
,以便
kernel
可以有较大的灵活性。在
linux
kernel
中,
Device
Tree
的设计目标就
是如此。
二、
dts
基本知识
2.1 dts
加载过程
如果要使用
Device Tree
,
首先用户要了解自己的硬件配置和系统运行参数,
并把这些信息
组织成
Device Tree
source file
p>
。通过
DTC
(
D
evice Tree
Compiler
),可以将这些适合人类阅读的
Device
Tree source file
变成适合机器
处理的
Device Tree binary file
(有一个更好听的
名字,
DTB
,
device
tree blob
)。在系统启动的时候,
boot pro
gram
(例如:
firmware
、
bootloader
)可以将保存在
flash
中的
DTB copy
到内
存(当然也可以通过其他方式,例如可以
通过
bootload
er
的交互式命令加载
DTB
,或者<
/p>
firmware
可以探测到
devic
e
的信息,组织成
DTB
保存在内存中
),
并把
DTB
的起始地址传递给
p>
client
program
(例如
OS
kernel
,
bootloader
或者其他特殊功能的程序)。对于计算
机系统(
computer system
),一般是
firmware
->bootloader->OS
,对于嵌入式系统,一般是
bootloader->OS
。
在
高通
msm8992
平台:
sbl
将烧写在
emmc
中的
进行读取和处理,获得
nPla
tform
和
nSubtype
,如果
没有
CDT
分区,那么就
使用代码里配
置的
cdt
,存入共享内存;
lk
将从共享内存中获得
nPlatform
和
nSubtype
进行相应处理,确
定
dtb entry
,然后选择一个对应的
< br>dtb(
所有
dtb
保存在
p>
中
)
从
emmc
中读进内存地址
hdr->tags_a
ddr
,这个参数会传递给
kernel
;
kernel
通过传入的
dtb
地址进行设备的创建。
2.2
dts
描述信息
Device Tr
ee
由一系列被命名的结点(
node
)和属性(
property
)组成,而结点本身可包含子结点
。所谓属性,
其实就是成对出现的
name
和
value
。在
Device
Tree
中,可描述的信息包括(原先这些信息大多被
hard
code
到
kernel
中):
CPU
的数量和类别
内存基地址和大小
总线和桥
外设连接
中断控制器和中断使用情况
GPIO
控制器和
GPIO
使用情况
Clock
控制器和
C
lock
使用情况
它基本上就是画一
棵电路板上
CPU
、总线、设备组成的树,
Bootloader
会将这棵树传递给内核,然后内核可
以识别这棵树,并根据它展开出
Linux
内核中的
platform_device
、
i2c_cl
ient
、
spi_device
等设
备,而这些设备用到
的内存、
IRQ
等
资源,也被传递给了内核,内核会将这些资源绑定给展开的相应的设备。
是否
Device
Tree
要描述系统中的所有硬件信息?答案是否定的。基本上,那些可以动态探测到的设备是不
需要描述的,例如
USB device
。不过
对于
SOC
上的
usb host c
ontroller
,它是无法动态识别的,需要在
devic
e tree
中描述。同样的道理,在
computer
system
中,
PCI
device
可以被动态探测到,不需要在
device
tree
中描述,但是
PCI
bridge
如果不能被探测,那么就需要描述之。
.dts
文件是一种
ASCII
文本格式的
Device Tree
描
述,
此文本格式非常人性化,
适合人类的阅读习惯。
基本上,
在
ARM
Li
nux
在,一个
.dts
文件对应一个
ARM
的
machine
,
一般放置在内核的
arch/arm/boot/
dts/
目录
。由于一
个
SoC
可能对应多个
machine
(一个
SoC
可以对应多个产品和电路板),势必这些
.dts
文件需包含许多共同的部
分,
Linux
内核为了简化,把
SoC<
/p>
公用的部分或者多个
machine
共同
的部分一般提炼为
.dtsi
,类似于
C
语言的头
文件。其他的
machin
e
对应的
.dts
就
< br>include
这个
.dtsi
。
譬如在
arch/arm/boo
t/dts/qcom/
目录下,
高通的很多
< br>.dtsi
都
include
了
或者
。
正常情况下所有的
dts
< br>文件以及
dtsi
文件都含有一个根节点”
/
”,这样
include
之后就会造成有很多个“根
节点”
。
按理说
device tree
p>
既然是一个树,
那么其只能有一个根节点,
所有其他的节点都是派生于根节点的
child
node
。其实
Device
Tree Compiler
会对
DTS
的
node
进行合并,最终生成的
D
TB
中只有一个
root node.
device tree
的基本单元是
node
。
这些
node
被组织成树状结构,
除了
root node
,
每个
node
都只
有一个
parent
。
一个
device tree
文件中只能有一个
root node
。
每个
node
中包含了若干
的
property/value
来描述该
node
的一些特
性。每个
nod
e
用节点名字(
node
name
)标识,节点名字的格式是
node-
name@unit-address
。如果该
node
没有
reg
属性(后面会描述这个
property
),那么该节点名字中必须不能包括
@
和
unit-
address
。
unit-address
< br>的具体格
式是和设备挂在那个
bus
上相关。
例如对于
cpu
,其
p>
unit-address
就是从
0
开始编址,依次加一
。而具体的设备,
例如以
太网控制器,其
unit-
address
就是寄存器地址。
root
node
的
node name
是确定
的,必须是“
/
”。
在一个树状结构的
device tree
中,如何引用一个
node
呢?要想唯一指定一个
node
必须使用
full
path
,例如
/node-
name-1
/node-name-2
/node-
name-N
2.3
dts
组成结构示例
/ {
表示
root
结点,
该结点下有两个子结点
node1
和
n
ode2
node1 {
结点
下又含有子结点,本例中为
和
,各结点都有一系列属性
a-string-property =
属性是字符串
a-string-list-property =
字符串数组
a-byte-data-property = [0x01 0x23 0x34
0x56];
二进制数组
child-node1 {
first-child-
property;
second-child-property = <1>
;
Cells
(由
u32
整数组成)
a-string-
property =
};
child-node2 {
};
};
node2 {
an-empty-
property;
属性为空
a-cell-property = <1 2 3 4>;
/* each number (cell) is a uint32 */
child-node1 {
};
};
};
上述
.dts
< br>文件并没有什么真实的用途,但它基本表征了一个
Device
Tree
源文件的结构。
2.4
dts
语法
完整的
Device Tree
可以将
一个
PCB
摆在你眼前,下面我们一起来看一下:
下面以一个最简单的
machine
为例来看如何写一个
.dts
文件。假设此
machine
的配置如下:
1
个
双核
ARM
Cortex-A9 32
位处理器;
ARM
的
local bus
上的内存映射区域分布了
2
个串口(分别位于<
/p>
0x101F1000
和
0x101F2000
)、
GPIO
控制器
(位于
0x101F3000
)、
SPI
控制器(位于
0x
10115000
)、中断控制器(位于
0x10140000
)和一个
external
bus
桥;
External
bus
桥上又连接了
SMC SMC91111 Ethern
et
(位于
0x10100000
)、
I2C
控制器(位于
0x101600
00
)、
64MB NOR Flash
(位于
0x30000000
);
External bus
桥上连接
的
I2C
控制器所对应的
I2C
总线上又连接了
Maxim DS1338
实
时钟(
I2C
地址为
0x58
)。
其对应的
.dt
s
文件为:
/ {
compatible =
#address-cells = <1>;
子结点需要一个
cell
描述地址
#size-cells = <1>;
子结点需要一个
c
ell
描述长度
interrupt-parent = <&intc>;
cpus {
#address-cells = <1>;
#size-
cells = <0>;
cpu@
0
{
compatible =
reg = <0>;
};
cpu@
1
{
compatible =
reg = <1>;
};
};
serial@
101f1000
{
串口
compatible =
reg =
<
0x101f1000
0x1000 >;
interrupts = < 1 0 >;
};
serial@
101f2000
{
串口
compatible =
reg =
<
0x101f2000
0x1000 >;
interrupts = < 2 0 >;
};
gpio@
101f3000
{
GPIO
控制器
compatible =
reg = <
0x101f3000
0x1000
0x101f4000
0x0010>;
interrupts = < 3 0 >;
};
intc: interrupt-
controller@
10140000
{
中断控制器
compatible =
reg =
<
0x10140000
0x1000 >;
interrupt-controller;
#interrupt-cells = <2>;
};
spi@
10115000
{
spi
控制器
compatible =
reg = <
0x10115000
0x1000 >;
起始地址为
0x10115000
,长
度为
0x1000
interrupts = < 4 0 >;
};
external-bus {
external bus
桥
#address-cells = <2>
子结点需要两个
cell
描述地址,片选
< br>
#size-cells = <1>;
子结点需要一个
cell
描述长度
ranges = <
0 0
0x10100000 0x10000
//
Chipselect 1, Ethernet
片选
0
0
,地址
0x10100000
,长度
0x10000
1 0
0x10160000
0x10000
// Chipselect 2, i2c controller
2 0
0x30000000
0x1000000>;
// Chipselect 3,
NOR Flash
ethernet@0,0 {
compatible
=
reg = <0 0 0x1000>;
interrupts = < 5 2 >;
};
i2c@1,0 {
compatible =
#address-cells = <1>;
rtc
需要一个
cell
描述地址
#size-
cells = <0>;
rtc
不需要
< br>0
描述长度
reg = <1 0 0x1000>;
rtc@
58
{
compatible =
reg =
<
58
>;
interrupts = < 7 3 >;
};
};
flash@2,0 {
compatible =
reg = <2 0 0x4000000>;
};
};
};
注释不是太多,下面来详细分类解释:
2.4.1 compatible
上述
< br>.dts
文件中
,root
结点
的
compatible
属性
compatible =
定义
了系统的名称,它
的组织形式为:
。
Linux
内核
透过
root
结点
的
compatible
属性即可判断它启动的是什
p>
么
machine
。
在
.dts
文件的每个设备,都有一个
compatible
属性,<
/p>
compatible
属性用户驱动和设备的绑定。
compatible
属
性是一个字符串的列表,列
表中的第一个字符串表征了结点代表的确切设备,形式为
,
p>
其后的字符串表征可兼容的其他设备。可以说前面的是特指,后面的则涵盖更广的范围。
p>
如在
arch/arm/boot/dt
s/
中的
Flash
结点:
flash@0,00000000 {
compatible =
reg = <0 0x00000000
0x04000000>,
<1 0x00000000
0x04000000>;
bank-width = <4>;
};
compatible
属性
的第
2
个字符串
明显比第
1
个字符串
涵盖的范围更广。
2.4.2
name@unit-address
接下来
root
结点
的
cpus
p>
子结点下面又包含
2
个
cpu
子结点,描述了此
machine
< br>上的
2
个
CPU
,并且二者
的
compatible
属性为
。
注意
cpus
和
cpus
的
2
个
cpu
子结点的命名,它们遵循的组织形式为:
,
< br><>
中的内
容是必选项,
[]<
/p>
中的则为可选项。
name
是一个
ASCII
字符串,用于描述结点对应的设备类型,如网卡适配器对应
的结点
name
宜为
< br>ethernet
,表示这个是网卡。如果一个结点描述的设备有地址,则应该给
出
@unit-address
。多
个
相同类型设备结点的
name
可以一样,只要
< br>unit-address
不同即可,如本例中含有
cp
u@0
、
cpu@1
以及
serial@101f0000
与
serial@
101f2000
这样的同名结点。
设备的
unit-address
地址也经常在其对应结点的
re
g
属性中
给出。
2.4.3 reg address-cells size-cells
设备的地址特性根据一下几个属性来控制:
●
reg
-
-
-
-
-
-
-
-
-
上一篇:主板cmos自检出错
下一篇:用Abaqus所遇到问题汇总