3. ACPI命名空间:设备路径命名规则、作用域与对象规范
ACPI命名空间(Namespace)是嵌入式设备电源管理与硬件拓扑描述的核心数据结构。它采用树形层次结构,将系统中的所有设备、电源资源、热区、处理器等抽象为命名对象。理解命名空间的构建规则、作用域划分与对象命名规范,是进行ACPI表编写、设备路径调试与电源集成优化的基础。
核心要点: ACPI命名空间本质上是一个由“作用域(Scope)”和“设备(Device)”节点组成的树,每个节点通过唯一的“绝对路径”标识。所有电源管理操作(如_PSC、_PS0、_PS3)都挂载在特定设备节点下。
3.1 命名空间树形结构与绝对路径
ACPI命名空间从根节点“\”开始,向下逐级展开。每个节点(对象)的名称由父级作用域和本地名称组合而成,形成类似文件系统的路径表示。路径分隔符为“\”或“.”,其中“\”表示绝对路径起始,“.”用于分隔作用域层级。
// 命名空间路径示例
\_SB_.PCI0.I2C1.TPM0 // 绝对路径:根 -> 系统总线 -> PCI0 -> I2C1 -> TPM设备
\_SB_.PCI0.GPIO0 // 绝对路径:根 -> 系统总线 -> PCI0 -> GPIO控制器
\_PR_.CPU0 // 绝对路径:根 -> 处理器作用域 -> CPU0
路径命名规则:
- 绝对路径以“\”开头,后跟作用域或设备名,层级间用“.”分隔。
- 每个名称段固定为4个字符(ASL编译器自动补齐下划线),例如“PCI0”实际存储为“PCI_”。
- 路径不区分大小写,但推荐使用大写字母与数字组合。
- 同一父级下不允许出现同名对象。
3.2 核心作用域:\_SB、\_PR、\_TZ 与 \_GPE
ACPI规范预定义了若干顶级作用域(Scope),用于组织不同类型的系统资源。嵌入式开发中最常接触的是以下四个作用域:
| 作用域名称 | 全称 | 包含内容 | 电源管理关联 |
|---|---|---|---|
| \_SB_ | System Bus | 所有系统总线设备:PCI、I2C、SPI、UART、GPIO、PMIC等 | 设备电源状态控制(_PS0/_PS3)、资源唤醒(_PRW) |
| \_PR_ | Processor | CPU核心对象,每个核心一个设备节点 | 处理器性能状态(_PPC)、C状态(_CST)、P状态(_PSS) |
| \_TZ_ | Thermal Zone | 热区对象,包含温度传感器、冷却设备、触发策略 | 热管理策略(_PSV/_HOT/_CRT)、风扇控制(_AL0) |
| \_GPE | General Purpose Events | 通用事件块,定义SCI中断路由与事件处理 | 唤醒事件路由、电源按钮事件、外设热插拔 |
常见误区: 初学者常将\_SB_理解为“南桥”或“芯片组”,实际上\_SB_是“系统总线”的抽象,所有挂载在总线上的设备(包括PCIe Root Complex、I2C控制器、SPI控制器等)都应放在\_SB_下。不要将\_SB_与具体的硬件总线混为一谈。
3.3 ACPI对象命名规范
ACPI对象命名遵循严格的4字符规则,同时区分“预定义对象”与“用户定义对象”。预定义对象以下划线“_”开头,由ACPI规范定义其含义与行为;用户定义对象由OEM或开发者自行命名,不能以下划线开头。
3.3.1 预定义对象(Method & Control Method)
预定义对象是ACPI规范中固定名称的方法或控制方法,用于向OSPM(操作系统电源管理)暴露设备能力。以下为嵌入式设备中最常用的预定义对象:
| 对象名称 | 类型 | 功能描述 | 返回值/参数 |
|---|---|---|---|
| _HID | Method | 硬件标识符,返回PNP ID或ACPI ID | 返回字符串,如"ACPI000E" |
| _CID | Method | 兼容标识符列表,用于驱动匹配 | 返回包(Package) |
| _STA | Method | 设备状态,返回位掩码指示设备是否存在、使能、显示等 | 返回整数(0x0F表示全功能) |
| _CRS | Method | 当前资源设置,描述设备使用的IO、IRQ、Memory等 | 返回Buffer(Resource Template) |
| _PS0 | Method | 将设备从D3hot/D3cold恢复到D0(全功率) | 无参数,执行电源序列 |
| _PS3 | Method | 将设备从D0切换到D3hot(低功耗) | 无参数,执行断电序列 |
| _PRW | Method | 电源唤醒能力,定义设备支持的唤醒事件与GPE关联 | 返回包[GPE编号, 最低唤醒电源状态] |
3.3.2 用户定义对象命名规则
用户定义对象(如设备实例、自定义方法、数据包)必须遵循以下规范:
- 名称长度: 固定4个字符,不足部分用下划线“_”补齐(例如“TPM0”实际存储为“TPM_”)。
- 首字符: 不能以下划线开头(下划线开头为ACPI规范保留)。
- 允许字符: 大写字母A-Z、数字0-9、下划线“_”。
- 命名建议: 使用设备类型缩写+序号,如“I2C0”、“UART1”、“GPIO0”、“PMIC0”。
- 避免冲突: 同一作用域内名称必须唯一,不能与预定义对象重名。
// 用户定义对象命名示例
Device (TPM0) { // 有效:TPM0 -> TPM_
Name (_HID, "MSFT0101") // 预定义对象,以下划线开头
Name (MYID, 0x1234) // 用户定义数据对象,不能以下划线开头
Method (INIT, 0) { // 用户定义方法,不能以下划线开头
// 自定义初始化序列
}
}
// 错误命名示例
Device (_TPM) { } // 错误:以下划线开头,与预定义保留冲突
Device (TPM) { } // 错误:名称不足4字符,ASL编译器报错
Device (TPM00) { } // 错误:名称超过4字符,ASL编译器截断或报错
3.4 作用域嵌套与设备路径调试
在实际嵌入式项目中,ACPI命名空间的嵌套深度直接影响设备路径的解析与调试效率。以下是一个典型的嵌入式设备命名空间布局:
Scope (\_SB_) {
Device (PCI0) { // PCIe Root Complex
Name (_HID, "PNP0A08") // PCI Express Root Bridge
Device (I2C1) { // I2C控制器 #1
Name (_HID, "AMDI0010") // AMD I2C控制器
Name (_CRS, ResourceTemplate() {
Memory32Fixed (ReadWrite, 0xFEDC0000, 0x1000)
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
})
Device (TPM0) { // TPM安全芯片,挂载在I2C1下
Name (_HID, "MSFT0101")
Name (_CRS, ResourceTemplate() {
I2cSerialBus (0x50, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB_.PCI0.I2C1", 0, ResourceConsumer)
})
Method (_PS0, 0) { // 电源恢复序列
// 使能TPM电源轨
Store (0x01, \_SB_.GPIO0.PWR_EN)
Sleep (10)
}
Method (_PS3, 0) { // 电源关闭序列
Store (0x00, \_SB_.GPIO0.PWR_EN)
}
}
}
}
}
调试技巧: 在Linux系统中,可以通过以下命令查看ACPI命名空间树:
# 查看完整命名空间树
cat /sys/firmware/acpi/tables/DSDT | xxd | head -20
# 或使用acpidump工具
acpidump -o dsdt.dat
iasl -d dsdt.dat
# 查看设备路径与电源状态
ls -la /sys/bus/acpi/devices/
cat /sys/bus/acpi/devices/TPM0:00/power_state
3.5 命名空间与电源状态的关系
ACPI命名空间的结构直接影响电源管理的粒度。每个设备节点可以独立定义电源控制方法(_PS0/_PS3),而作用域层级决定了电源管理的范围:
- 设备级电源管理: 每个Device节点独立控制自己的电源状态,适用于外设、传感器等。
- 总线级电源管理: 在Scope或Device内定义_PSC(电源状态能力),可批量控制子设备。
- 系统级电源状态: 通过\_S0、\_S3、\_S4、\_S5等全局对象定义系统睡眠状态。
3.6 实战案例:嵌入式设备命名空间设计
以一款基于ARM架构的嵌入式IoT网关为例,其ACPI命名空间设计如下:
| 作用域/设备 | 路径 | 电源控制方法 | 说明 |
|---|---|---|---|
| \_SB_ | \_SB_ | — | 系统总线根作用域 |
| PCI0 | \_SB_.PCI0 | _PS0/_PS3 | PCIe Root Complex,控制PCIe总线电源 |
| I2C0 | \_SB_.I2C0 | _PS0/_PS3 | I2C控制器#0,挂载传感器 |
| GPIO0 | \_SB_.GPIO0 | _PS0/_PS3 | GPIO控制器,用于电源轨使能 |
| PMIC0 | \_SB_.PMIC0 | _PS0/_PS3 | 电源管理IC,控制系统电源轨 |
| TPM0 | \_SB_.PCI0.I2C1.TPM0 | _PS0/_PS3 | 安全芯片,深度嵌套在I2C1下 |
| ALS0 | \_SB_.PCI0.I2C1.ALS0 | _PS0/_PS3 | 环境光传感器,与TPM共享I2C总线 |
设计建议: 在嵌入式设备中,建议将电源控制相关的GPIO(如电源轨使能、复位信号)抽象为独立的GPIO设备节点,放在\_SB_下。这样所有设备都可以通过绝对路径引用这些GPIO,避免命名空间耦合。例如:\_SB_.GPIO0.PWR_EN 用于控制TPM的电源轨。