软件定义的电池
注意
一些信息与预发布产品相关,在商业发行之前可能发生实质性修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。
介绍
本主题旨在介绍软件定义的电池 (SDB)、描述 Windows SDB 体系结构并详细说明该功能的 Windows API 和 DDI 协议。
本专题首先介绍假设双电池系统的简单老化平衡 SDB 算法。 随后是实现 SDB 算法所需的体系结构布局和 API 协议。
命名法
BattC - 电池类驱动程序
CAD - 充电仲裁驱动程序 (CAD) 是一款 Microsoft 驱动程序,用于仲裁 USB 旧版、USB Type-C 和无线充电源之间的功率。
冷插拔电池 - 不能从系统中拆卸的电池,否则会有停电或完全断电的风险
循环计数 - 电池经历的完全充放电循环次数,如 ACPI 规范所述
热插拔电池 - 可在系统运行时安全拆卸的电池,没有任何停电风险
HPMI - 硬件电源管理器接口
非热插拔电池 - 系统中安装了一个或多个冷插拔和非插拔电池
非插拔电池 - 设计上不允许最终用户拆卸的电池
SDB 概述
有关软件定义电池的 MSR 研究论文可在此处查阅:https://www.microsoft.com/research/wp-content/uploads/2016/02/multibattery_sosp2015.pdf。
本专题重述了本文所述的部分观点,并提出了将基于软件的电池老化平衡功能应用于笔记本电脑和其他移动设备的设想。
想象有一个双电池系统。 其中一块电池是不可拆卸电池,位于 SOC 旁边,我们称之为内部电池。 另一块电池是热插拔电池,位于可拆卸键盘旁边,我们称之为外部电池。
多电池系统
由于键盘在一段时间内处于连接-分离状态,这就迫使两块电池的老化程度各不相同。 这就为采用 SDB 简单老化平衡算法平衡电池寿命和延长系统可用性创造了条件。
简单老化平衡 SDB 算法
这种算法被称为简单老化平衡,因为它试图平衡电池老化。 简单老化平衡算法会使系统优先选择老化程度最低的电池进行放电。 循环次数越少的电池,不仅容量越大,而且供电效率也越高。 从而它可以延长系统使用电池的时间。
简单老化平衡 SDB 算法
如上流程图中的决策框 (2) 所示,简单老化平衡算法的核心理念是使用累积电池循环次数最少的电池。 本示例中的假设系统可专用内部或外部电池。 然而,并非所有系统都是如此。 其他系统可能不那么灵活,或者对电池的使用存在电气限制。 在这种情况下,算法希望能尽最大努力实现老化平衡。 例如,请考虑如下情况。
系统无法完全依靠外部电池供电(可能是因为外部电池只是设计为辅助电源)。 此系统可通过在上述流程图中的流程块 (A) 中同时对内部和外部电池放电来实现简单老化算法。
要求只要有外部电池就必须使用的系统(可能是因为保持可移动键盘通电需要额外耗电):这种系统可以通过在上述流程图中的流程块 (B) 中同时给内部和外部电池放电来实现简单老化平衡算法。
只有当内部和外部电池中的电量足以运行系统时,才可以使用简单老化平衡算法,决策框 (1) 在上述流程图中描述了这一条件检查。 例如(再次回到假设系统),如果外部电池没有电量,就不存在电池老化平衡的问题,决策框 (1) 的结果将是“否”分支。
除了内部或外部电池没电时,OEM 还可以自由选择不采用简单老化平衡算法的限制条件。 例如,当出现以下情况时,OEM 可以选择不执行任何老化平衡:
- SOC/处理器以高性能模式运行
- 系统热不稳定
当不使用简单老化平衡算法时(由于上述一种或多种情况),逻辑将恢复到 OEM 专有的电池使用策略,如上流程图中流程框 (3) 所示。 如果不支持 SDB,流程框 (3) 将显示 OEM 将执行的逻辑。
调整 SDB 算法以便与热插拔电池配合使用
简单老化平衡 SDB 算法会尝试使用最健康的电池,虽然这种策略能很好地提高电池的长期寿命,但它可能会严重影响系统的短期可用性,如以下场景所述。
在上述双电池系统中,请考虑以下情况:
用户预期会长时间使用系统,直至内部和外部电池电量耗尽。
与内部电池相比,外部电池的老化程度更高。
在此系统上使用简单老化平衡算法时,它会首先尝试耗尽内部电池中存储的电量(基于上述条件 #1 和 #2)。 当用户在使用一段时间后决定拆下外部电池时,会导致糟糕的用户体验,因为一旦拆下外部电池,可供使用的电池容量就会急剧下降,因为内部电池会被用完。
在非 SDB 系统中,一般不会出现这种问题,因为在大多数情况下,外部电池在内部电池投入使用之前就已耗尽。
因此,我们希望在可能出现上述情况时,有选择地禁用简单老化平衡算法。
总之,当用户需要在拆卸外部电池的情况下长时间使用系统时,最好禁用 SDB 算法,恢复使用 OEM 电池使用策略(通常优先使用外部电池)。
Windows 会计算电池的可用性,并生成“保留非热插拔电池”提示。 当 SDB 算法使用该提示时,如下流程图中的决策框 (X) 所示。
适用于热插拔电池的简单老化平衡 SDB 算法
在固件中实现 SDB 算法
本部分描述了在系统固件中实现的全部电池放电控制逻辑。 这是在上述电池老化平衡逻辑的基础上,演示如何将现有的多电池放电逻辑(标记在 (Y) 块中)与之结合。
请注意,这并不是 OEM 应该如何实施 SDB 算法的规定,而是本部分中描述的用于说明 SDB 行为的简单、假设的多电池设备的综合示例。
简单老化平衡 SDB 算法的完整固件实现
功率堆栈体系结构
本部分介绍参与电源堆栈的所有组件的布局及其相互之间的相对关系。
电池微型端口
电池微型端口接口保持不变。
SDB 接口不会影响 OEM 依赖 ACPI/CmBatt 机制或开发其专有微型端口的意愿。
Windows 会将所有 IOCTL_BATTERY_SET_INFORMATION 命令转发给系统中列举的所有电池设备。
HPMI
硬件电源管理器接口 (HPMI) 是电源堆栈中引入的一个新组件。
HPMI 是由 OEM/设备制造商开发和拥有的驱动程序。
HPMI 对基础硬件配置和状态了如指掌,并能访问系统固件。
为实现 SDB 功能,HPMI 驱动程序将:
- 自动向 Windows 注册。
- 播发 SDB 支持。
- 使用 Windows 提供的 SDB 控制参数。
支持 SDB 的多电池系统今后必须实现 HPMI 接口。 HPMI API 协议是实现多电池系统的新标准。
根据计划,HPMI 将在未来进行更新,以支持其他充电、放电和充电管理功能。
驱动程序特性
一个系统中的 HPMI 驱动程序实例不得超过一个。 HPMI 可作为用户模式或内核模式驱动程序来实现。
安装
HPMI 既可以表现为 ACPI 设备,也可以由其他 OEM 服务/驱动程序根枚举,由 OEM 自行决定。
SDB 算法的实现
下图举了两个例子,说明如果固件组件已经承载了大部分电池控制逻辑,如何实现 SDB 算法。
HPMI 实现 SDB 算法
HPMI 可以选择实现 SDB 算法,这将要求 HPMI 向固件发送充电/放电提示。
固件实现 SDB 算法
另外,HPMI 也可以充当转发器,将 Windows 电池利用率提示转发给实施 SDB 算法的固件,如上图所示。 建议使用这种模式的原因如下:
实现 SDB 算法所需的信息是现成的 - 无需将这些信息传递给 HPMI
SDB 算法是对多电池系统中已实现的放电逻辑的扩展
有关如何实施 SDB 算法的完整流程图模型,请参阅在固件中实施 SDB 算法。
接口定义
为 HPMI 设备引入了新的设备接口类 GUID。 HPMI 设备必须标识自己实现了设备接口类。 有关详细信息,请参阅 WDK 中的使用设备接口。
Windows 使用设备到达通知来查询和配置 HPMI 设备。
//
// HPMI Device Interface Class.
//
// {DEDAE202-1D20-4C40-A6F3-1897E319D54F}
DEFINE_GUID(GUID_DEVINTERFACE_HPMI,
0xdedae202, 0x1d20, 0x4c40, 0xa6, 0xf3, 0x18, 0x97, 0xe3, 0x19, 0xd5, 0x4f);
HPMI 应能同时为多个 IOCTL 调用提供服务。
请注意,设备索引应设置为零。
功能发现
IOCTL_HPMI_QUERY_CAPABILITIES 用于发现 HPMI 支持的功能。 IOCTL_HPMI_QUERY_CAPABILITIES 是必需的 IOCTL。
发现新的 HPMI 驱动程序实例后,Windows 将向 HPMI 发出一次 IOCL。
//
// Query command sent to HPMI to query features supported by HPMI and Windows
// services requested by HPMI.
//
// This IOCTL may be issued multiple times, HPMI must respond with same
// information in HPMI_QUERY_CAPABILITIES_RESPONSE, as a response to all
// subsequent IOCTL calls.
//
#define IOCTL_HPMI_QUERY_CAPABILITIES
CTL_CODE(FILE_DEVICE_BATTERY, 0x200,
METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//
// IOCTL_HPMI_QUERY_CAPABILITIES - Command.
//
typedef struct _HPMI_QUERY_CAPABILITIES {
//
// Set to HPMI_QUERY_CAPABILITIES_VERSION_1.
//
ULONG Version;
} HPMI_QUERY_CAPABILITIES, *PHPMI_QUERY_CAPABILITIES;
#define HPMI_QUERY_CAPABILITIES_VERSION_1
(1)
#define HPMI_QUERY_CAPABILITIES_SIZEOF_VERSION_1
sizeof(HPMI_QUERY_CAPABILITIES)
//
// IOCTL_HPMI_QUERY_CAPABILITIES - Response.
//
#define HPMI_REQUEST_SERVICE_NONE
(0x00000000) // No Windows services is requested.
#define HPMI_REQUEST_SERVICE_BATTERY_UTILIZATION_HINTS
(0x00000001) // Battery utilization hints requested from Windows.
#define HPMI_CAPABILITY_NOT_SUPPORTED
(0x00000000) // HPMI supports no capabilities.
#define HPMI_CAPABILITY_SDB_OEM_SIMPLE_AGE_BALANCING
(0x00000001) // OEM device specific age balancing SDB support
typedef struct _HPMI_QUERY_CAPABILITIES_RESPONSE {
//
// Set to HPMI_QUERY_CAPABILITIES_RESPONSE_VERSION_1.
//
ULONG Version;
//
命令格式
Windows 使用 HPMI_QUERY_CAPABILITIES 发布此 IOCTL。
版本设置为 HPMI_QUERY_CAPABILITIES_VERSION_1。
响应格式
HPMI 必须返回 STATUS_SUCCESS 代码。
HPMI 通过在 HPMI_QUERY_CAPABILITIES_RESPONSE 结构中设置以下值来做出响应:
- 版本设置为 HPMI_QUERY_CAPABILITIES_RESPONSE_VERSION_1
- RequestService 设置为 HPMI_REQUEST_SERVICE_BATTERY_UTILIZATION_HINTS,以确保 HPMI 驱动程序收到 IOCTL_HPMI_BATTERY_UTILIZATION_HINT。
- SdbCapabilities 设置为 HPMI_CAPABILITY_SDB_OEM_SIMPLE_AGE_BALANCING,表示支持电池老化平衡。
电池利用率
Windows 向 HPMI 发出 IOCTL_HPMI_BATTERY_UTILIZATION_HINT 以提供最新的电池利用率提示。 IOCTL_HPMI_BATTERY_UTILIZATION_HINT 是必需的 IOCTL。
HPMI 可利用调整 SDB 算法以便与热插拔电池配合使用中所述的 PreserveNonHotSwappableBatteries 提示来保护内部电池。
//
// Set command sent to HPMI to provide battery utilization hints.
//
// This IOCTL may be issued multiple times if HPMI requests
// HPMI_REQUEST_SERVICE_BATTERY_UTILIZATION_HINTS service.
//
#define IOCTL_HPMI_BATTERY_UTILIZATION_HINT
CTL_CODE(FILE_DEVICE_BATTERY, 0x201,
METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//
// Boolean type value.
//
typedef enum _HPMI_HINT_BOOL {
// No data is available.
HpmiBoolUnavailable = 0,
// Condition is asserted to be false.
HpmiBoolFalse,
// Condition is asserted to be true.
HpmiBoolTrue,
// Value not used.
HpmiBoolMax
} HPMI_HINT_BOOL, *PHPMI_HINT_BOOL;
//
// IOCTL_HPMI_BATTERY_UTILIZATION_HINT - Command.
//
typedef struct _HPMI_BATTERY_UTILIZATION_HINT {
//
// Set to HPMI_BATTERY_UTILIZATION_HINT_VERSION_1.
//
ULONG Version;
//
// This hint indicates if the OEM Battery Manager should attempt to save as
// much charge as possible in the non-hot swappable batteries (i.e. the
// batteries are generally referred to as "internal batteries", these
// batteries cannot be removed while system is operational).
//
// Interpretation of values:
// - HpmiBoolUnavailable:
// Battery utilization hint is unavailable at the moment.
// - HpmiBoolFalse:
// It is not necessary to preserve charge in the internal batteries
// at the moment.
// - HpmiBoolTrue:
// Every attempt should be made to save as much charge as possible in
// the internal batteries.
//
HPMI_HINT_BOOL PreserveNonHotSwappableBatteries;
} HPMI_BATTERY_UTILIZATION_HINT, *PHPMI_BATTERY_UTILIZATION_HINT;
#define HPMI_BATTERY_UTILIZATION_HINT_VERSION_1
(1)
#define HPMI_BATTERY_UTILIZATION_HINT_SIZEOF_VERSION_1
sizeof(HPMI_BATTERY_UTILIZATION_HINT)
命令格式
Windows 使用 HPMI_BATTERY_UTILIZATION_HINT 发布此 IOCTL。 版本设置为 HPMI_BATTERY_UTILIZATION_HINT_VERSION_1。
PreserveNonHotSwappableBatteries 可设置为下列值之一:
- HpmiBoolUnavailable:在无法提供电池利用率提示时设置。 作为回应,HPMI/Fimware 一般应采用事实上的放电策略。
- HpmiBoolFalse:在 Windows 确定电池老化平衡的合适时间时设置。
- HpmiBoolTrue:当 Windows 确定需要保存内部电池中存储的能量时设置。
响应格式
HPMI 必须返回 STATUS_SUCCESS 代码。
响应中不返回数据。
示例接口协议
请参阅 HMPI.h 以获取此处所述接口定义的完整(示例)API 协议。
注意
本文档内容如有更改,恕不另行通知。