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_”。
  • 路径不区分大小写,但推荐使用大写字母与数字组合。
  • 同一父级下不允许出现同名对象。
ACPI命名空间树形结构示例 \ (根) \_SB_ \_PR_ \_TZ_ PCI0 I2C0 GPIO I2C1 UART TPM0 ALS0 CPU0 CPU1 TZ00 每个节点对应一个4字符名称,路径从根“\”开始,层级间用“.”分隔,形成唯一设备标识

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等全局对象定义系统睡眠状态。
命名空间层级与电源管理粒度 系统级:\_S0 (Working)、\_S3 (Suspend-to-RAM)、\_S4 (Hibernate)、\_S5 (Soft Off) 作用域级:\_SB_ (系统总线)、\_PR_ (处理器)、\_TZ_ (热区) 设备级:PCI0、I2C1、TPM0、GPIO0 — 独立 _PS0/_PS3 控制 电源管理粒度从系统级到设备级逐层细化,命名空间层级越深,电源控制越精细

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的电源轨。