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 设备结构
struct acr_det_dev {
struct device *dev;
struct delayed_work rt_work;
int rt_run;
u32 rt_support;
int rt_status;
int rt_threshold;
u32 rt_fmd_min;
u32 rt_fmd_max;
};
3.2 检测状态
enum acr_det_status_type {
ACR_DET_STATUS_INIT = 0,
ACR_DET_STATUS_FAIL,
ACR_DET_STATUS_SUCC,
};
3.3 运行状态
#define ACR_DET_NOT_RUNNING 0
#define ACR_DET_RUNNING 1
3.4 配置参数
#define ACR_DET_RETRY_TIMES 50
#define ACR_DET_MIN_CURRENT 10
#define ACR_DET_DEFAULT_THLD 100
#define ACR_DET_DEFAULT_MIN_FMD 40
#define ACR_DET_DEFAULT_MAX_FMD 90
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 测量核心代码
static int acr_det_start_detect(struct acr_det_dev *l_dev)
{
int ret;
int acr_value = 0;
power_platform_start_acr_calc();
msleep(1000);
ret = power_platform_get_acr_resistance(&acr_value);
if (ret == 0) {
hwlog_info("acr:%d, threshold:%d\n", acr_value, l_dev->rt_threshold);
acr_det_fmd_report(l_dev, acr_value);
msleep(50);
if (acr_value > l_dev->rt_threshold)
acr_det_dmd_report(acr_value);
}
return ret;
}
4.3 电流稳定等待逻辑
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;
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;
}
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): 华为数据采集系统,用于产品质量分析
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;
acr_msg->data_source = DATA_FROM_KERNEL;
acr_msg->num_events = 1;
acr_msg->events[0].error_code = 0;
acr_msg->events[0].item_id = ACR_DET_ITEM_ID;
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);
snprintf(acr_msg->events[0].max_threshold, MAX_VAL_LEN,
"%u", l_dev->rt_fmd_max);
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): 设备监控与诊断系统
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(),
-power_platform_get_battery_current(),
power_supply_app_get_bat_capacity(),
power_supply_app_get_bat_temp(),
acr_val);
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 接口列表
/sys/class/hw_power/charger/acr/
├── acr_rt_support
└── acr_rt_detect
6.2 接口详解
6.2.1 acr_rt_support(只读)
功能: 查询是否支持 ACR 运行时检测
cat /sys/class/hw_power/charger/acr/acr_rt_support
返回值:
6.2.2 acr_rt_detect(读写)
功能: 触发 ACR 检测 / 查询检测状态
写操作(触发检测):
echo 1 > /sys/class/hw_power/charger/acr/acr_rt_detect
前置条件:
rt_support == 1(功能使能)
factory_mode(工厂模式)
rt_run == NOT_RUNNING(未在运行)
读操作(查询状态):
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 使用示例
产线检测脚本:
#!/bin/bash
support=$(cat /sys/class/hw_power/charger/acr/acr_rt_support)
if [ "$support" != "1" ]; then
echo "ACR detect not supported"
exit 1
fi
echo 1 > /sys/class/hw_power/charger/acr/acr_rt_detect
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 1
7. 典型应用场景
7.1 产线老化测试
场景: 工厂产线对电池进行老化测试
echo 1 > /sys/class/hw_power/charger/acr/acr_rt_detect
sleep 10
status=$(cat /sys/class/hw_power/charger/acr/acr_rt_detect)
if [ "$status" == "2" ]; then
echo "PASS"
else
echo "FAIL"
fi
7.2 售后诊断工具
场景: 售后检测电池健康状态
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 功能
8. DTS 配置
8.1 配置示例
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 日志分析
使能动态日志:
echo 'file acr_detect.c +p' > /sys/kernel/debug/dynamic_debug/control
关键日志:
[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_detect] acr:75, threshold:100
[acr_detect] acr detect succ
[acr_detect] acr detect fail
9.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)
解决方案: 循环检测 + 延迟等待
for (i = 0; i < ACR_DET_RETRY_TIMES; i++) {
ichg = get_battery_current();
if (abs(ichg) < ACR_DET_MIN_CURRENT) {
break;
}
msleep(100);
}
优点:
✅ 自适应等待,避免固定延迟浪费时间
✅ 有超时保护(最多 5 秒)
✅ 日志记录每次电流值,便于调试
10.2 DMD/FMD 双重上报
DMD: 设备异常监控,触发告警
仅在 acr > threshold 时上报
用于售后问题追踪
FMD: 数据采集平台,质量分析
每次测量都上报(包括正常和异常)
用于大数据分析、质量改进
时序控制:
acr_det_fmd_report(acr_value);
msleep(50);
if (acr_value > threshold)
acr_det_dmd_report(acr_value);
10.3 工厂模式限制
安全考虑: 仅工厂模式可触发检测
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. 上报结果
该模块充分体现了测量条件控制和多维度数据上报的设计思想,是电池健康监测的重要组件。