Skip to content

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Ω(可配置)

测量条件:

  1. 静态电流:电池电流 < 10mA(接近空载状态)
  2. 充电模式:设置最大输入电流后等待稳定
  3. 测量时长: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_id703023001ACR 检测项 ID
device_namebattery设备名称
test_nameBATT_ACR_VAL测试名称
min_threshold40最小阈值(mΩ)
max_threshold90最大阈值(mΩ)
resultpass/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

前置条件:

  1. rt_support == 1(功能使能)
  2. factory_mode(工厂模式)
  3. 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 1

7. 典型应用场景

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"
fi

7.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 succ

8. 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_supportu320是否支持运行时检测
acr_rt_thresholdu32100ACR 阈值(Ω,会×1000 转为 mΩ)
acr_rt_fmd_minu3240FMD 最小阈值(mΩ)
acr_rt_fmd_maxu3290FMD 最大阈值(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 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=1cat acr_rt_support
工厂模式cmdline 包含 factorycat /proc/cmdline
电流稳定ichg < 10mAdmesg grep ichg
ACR 测量返回有效值dmesg grep "acr:"
状态更新rt_status=2cat 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);  // 后 DMD

10.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)

状态转换:

  1. INIT → RUNNING:用户触发检测
  2. RUNNINGSUCC:检测成功
  3. RUNNINGFAIL:检测失败

11. 总结

acr_detect 模块是华为充电管理系统中的电池健康监测组件,通过以下设计实现了可靠的 ACR 检测:

核心特性:

  1. 智能等待:自适应电流稳定检测(最多 5 秒)
  2. 双重上报:DMD 告警 + FMD 数据采集
  3. 安全限制:仅工厂模式可用,避免误操作
  4. 状态管理:清晰的状态机设计(INIT/FAIL/SUCC)

应用价值:

  • 🏭 产线检测:电池老化测试、出厂质检
  • 🔧 售后诊断:电池健康状态评估
  • 📊 数据采集:质量分析、产品改进
  • 🛡️ 异常预警:ACR 超阈值时触发告警

典型流程:

  1. 设置最大输入电流 → 2. 等待电流 <10mA → 3. 测量 ACR → 4. 上报结果

该模块充分体现了测量条件控制多维度数据上报的设计思想,是电池健康监测的重要组件。