设备树知识小全(七):地址编码

其实这个部分我在前面第四篇笔记中,介绍了这个,这里再展开这个讲讲。

参考资料:《Linux设备驱动开发详解》

1、地址编码

可寻址的设备使用如下信息在设备树中编码地址信息:

reg
    #address-cells
    #size-cells

其中,reg的组织形式为

reg=

其中的每一组address length表明了设备使用的一个地址范围。

address为1个或多个32位的整型(即cell),而length的意义则意味着从address到address+length–1的地址范围都属于该节点。若#size-cells=0,则length字段为空。

address和length字段是可变长的,父节点的#address-cells和#size-cells分别决定了子节点reg属性的address和length字段的长度。

在代码清单18.2中,根节点的#address-cells=<1>;和#size-cells=<1>;决定了serial、gpio、spi等节点的address和length字段的长度分别为1

cpus节点的#address-cells=<1>;和#size-cells=<0>;决定了两个cpu子节点的address为1,而length为空,于是形成了两个cpu的reg=<0>;和reg=<1>;。

external-bus节点的#address-cells=<2>和#size-cells=<1>;
决定了其下的ethernet、i2c、flash的reg字段形如reg=<0 00 x1000>;、reg=<1 00 x1000>;和reg=<2 00 x4000000>;。

其中,address字段长度为2,开始的第一个cell(即“<”后的0、1、2)是对应的片选,第2个cell(即<000x1000>、<100x1000>和<200x1000000>中间的0,0,0)是相对该片选的基地址,第3个cell(即“>”前的0x1000、0x1000、0x1000000)为length。

特别要留意的是i2c节点中定义的#address-cells=<1>;和#size-cells=<0>;,其作用到了I2C总线上连接的RTC,它的address字段为0x58,是RTC设备的I2C地址。(这个意思就是你就在这里,哪里都不需要去)

根节点的直接子书点描述的是CPU的视图,因此根子节点的address区域就直接位于CPU的内存区域

但是,经过总线桥后的address往往需要经过转换才能对应CPU的内存映射

2、ranges

external-bus的ranges属性定义了经过external-bus桥后的地址范围如何映射到CPU的内存区域**。**

(设备的内存管理)

ranges是地址转换表,其中的每个项目是一个子地址、父地址以及在子地址空间的大小的映射。

映射表中的子地址、父地址分别采用子地址空间的#address-cells父地址空间的#address-cells大小。对于本例而言,子地址空间的#address-cells为2,父地址空间的#address-cells值为1,因此0 0 0x10100000 0x10000的

前2个cell为external-bus桥后external-bus上片选0偏移0,(子地址)

第3个cell表示external-bus上片选0偏移0的地址空间被映射到CPU的本地总线的0x10100000位置, (父地址)

第4个cell表示映射的大小为0x10000。 ranges后面两个项目的含义可以类推。(长度length)

ranges = <0 0  0x10100000   0x10000     // Chipselect 1, Ethernet
                  1 0  0x10160000   0x10000     // Chipselect 2, i2c controller
                  2 0  0x30000000   0x1000000>; // Chipselect 3, NOR Flash

慢慢看多了就理解了,我这么菜,感觉有时候也很晕乎乎。

你可能感兴趣的:(工具技能知识点学习,驱动开发,kernel,ARM,UBoot,设备树)