在设备树(Device Tree)中,address-cells
和 size-cells
是两个关键属性,用于定义如何解析子节点中 reg
属性的地址和大小信息。它们是设备树中描述硬件资源(如内存映射I/O、寄存器等)的基础机制。
1. address-cells
属性
- 作用:定义子节点
reg
属性中 地址字段(address field) 占用的单元格(cell)数量。 - 取值范围:整数(通常为 1 或 2,取决于地址宽度)。
- 典型场景:
- 在 32 位系统中,地址通常用 1 个单元格(32 位)表示,因此
address-cells = <1>
。 - 在 64 位系统中,地址可能用 2 个单元格(64 位)表示,因此
address-cells = <2>
。
- 在 32 位系统中,地址通常用 1 个单元格(32 位)表示,因此
示例:
soc {
#address-cells = <2>; // 子节点的 reg 地址字段占 2 个单元格
#size-cells = <1>; // 子节点的 reg 大小字段占 1 个单元格
spi@0,0 {
reg = <0x0 0x1000 0x100>; // 地址 = 0x00001000(2 个单元格),大小 = 0x100(1 个单元格)
};
};
2. size-cells
属性
- 作用:定义子节点
reg
属性中 大小字段(size field) 占用的单元格(cell)数量。 - 取值范围:整数(通常为 1 或 2,取决于地址空间范围)。
- 典型场景:
- 如果地址空间大小用 32 位表示,则
size-cells = <1>
。 - 如果地址空间大小用 64 位表示,则
size-cells = <2>
。
- 如果地址空间大小用 32 位表示,则
示例:
memory@0 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x20000000>; // 地址 = 0x0000000080000000(2 个单元格),大小 = 0x0000000020000000(2 个单元格)
};
3. 继承规则
address-cells
和size-cells
是继承属性,子节点会默认使用父节点的值。- 如果子节点需要覆盖父节点的值,可以显式定义自己的
address-cells
和size-cells
。
示例:
soc {
#address-cells = <2>;
#size-cells = <1>;
i2c@1 {
#address-cells = <1>; // 覆盖父节点的 address-cells
#size-cells = <0>; // 覆盖父节点的 size-cells(表示大小字段不存在)
reg = <0x1>; // 地址 = 0x1(1 个单元格),无大小字段
};
};
4. reg
属性的格式
reg
属性的格式为:
reg = <address1 address2 ... size1 size2 ...>;
- 地址字段:由
address-cells
决定单元格数量。 - 大小字段:由
size-cells
决定单元格数量。
示例:
// 父节点设置:address-cells=2, size-cells=1
reg = <0x0 0x1000 0x100>; // 地址 = 0x00001000,大小 = 0x100
5. 典型应用场景
- 内存映射I/O(MMIO):
- 描述外设寄存器的基地址和范围。
- 例如:
reg = <0x1000 0x100>;
表示基地址0x1000
,范围0x100
字节。
- 内存区域:
- 描述系统内存的起始地址和大小。
- 例如:
reg = <0x0 0x80000000 0x0 0x20000000>;
表示内存起始地址0x80000000
,大小0x20000000
。
- 中断控制器:
- 描述中断控制器的寄存器地址。
6. 注意事项
- 一致性:父节点和子节点的
address-cells
/size-cells
必须一致,否则reg
属性解析会出错。 - 单位:设备树中的地址和大小通常以字节为单位,但具体含义由硬件决定。
- 64位地址:在 64 位系统中,地址可能拆分为高 32 位和低 32 位(如
reg = <0x0 0x1000 0x100>;
)。
总结
address-cells
和size-cells
是设备树中描述硬件资源地址和大小的关键属性。- 它们通过定义
reg
属性的单元格数量,确保内核能正确解析硬件资源的布局。 - 正确设置这些属性是设备树兼容性和硬件抽象化的基础。