linux 电池 驱动

99ANYc3cd6
预计阅读时长 18 分钟
位置: 首页 电池处理 正文
  1. 核心概念:ACPI (高级配置与电源接口)
  2. Linux 内核中的电池驱动架构
  3. 关键的数据结构:power_supply
  4. 用户空间如何获取电池信息
  5. 如何排查电池驱动问题

核心概念:ACPI (高级配置与电源接口)

现代笔记本电脑、服务器和台式机的电源管理(包括电池)都依赖于一个叫做 ACPI 的工业标准,ACPI 是一个开放标准,定义了操作系统与固件(BIOS/UEFI)之间的接口。

linux 电池 驱动
(图片来源网络,侵删)
  • 固件的作用:硬件(主板上的 PMIC - 电源管理集成电路、电池本身等)通过 ACPI 提供的“方法”(Methods)和“对象”(Objects)来报告其状态。
  • 驱动的作用:Linux 内核的 ACPI 子系统(drivers/acpi/)会解析这些 ACPI 表(如 BAT0, ACAD 等),并根据这些信息来与硬件交互,例如读取电量、计算剩余时间、控制充电等。

ACPI 是连接硬件固件和 Linux 操作系统的“语言”,而电池驱动就是“翻译官”,负责“说”这门语言。


Linux 内核中的电池驱动架构

Linux 内核的驱动架构是分层的,电池驱动也不例外,这种分层设计使得代码结构清晰,并且可以方便地支持不同的硬件。

电池驱动通常位于 drivers/power/supply/ 目录下,主要分为以下几个层次:

a) 平台层 / 硬件抽象层

这是最底层,直接与硬件寄存器或通过 I2C/SPI 等总线通信的驱动代码。

linux 电池 驱动
(图片来源网络,侵删)
  • 作用:负责最原始的数据读写,比如从电池管理芯片的寄存器中读取电压、电流、温度等原始值。
  • 例子
    • i2c-charger.c: 用于通过 I2C 总线与充电芯片通信。
    • max77693-charger.c: 针对特定芯片(如 Maxim MAX77693)的驱动。
    • 一些老式的或简单的电池驱动可能直接在这里实现所有逻辑。

b) 核心层 / power_supply

这是电池驱动的核心,位于 drivers/power/supply/ 下的核心文件(如 power_supply_core.c, power_supply_sysfs.c)。几乎所有现代的电池驱动最终都会通过这个框架来暴露信息

  • 作用
    1. 提供标准接口:定义了一套标准的属性(如 status, capacity, present, health 等),使得用户空间的应用程序(如 upower, acpi_call)可以用统一的方式访问不同品牌的电池。
    2. 管理电源状态:处理电源事件,如 AC 插入/拔出、电池电量变化等,并通知上层(如用户空间)。
    3. 提供 sysfs 接口:在 /sys/class/power_supply/ 目录下创建文件,将电池信息暴露给用户空间。

c) ACPI 子系统层

这是目前笔记本电池驱动最主流的实现方式。

  • 作用:ACPI 子系统解析 ACPI 表,找到电池相关的设备描述(_BIF - Battery Information, _BST - Battery Status, _BTP - Battery Trip Points 等)。
  • 实现drivers/acpi/battery.c 是一个“通用”的 ACPI 电池驱动,当内核发现一个符合 ACPI 规范的电池设备时,会自动加载这个驱动,这个驱动会调用 power_supply 核心层的接口来注册自己,并将从 ACPI 获取的数据填充进去。

分层总结ACPI 表 -> ACPI 电池驱动 -> power_supply 核心框架 -> /sys/class/power_supply/ -> 用户空间工具


关键的数据结构:power_supply

power_supply 是内核中表示一个电源供应源的抽象类,它可以是电池、交流适配器、USB 电源等,驱动开发者通过注册一个 power_supply 结构体来告诉内核自己是一个电源设备。

核心结构体struct power_supply

驱动程序需要填充这个结构体,最重要的部分是 desc (描述符) 和 properties (属性)。

  • struct power_supply_desc desc:

    • name: 电源设备的名称,如 BAT0, ACAD,这个名字会出现在 /sys/class/power_supply/ 目录下。
    • type: 电源类型,如 POWER_SUPPLY_TYPE_BATTERY, POWER_SUPPLY_TYPE_MAINS (交流电)。
    • get_property: 这是一个函数指针,是驱动的核心,当用户空间(如通过 cat /sys/class/power_supply/BAT0/capacity)请求某个属性时,内核会调用这个函数,驱动程序负责从硬件或 ACPI 数据中获取该值并返回。
  • enum power_supply_property properties[]:

    • 这是一个属性列表,定义了该电源设备支持哪些属性,
      • POWER_SUPPLY_PROP_STATUS: 电池状态 (Unknown, Charging, Discharging, Not charging, Full)。
      • POWER_SUPPLY_PROP_CAPACITY: 当前电量百分比 (0-100)。
      • POWER_SUPPLY_PROP_PRESENT: 电池是否物理存在。
      • POWER_SUPPLY_PROP_HEALTH: 电池健康状态 (Good, Overheat, Dead 等)。
      • POWER_SUPPLY_PROP_TECHNOLOGY: 电池技术 (NiMH, Li-ion, Li-poly 等)。
      • POWER_SUPPLY_PROP_VOLTAGE_NOW: 当前电压。
      • POWER_SUPPLY_PROP_CURRENT_NOW: 当前电流。
      • POWER_SUPPLY_PROP_CAPACITY_LEVEL: 电量等级 (Critical, Low, Normal, High, Full)。

用户空间如何获取电池信息

用户空间的应用程序通过以下几种主要方式与电池驱动交互:

a) /sys 文件系统 (最直接)

这是内核提供给用户空间的标准化接口,所有电池信息都在这里。

# 查看所有注册的电源设备
ls /sys/class/power_supply/
# 输出可能类似于: AC ADP1 BAT0
# 查看 BAT0 电池的信息
ls /sys/class/power_supply/BAT0/
# 输出: capacity, capacity_level, current_now, health, present, status, type, voltage_now, ...
# 读取当前电量
cat /sys/class/power_supply/BAT0/capacity
# 输出: 85
# 查看充电状态
cat /sys/class/power_supply/BAT0/status
# 输出: Discharging

b) upower 工具 (最常用)

upower 是一个系统守护进程,它聚合了来自 /sys 的电源信息,并为其他应用程序(如桌面环境、GNOME Power Manager)提供一个统一的 D-Bus 接口。

# 查看 upower 知道的所有电源设备
upower -e
# 输出: /org/freedesktop/UPower/devices/line_power_AC0 /org/freedesktop/UPower/devices/battery_BAT0
# 查看电池详细信息
upower -i /org/freedesktop/UPower/devices/battery_BAT0

c) acpi 命令行工具

acpi 命令是一个更底层的工具,它直接读取 ACPI 信息,有时可以提供 power_supply 没有或显示不友好的信息。

acpi -V
# 输出: Battery 0: 85%, Discharging, 02:45:17 remaining

如何排查电池驱动问题

如果遇到电池信息不显示、信息不准、无法充电等问题,可以按照以下步骤排查:

  1. 检查内核是否加载了驱动

    # 查看内核日志,看有没有电池相关的信息
    dmesg | grep -i "battery\|power_supply\|ACPI"
    # 如果看到类似 "battery: ACPI battery driver registered" 的信息,说明驱动已加载。
  2. 检查 /sys 文件系统

    # 检查设备是否存在
    ls /sys/class/power_supply/
    # 检查关键文件是否有内容,而不是空文件
    cat /sys/class/power_supply/BAT0/status
    # 如果文件存在但读取为空或报错,可能是驱动没有正确获取硬件信息。
  3. 检查内核配置: 确保内核编译时启用了相关选项:

    # 查看当前内核配置
    zcat /proc/config.gz | grep -E "CONFIG_ACPI|CONFIG_POWER_SUPPLY"
    # 应该看到 CONFIG_ACPI=y 和 CONFIG_POWER_SUPPLY=y
  4. 检查硬件和固件

    • BIOS/UEFI 更新:有时电池问题是由于 BIOS/UEFI 的 Bug 引起的,尝试更新到最新版本。
    • 硬件问题:如果所有驱动和软件都正常,但电池就是无法识别或充电,可能是电池本身或主板上的充电电路硬件损坏。
  5. 使用 acpi_call (高级): 这是一个非常有用的工具,允许你在用户空间直接调用 ACPI 方法,可以用来测试 ACPI 表是否工作正常,或者进行一些高级的电源管理操作。

    # 安装 acpi_call
    sudo apt-get install acpi-call-dkms  # for Debian/Ubuntu
    # 或者从源码编译
    # 调用一个方法(示例,具体方法名因主板而异)
    sudo modprobe acpi_call
    echo '\_SB.PCI0.LPCB.EC0.V0B0' | sudo tee /proc/acpi/call
    # 这需要你知道具体的 ACPI 方法路径,通常需要查阅硬件文档或社区资料。

Linux 电池驱动是一个成熟且标准化的子系统,其核心思想是:

  • 硬件通过 ACPI 提供信息
  • 内核的 ACPI 子系统解析这些信息
  • 驱动通过 power_supply 框架将信息标准化
  • 用户空间通过 /sys, upower 等接口访问这些信息

对于大多数用户来说,你不需要关心底层驱动细节,只需知道如何通过 upower/sys 来查看和管理电池即可,但对于开发者来说,理解这个分层架构对于编写、调试或移植电池驱动至关重要。

-- 展开阅读全文 --
头像
创维55E70RG三无故障,何因?
« 上一篇 昨天
创维波轮洗衣机故障代码E4是什么意思?
下一篇 » 昨天

相关文章

取消
微信二维码
支付宝二维码

目录[+]