地址转换规则在设备树中通过ranges
属性来定义,它允许将一个设备的地址空间映射到另一个不同的地址空间,这通常用于硬件设计中,其中某些设备通过总线桥接器(bus bridges)连接到CPU或主总线。这种映射是必需的,因为不是所有设备都直接连接到CPU可以访问的地址空间。
地址转换规则的组成
ranges
属性的每个条目都是一个元组,定义了子地址空间如何映射到父地址空间。每个元组包含三个主要部分:
- 子地址单元 (
child-address-space
) - 父地址单元 (
parent-address-space
) - 长度单元 (
length
)
地址转换规则的语法
在设备树源文件(DTS)中,ranges
属性的语法如下:
ranges = <
<child-address-cell-1 child-address-cell-2 ...>
<parent-address-cell-1 parent-address-cell-2 ...>
<length-cell-1 length-cell-2 ...>
>;
- child-address-cell:表示子设备的地址空间中的地址。
- parent-address-cell:表示父设备的地址空间中的地址。
- length-cell:表示映射的地址空间的长度。
地址转换规则的解释
每个ranges
条目定义了一个地址转换规则,其含义是:
- 从子地址空间的
child-address-space
开始的内存区域, - 映射到父地址空间的
parent-address-space
开始的内存区域, - 映射的长度为
length
。
示例
考虑以下设备树片段:
/ {
model = "Example Board";
compatible = "example,board";
external-bus {
#address-cells = <2>;
#size-cells = <1>;
ranges = <
// 子地址 父地址 长度
0x0 0x40000000 0x00100000 // 子地址空间0x0到0xFFFFF映射到父地址空间0x40000000到0x400FFFFF
0x1 0x41000000 0x00100000 // 子地址空间0x100000到0x1FFFFF映射到父地址空间0x41000000到0x410FFFFF
>;
// 子设备定义...
};
};
在这个示例中,external-bus
是一个父总线,它有两个地址转换规则:
- 子地址空间从
0x0
开始,长度为0x00100000
(1MB),映射到父地址空间从0x40000000
开始的同样长度的区域。 - 子地址空间从
0x100000
(1MB)开始,长度为0x00100000
(1MB),映射到父地址空间从0x41000000
开始的同样长度的区域。
这意味着,当CPU尝试访问0x40000000
到0x410FFFFF
之间的地址时,内存控制器将这些访问转发到相应的子设备地址空间。
注意事项
#address-cells
和#size-cells
属性定义了在reg
属性和ranges
属性中地址和大小的单元数量。在64位系统中,这些值可能是2,表示地址和大小使用两个单元(64位)。- 地址转换规则必须正确无误,否则设备可能无法正确访问内存或其他资源,导致系统不稳定或无法启动。
地址转换是设备树中一个强大的特性,它为硬件设计提供了灵活性,允许不同地址空间之间的映射和转换。