ACR Detect 模块分析
1. 模块定位与核心价值
acr_detect 是华为充电管理系统中的 ACR(Alternating Current Resistance,交流阻抗)异常检测模块,用于监测电池的内阻状态,判断电池健康程度。
核心价值:
- 🔋 电池健康监测:通过测量 ACR 值评估电池老化程度
- 🛡️ 异常预警:超过阈值时触发 DMD/FMD 报告
- 🏭 产线检测:工厂模式下支持运行时检测
- 📊 数据采集:集成华为大数据平台,支持 FMD 上报
2. 系统架构
2.1 整体架构
┌─────────────────────────────────────────────────────────────┐
│ 用户空间/产线工具 │
└──────────────────────┬──────────────────────────────────────┘
│ sysfs
┌────────────┴────────────┐
│ │
▼ ▼
acr_rt_support acr_rt_detect
(是否支持) (触发检测)
│ │
└────────────┬────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ acr_detect.c (核心逻辑) │
├─────────────────────────────────────────────────────────────┤
│ • 启动检测工作队列 │
│ • 设置最大输入电流 │
│ • 等待电流降至 <10mA │
│ • 调用平台接口计算 ACR │
│ • 比对阈值并上报异常 │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Platform API │ │ DMD Report │ │ FMD Report │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ start_acr_ │ │ POWER_DSM_ │ │ Data Acqu- │
│ calc() │ │ BATTERY │ │ isition │
│ │ │ │ │ System │
│ get_acr_ │ │ ERROR_BATT_ │ │ │
│ resistance()│ │ ACR_OVER_ │ │ Item ID: │
│ │ │ THRESHOLD │ │ 703023001 │
└──────────────┘ └──────────────┘ └──────────────┘2.2 ACR 检测原理
ACR(交流内阻)定义:
- 反映电池在交流条件下的阻抗特性
- 随着电池老化,ACR 值会逐渐增大
- 正常范围:40-90mΩ(可配置)
测量条件:
- 静态电流:电池电流 < 10mA(接近空载状态)
- 充电模式:设置最大输入电流后等待稳定
- 测量时长:1000ms 计算时间
3. 核心数据结构
3.1 设备结构
c
struct acr_det_dev {
struct device *dev; // 设备指针
struct delayed_work rt_work; // 延迟工作队列(运行时检测)
int rt_run; // 运行状态(0=未运行, 1=运行中)
u32 rt_support; // 是否支持运行时检测
int rt_status; // 检测状态(初始化/失败/成功)
int rt_threshold; // ACR 阈值(单位:mΩ)
u32 rt_fmd_min; // FMD 最小阈值(默认 40mΩ)
u32 rt_fmd_max; // FMD 最大阈值(默认 90mΩ)
};3.2 检测状态
c
enum acr_det_status_type {
ACR_DET_STATUS_INIT = 0, // 初始状态
ACR_DET_STATUS_FAIL, // 检测失败
ACR_DET_STATUS_SUCC, // 检测成功
};3.3 运行状态
c
#define ACR_DET_NOT_RUNNING 0 // 未运行
#define ACR_DET_RUNNING 1 // 运行中3.4 配置参数
c
#define ACR_DET_RETRY_TIMES 50 // 最大重试次数
#define ACR_DET_MIN_CURRENT 10 // 最小电流阈值(10mA)
#define ACR_DET_DEFAULT_THLD 100 // 默认阈值(100mΩ)
#define ACR_DET_DEFAULT_MIN_FMD 40 // FMD 最小值(40mΩ)
#define ACR_DET_DEFAULT_MAX_FMD 90 // FMD 最大值(90mΩ)4. 核心流程实现
4.1 完整检测流程
┌─────────────────────────────────────────────────────────────┐
│ 1. 用户空间触发 │
│ echo 1 > /sys/class/hw_power/charger/acr/acr_rt_detect │
└────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 检查前置条件 │
│ • rt_support == 1 (功能使能) │
│ • factory_mode (工厂模式) │
│ • rt_run == NOT_RUNNING (未在运行) │
└────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 调度延迟工作队列 │
│ schedule_delayed_work(&rt_work, 0) │
└────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. acr_det_rt_work() 执行 │
│ rt_run = RUNNING │
│ ↓ │
│ power_platform_set_max_input_current() │
│ (设置最大输入电流,准备充电环境) │
└────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. 等待电流稳定(最多重试 50 次) │
│ for (i = 0; i < 50; i++) { │
│ ichg = get_battery_current() │
│ if (abs(ichg) < 10mA) │
│ break; // 电流足够小,可以测量 │
│ msleep(100); // 等待 100ms │
│ } │
└────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 6. ACR 测量序列 │
│ ① power_platform_start_acr_calc() │
│ (启动 ACR 计算) │
│ ② msleep(1000) │
│ (等待 1 秒,完成计算) │
│ ③ power_platform_get_acr_resistance(&acr_value) │
│ (读取 ACR 值) │
└────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 7. 结果上报 │
│ ① acr_det_fmd_report(acr_value) │
│ (FMD 数据采集上报) │
│ ② msleep(50) │
│ (等待 DSM client 释放) │
│ ③ if (acr_value > threshold) │
│ acr_det_dmd_report(acr_value) │
│ (超阈值则 DMD 异常上报) │
└────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 8. 更新状态 │
│ rt_status = SUCC / FAIL │
│ rt_run = NOT_RUNNING │
└─────────────────────────────────────────────────────────────┘4.2 ACR 测量核心代码
c
static int acr_det_start_detect(struct acr_det_dev *l_dev)
{
int ret;
int acr_value = 0;
/* 步骤 1: 启动 ACR 计算 */
power_platform_start_acr_calc();
/* 步骤 2: 等待 1000ms,让硬件完成计算 */
msleep(1000);
/* 步骤 3: 读取 ACR 阻抗值 */
ret = power_platform_get_acr_resistance(&acr_value);
if (ret == 0) {
hwlog_info("acr:%d, threshold:%d\n", acr_value, l_dev->rt_threshold);
/* 步骤 4: FMD 上报(数据采集) */
acr_det_fmd_report(l_dev, acr_value);
/* 步骤 5: 等待 50ms,避免 DSM client 冲突 */
msleep(50);
/* 步骤 6: 超阈值时 DMD 告警上报 */
if (acr_value > l_dev->rt_threshold)
acr_det_dmd_report(acr_value);
}
return ret;
}4.3 电流稳定等待逻辑
c
static void acr_det_rt_work(struct work_struct *work)
{
struct acr_det_dev *l_dev = g_acr_det_dev;
int i;
int ichg;
l_dev->rt_run = ACR_DET_RUNNING;
/* 设置最大输入电流 */
if (power_platform_set_max_input_current())
goto detect_fail;
/* 等待电流降至 < 10mA(最多重试 50 次,共 5 秒)*/
for (i = 0; i < ACR_DET_RETRY_TIMES; i++) {
ichg = -power_platform_get_battery_current();
hwlog_info("i:%d, ichg:%d\n", i, ichg);
if (abs(ichg) < ACR_DET_MIN_CURRENT) {
/* 电流足够小,开始测量 */
if (acr_det_start_detect(l_dev) == 0) {
l_dev->rt_status = ACR_DET_STATUS_SUCC;
l_dev->rt_run = ACR_DET_NOT_RUNNING;
hwlog_info("acr detect succ\n");
return;
}
goto detect_fail;
}
/* 等待 100ms 后重试 */
msleep(100);
}
detect_fail:
l_dev->rt_status = ACR_DET_STATUS_FAIL;
l_dev->rt_run = ACR_DET_NOT_RUNNING;
hwlog_err("acr detect fail\n");
}等待逻辑图示:
电流 (mA)
│
│ 1000 ┼──────┐
│ │ │
│ 500 │ │
│ │ └──┐
│ 100 │ │
│ │ └───┐
│ 10 │ └────────────── (达到阈值,开始测量)
│ 0 ┼─────────────────────────►
0ms 100ms 200ms 300ms ... 5000ms
└──┬──┘ └──┬──┘ └──┬──┘
重试1 重试2 重试3 (最多 50 次)5. 数据上报机制
5.1 FMD 上报(数据采集)
FMD(Fault Management Data): 华为数据采集系统,用于产品质量分析
c
static void acr_det_fmd_report(struct acr_det_dev *l_dev, int acr_val)
{
struct message *acr_msg = NULL;
acr_msg = kzalloc(sizeof(*acr_msg), GFP_KERNEL);
if (!acr_msg)
return;
/* 填充消息头 */
acr_msg->version = ACR_DET_DEFAULT_VERSION; // 版本号:1
acr_msg->data_source = DATA_FROM_KERNEL; // 数据来源:内核
acr_msg->num_events = 1; // 事件数量:1
/* 填充事件信息 */
acr_msg->events[0].error_code = 0;
acr_msg->events[0].item_id = ACR_DET_ITEM_ID; // 703023001
acr_msg->events[0].cycle = 0;
/* 固定字段 */
memcpy(acr_msg->events[0].station, "NA", ...);
memcpy(acr_msg->events[0].bsn, "NA", ...);
memcpy(acr_msg->events[0].time, "NA", ...);
memcpy(acr_msg->events[0].device_name, "battery", ...);
memcpy(acr_msg->events[0].test_name, "BATT_ACR_VAL", ...);
/* 阈值信息 */
snprintf(acr_msg->events[0].min_threshold, MAX_VAL_LEN,
"%u", l_dev->rt_fmd_min); // 40
snprintf(acr_msg->events[0].max_threshold, MAX_VAL_LEN,
"%u", l_dev->rt_fmd_max); // 90
/* 测试结果 */
if (acr_val > l_dev->rt_threshold)
memcpy(acr_msg->events[0].result, "fail", ...);
else
memcpy(acr_msg->events[0].result, "pass", ...);
/* 测量值 */
snprintf(acr_msg->events[0].value, MAX_VAL_LEN, "%d", acr_val);
/* 电池信息 */
memcpy(acr_msg->events[0].firmware, batt_brand, MAX_FIRMWARE_LEN);
snprintf(acr_msg->events[0].description, MAX_DESCRIPTION_LEN,
"batt_volt:%dmV, batt_temp:%d", batt_volt, batt_temp);
/* 上报到数据采集平台 */
power_dsm_report_fmd(POWER_DSM_BATTERY,
POWER_DSM_DA_BATTERY_ACR_ERROR_NO, acr_msg);
kfree(acr_msg);
}FMD 数据格式:
| 字段 | 值 | 说明 |
|---|---|---|
| item_id | 703023001 | ACR 检测项 ID |
| device_name | battery | 设备名称 |
| test_name | BATT_ACR_VAL | 测试名称 |
| min_threshold | 40 | 最小阈值(mΩ) |
| max_threshold | 90 | 最大阈值(mΩ) |
| result | pass/fail | 测试结果 |
| value | 实测值 | ACR 测量值(mΩ) |
| firmware | 电池品牌 | 如 "ATL", "SUNWODA" |
| description | 上下文信息 | 电压、温度等 |
5.2 DMD 上报(异常告警)
DMD(Device Monitor and Diagnosis): 设备监控与诊断系统
c
static void acr_det_dmd_report(int acr_val)
{
char buf[POWER_DSM_BUF_SIZE_0128] = { 0 };
/* 构造异常信息 */
snprintf(buf, POWER_DSM_BUF_SIZE_0128 - 1,
"brand:%s, volt:%d, curr:%d, soc:%d, temp:%d, acr:%d\n",
power_supply_app_get_bat_brand(), // 电池品牌
power_supply_app_get_bat_voltage_now(), // 电池电压(mV)
-power_platform_get_battery_current(), // 充电电流(mA)
power_supply_app_get_bat_capacity(), // 电量百分比
power_supply_app_get_bat_temp(), // 电池温度(℃)
acr_val); // ACR 值(mΩ)
/* 上报 DMD 异常 */
power_dsm_report_dmd(POWER_DSM_BATTERY,
POWER_DSM_ERROR_BATT_ACR_OVER_THRESHOLD, buf);
}DMD 上报示例:
brand:ATL, volt:3850, curr:120, soc:45, temp:25, acr:105触发条件: acr_value > rt_threshold(默认 100mΩ)
6. Sysfs 接口
6.1 接口列表
bash
# ACR 检测 sysfs 节点路径
/sys/class/hw_power/charger/acr/
├── acr_rt_support # 只读,是否支持运行时检测
└── acr_rt_detect # 读写,触发检测/查询状态6.2 接口详解
6.2.1 acr_rt_support(只读)
功能: 查询是否支持 ACR 运行时检测
bash
cat /sys/class/hw_power/charger/acr/acr_rt_support返回值:
0- 不支持1- 支持
6.2.2 acr_rt_detect(读写)
功能: 触发 ACR 检测 / 查询检测状态
写操作(触发检测):
bash
echo 1 > /sys/class/hw_power/charger/acr/acr_rt_detect前置条件:
rt_support == 1(功能使能)factory_mode(工厂模式)rt_run == NOT_RUNNING(未在运行)
读操作(查询状态):
bash
cat /sys/class/hw_power/charger/acr/acr_rt_detect返回值:
0- 初始状态(ACR_DET_STATUS_INIT)1- 检测失败(ACR_DET_STATUS_FAIL)2- 检测成功(ACR_DET_STATUS_SUCC)
6.3 使用示例
产线检测脚本:
bash
#!/bin/bash
# 1. 检查是否支持
support=$(cat /sys/class/hw_power/charger/acr/acr_rt_support)
if [ "$support" != "1" ]; then
echo "ACR detect not supported"
exit 1
fi
# 2. 触发检测
echo 1 > /sys/class/hw_power/charger/acr/acr_rt_detect
# 3. 等待检测完成(最多 10 秒)
for i in {1..100}; do
status=$(cat /sys/class/hw_power/charger/acr/acr_rt_detect)
if [ "$status" == "2" ]; then
echo "ACR detect success"
exit 0
elif [ "$status" == "1" ]; then
echo "ACR detect failed"
exit 1
fi
sleep 0.1
done
echo "ACR detect timeout"
exit 17. 典型应用场景
7.1 产线老化测试
场景: 工厂产线对电池进行老化测试
bash
# 1. 充电至指定电量(如 50%)
# 2. 断开充电器,等待电流稳定
# 3. 触发 ACR 检测
echo 1 > /sys/class/hw_power/charger/acr/acr_rt_detect
# 4. 等待结果
sleep 10
status=$(cat /sys/class/hw_power/charger/acr/acr_rt_detect)
# 5. 判断结果
if [ "$status" == "2" ]; then
echo "PASS"
else
echo "FAIL"
fi7.2 售后诊断工具
场景: 售后检测电池健康状态
java
// Android 应用层代码示例
public class AcrDetector {
private static final String ACR_SUPPORT =
"/sys/class/hw_power/charger/acr/acr_rt_support";
private static final String ACR_DETECT =
"/sys/class/hw_power/charger/acr/acr_rt_detect";
public boolean isSupported() {
String value = FileUtils.readFile(ACR_SUPPORT);
return "1".equals(value);
}
public int startDetect() {
FileUtils.writeFile(ACR_DETECT, "1");
// 等待检测完成
for (int i = 0; i < 100; i++) {
String status = FileUtils.readFile(ACR_DETECT);
if ("2".equals(status)) {
return STATUS_SUCCESS;
} else if ("1".equals(status)) {
return STATUS_FAIL;
}
Thread.sleep(100);
}
return STATUS_TIMEOUT;
}
}7.3 研发调试
场景: 研发人员验证 ACR 功能
bash
# 查看 ACR 检测日志
dmesg | grep acr_detect
# 典型日志输出:
# [ 100.123] acr_detect: i:0, ichg:150
# [ 100.223] acr_detect: i:1, ichg:120
# [ 100.323] acr_detect: i:2, ichg:85
# [ 100.423] acr_detect: i:3, ichg:45
# [ 100.523] acr_detect: i:4, ichg:8 <- 电流达到阈值
# [ 101.623] acr_detect: acr:75, threshold:100
# [ 101.673] acr_detect: acr detect succ8. DTS 配置
8.1 配置示例
dts
batt_acr_detect {
compatible = "huawei,batt_acr_detect";
status = "ok";
/* 是否支持运行时检测(0=不支持, 1=支持)*/
acr_rt_support = <1>;
/* ACR 阈值(单位:Ω,会自动转换为 mΩ)*/
acr_rt_threshold = <100>; /* 100Ω → 100000mΩ */
/* FMD 上报阈值范围 */
acr_rt_fmd_min = <40>; /* 最小值 40mΩ */
acr_rt_fmd_max = <90>; /* 最大值 90mΩ */
};8.2 参数说明
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| acr_rt_support | u32 | 0 | 是否支持运行时检测 |
| acr_rt_threshold | u32 | 100 | ACR 阈值(Ω,会×1000 转为 mΩ) |
| acr_rt_fmd_min | u32 | 40 | FMD 最小阈值(mΩ) |
| acr_rt_fmd_max | u32 | 90 | FMD 最大阈值(mΩ) |
9. 调试方法
9.1 日志分析
使能动态日志:
bash
echo 'file acr_detect.c +p' > /sys/kernel/debug/dynamic_debug/control关键日志:
bash
# 检测启动
[acr_detect] acr detect is running
# 电流等待过程
[acr_detect] i:0, ichg:150
[acr_detect] i:1, ichg:120
...
[acr_detect] i:4, ichg:8
# ACR 测量结果
[acr_detect] acr:75, threshold:100
# 检测成功/失败
[acr_detect] acr detect succ
[acr_detect] acr detect fail9.2 故障诊断流程
问题:ACR 检测失败
├─ 1. 检查功能是否使能
│ └─ cat /sys/class/hw_power/charger/acr/acr_rt_support
│ (应返回 1)
│
├─ 2. 确认工厂模式
│ └─ cat /proc/cmdline | grep factory
│ (应包含 androidboot.mode=factory)
│
├─ 3. 检查电流是否稳定
│ └─ dmesg | grep "ichg"
│ (观察电流是否能降至 <10mA)
│
├─ 4. 验证平台接口
│ └─ power_platform_get_acr_resistance() 是否实现
│
└─ 5. 查看 DMD/FMD 上报
└─ dmesg | grep "dsm"9.3 测试检查点
| 检查项 | 预期结果 | 检查方法 |
|---|---|---|
| 功能使能 | rt_support=1 | cat acr_rt_support |
| 工厂模式 | cmdline 包含 factory | cat /proc/cmdline |
| 电流稳定 | ichg < 10mA | dmesg grep ichg |
| ACR 测量 | 返回有效值 | dmesg grep "acr:" |
| 状态更新 | rt_status=2 | cat acr_rt_detect |
| FMD 上报 | 数据采集成功 | 检查 FMD 平台 |
| DMD 上报 | 超阈值时触发 | dmesg grep dsm |
10. 设计亮点
10.1 电流稳定等待机制
问题: ACR 测量需要静态条件(电流 <10mA)
解决方案: 循环检测 + 延迟等待
c
for (i = 0; i < ACR_DET_RETRY_TIMES; i++) {
ichg = get_battery_current();
if (abs(ichg) < ACR_DET_MIN_CURRENT) {
// 电流足够小,开始测量
break;
}
msleep(100); // 等待 100ms 后重试
}优点:
- ✅ 自适应等待,避免固定延迟浪费时间
- ✅ 有超时保护(最多 5 秒)
- ✅ 日志记录每次电流值,便于调试
10.2 DMD/FMD 双重上报
DMD: 设备异常监控,触发告警
- 仅在
acr > threshold时上报 - 用于售后问题追踪
FMD: 数据采集平台,质量分析
- 每次测量都上报(包括正常和异常)
- 用于大数据分析、质量改进
时序控制:
c
acr_det_fmd_report(acr_value); // 先 FMD
msleep(50); // 延迟 50ms,避免 DSM client 冲突
if (acr_value > threshold)
acr_det_dmd_report(acr_value); // 后 DMD10.3 工厂模式限制
安全考虑: 仅工厂模式可触发检测
c
if (!power_cmdline_is_factory_mode()) {
hwlog_info("acr detect not support on normal mode\n");
return -EINVAL;
}原因:
- 🔒 避免用户误操作
- 🛡️ ACR 检测需要特殊充电条件
- 📊 仅用于产线/售后场景
10.4 状态机设计
INIT (0)
│
│ echo 1 > acr_rt_detect
▼
RUNNING
│
┌─────┴─────┐
▼ ▼
SUCC (2) FAIL (1)状态转换:
- INIT →
RUNNING:用户触发检测 RUNNING→SUCC:检测成功RUNNING→FAIL:检测失败
11. 总结
acr_detect 模块是华为充电管理系统中的电池健康监测组件,通过以下设计实现了可靠的 ACR 检测:
核心特性:
- ✅ 智能等待:自适应电流稳定检测(最多 5 秒)
- ✅ 双重上报:DMD 告警 + FMD 数据采集
- ✅ 安全限制:仅工厂模式可用,避免误操作
- ✅ 状态管理:清晰的状态机设计(INIT/FAIL/SUCC)
应用价值:
- 🏭 产线检测:电池老化测试、出厂质检
- 🔧 售后诊断:电池健康状态评估
- 📊 数据采集:质量分析、产品改进
- 🛡️ 异常预警:ACR 超阈值时触发告警
典型流程:
- 设置最大输入电流 → 2. 等待电流 <10mA → 3. 测量 ACR → 4. 上报结果
该模块充分体现了测量条件控制和多维度数据上报的设计思想,是电池健康监测的重要组件。