华为充电管理之Charge Mode Test 模块
1. 模块概述
1.1 模块定位
Charge Mode Test 是华为充电系统中的自动化测试模块,用于对各种充电模式进行系统化的功能验证和性能测试。该模块可以自动切换不同的充电协议和充电模式,并验证充电电流是否达到预期阈值。
核心功能:
文件位置:
drivers/hwpower/cc_charger/test/
├── charge_mode_test.c # 测试模块核心实现
├── charge_mode_test.h # 数据结构与接口定义
└── Makefile # 编译配置
1.2 设计特点
自动化测试流程:
灵活配置:
2. 核心数据结构
2.1 充电模式参数结构
struct charge_mode_para {
char protocol[PROTOCOL_LEN_MAX];
char mode[CHARGE_MODE_LEN_MAX];
int ibat_th;
int time;
int ext;
int force;
enum charge_mode_result result;
enum charge_mode_sub_result sub_result;
};
参数说明:
protocol:适配器协议类型("ufcs", "scp", "fcp")
mode:充电模式("dcp", "lvc", "sc", "sc_main", "sc_aux", "sc4", "sc4_main", "sc4_aux", "hvc")
ibat_th:电流阈值,测试时需达到此电流才算成功
time:测试超时时间(秒),转换为毫秒后存储
ext:提前结束标志(1=达到电流阈值即结束,0=必须持续到超时)
force:强制测试(1=即使适配器不支持也测试,0=适配器不支持则跳过)
2.2 测试设备结构
struct charge_mode_dev {
struct device *dev;
struct notifier_block charge_mode_nb;
struct delayed_work test_work;
struct charge_mode_para mode_para[CHARGE_MODE_NUM_MAX];
long long start_time;
long long curr_time;
int mode_idx;
int mode_num;
int adp_mode;
int ping_result;
int temp_err_flag;
int voltage_invalid_flag;
int delay_time;
char result[RESULT_BUF_LEN_MAX];
};
2.3 测试结果枚举
enum charge_mode_result {
CHARGE_MODE_RESULT_INIT = 0,
CHARGE_MODE_RESULT_SUCC,
CHARGE_MODE_RESULT_FAIL,
};
enum charge_mode_sub_result {
CHARGE_MODE_SUB_INIT = 0,
CHARGE_MODE_SUB_SUCC,
CHARGE_MODE_IBAT_FAIL,
CHARGE_MODE_UE_PROTOCOL_FAIL,
CHARGE_MODE_ADP_PROTOCOL_FAIL,
CHARGE_MODE_CC_MOISTURE,
CHARGE_MODE_TEMP_ERR,
CHARGE_MODE_VOL_INVALID,
CHARGE_MODE_ADP_UNSUPPORT,
};
2.4 充电模式类型枚举
enum charge_mode_type {
CHARGE_MODE_TYPE_DCP = 0,
CHARGE_MODE_TYPE_LVC,
CHARGE_MODE_TYPE_SC,
CHARGE_MODE_TYPE_MAIN_SC,
CHARGE_MODE_TYPE_AUX_SC,
CHARGE_MODE_TYPE_SC4,
CHARGE_MODE_TYPE_MAIN_SC4,
CHARGE_MODE_TYPE_AUX_SC4,
CHARGE_MODE_TYPE_HVC,
CHARGE_MODE_TYPE_END,
};
2.5 协议映射表
static struct charge_mode_map g_protocol_tbl[] = {
{ "ufcs", CHARGE_MODE_PROTOCOL_UFCS },
{ "scp", CHARGE_MODE_PROTOCOL_SCP },
{ "fcp", CHARGE_MODE_PROTOCOL_HVC }
};
static struct charge_mode_map g_mode_tbl[] = {
{ "dcp", CHARGE_MODE_TYPE_DCP },
{ "lvc", CHARGE_MODE_TYPE_LVC },
{ "sc", CHARGE_MODE_TYPE_SC },
{ "sc_main", CHARGE_MODE_TYPE_MAIN_SC },
{ "sc_aux", CHARGE_MODE_TYPE_AUX_SC },
{ "sc4", CHARGE_MODE_TYPE_SC4 },
{ "sc4_main", CHARGE_MODE_TYPE_MAIN_SC4 },
{ "sc4_aux", CHARGE_MODE_TYPE_AUX_SC4 },
{ "hvc", CHARGE_MODE_TYPE_HVC },
};
static int g_adp_mode_map[] = {
ADAPTER_SUPPORT_UNDEFINED,
ADAPTER_SUPPORT_LVC,
ADAPTER_SUPPORT_SC,
ADAPTER_SUPPORT_SC,
ADAPTER_SUPPORT_SC,
ADAPTER_SUPPORT_SC4,
ADAPTER_SUPPORT_SC4,
ADAPTER_SUPPORT_SC4,
ADAPTER_SUPPORT_HV,
};
2.6 模式控制动作表
static struct charge_mode_action g_action_tbl[] = {
{ POWER_IF_OP_TYPE_DCP, INVALID_INDEX },
{ POWER_IF_OP_TYPE_LVC, INVALID_INDEX },
{ POWER_IF_OP_TYPE_SC, INVALID_INDEX },
{ POWER_IF_OP_TYPE_MAINSC, POWER_IF_OP_TYPE_SC },
{ POWER_IF_OP_TYPE_AUXSC, POWER_IF_OP_TYPE_SC },
{ POWER_IF_OP_TYPE_SC4, INVALID_INDEX },
{ POWER_IF_OP_TYPE_MAINSC4, POWER_IF_OP_TYPE_SC4 },
{ POWER_IF_OP_TYPE_AUXSC4, POWER_IF_OP_TYPE_SC4 },
{ POWER_IF_OP_TYPE_HVC, INVALID_INDEX },
};
3. 核心功能实现
3.1 协议选择
static int charge_mode_select_protocol(struct charge_mode_dev *di)
{
unsigned int prot_type;
unsigned int init_prot;
int adp_mode;
int index;
for (adp_mode = 0; di->mode_idx < di->mode_num; di->mode_idx++) {
index = charge_mode_get_map_index(di->mode_para[di->mode_idx].mode,
g_mode_tbl, ARRAY_SIZE(g_mode_tbl));
if (index == CHARGE_MODE_TYPE_HVC)
return CHARGE_MODE_SUCCESS;
index = charge_mode_get_map_index(di->mode_para[di->mode_idx].protocol,
g_protocol_tbl, ARRAY_SIZE(g_protocol_tbl));
if (index == INVALID_INDEX)
continue;
if ((di->mode_idx > 0) &&
(strcmp(di->mode_para[di->mode_idx].protocol,
di->mode_para[di->mode_idx - 1].protocol) == 0))
return CHARGE_MODE_SUCCESS;
prot_type = adapter_detect_get_sysfs_protocol_type(index);
init_prot = adapter_detect_get_init_protocol_type();
if ((prot_type & init_prot) || (init_prot == 0)) {
power_if_kernel_sysfs_set(POWER_IF_OP_TYPE_ADAPTER_PROTOCOL,
POWER_IF_SYSFS_ADAPTER_PROTOCOL, index);
hwlog_info("select protocol %s\n", di->mode_para[di->mode_idx].protocol);
(void)power_msleep(DT_MSLEEP_1S, 0, NULL);
return CHARGE_MODE_SUCCESS;
} else {
charge_mode_set_result(&di->mode_para[di->mode_idx],
CHARGE_MODE_RESULT_FAIL,
CHARGE_MODE_UE_PROTOCOL_FAIL);
hwlog_err("not support protocol %s\n",
di->mode_para[di->mode_idx].protocol);
}
}
hwlog_err("protocol select fail\n");
return CHARGE_MODE_FAILURE;
}
协议选择逻辑:
检查模式是否为 HVC(HVC 不需要协议切换)
检查协议是否与上一个模式相同(避免重复切换)
验证协议是否被系统支持
通过 sysfs 接口设置协议
延迟 1 秒等待协议切换完成
3.2 模式选择与使能
static void charge_mode_select_mode(char *mode)
{
int index;
hwlog_info("select mode %s\n", mode);
index = charge_mode_get_map_index(mode, g_mode_tbl, ARRAY_SIZE(g_mode_tbl));
power_if_kernel_sysfs_set(POWER_IF_OP_TYPE_ALL,
POWER_IF_SYSFS_ENABLE_CHARGER, DISABLE);
(void)power_msleep(DT_MSLEEP_2S, 0, NULL);
power_if_kernel_sysfs_set(POWER_IF_OP_TYPE_DCP,
POWER_IF_SYSFS_ENABLE_CHARGER, ENABLE);
power_if_kernel_sysfs_set(g_action_tbl[index].first,
POWER_IF_SYSFS_ENABLE_CHARGER, ENABLE);
if (g_action_tbl[index].second != INVALID_INDEX) {
(void)power_msleep(DT_MSLEEP_1S, 0, NULL);
power_if_kernel_sysfs_set(g_action_tbl[index].second,
POWER_IF_SYSFS_ENABLE_CHARGER, ENABLE);
}
}
模式切换流程:
禁用所有充电模式
↓
等待 2 秒(确保直充完全停止)
↓
使能 DCP 基础充电
↓
使能目标充电模式(第一级)
↓
如需第二级使能(如 MAIN_SC)
↓
延迟 1 秒后使能第二级
二级使能示例:
sc_main:先使能 SC,1秒后使能 MAIN_SC
sc_aux:先使能 SC,1秒后使能 AUX_SC
sc4_main:先使能 SC4,1秒后使能 MAIN_SC4
3.3 充电电流计算与判断
static bool charge_mode_caculate(struct charge_mode_dev *di)
{
int ibat = 0;
int ibat_th;
int index;
if (di->mode_idx == INVALID_INDEX)
return false;
ibat_th = di->mode_para[di->mode_idx].ibat_th;
index = charge_mode_get_map_index(di->mode_para[di->mode_idx].mode,
g_mode_tbl, ARRAY_SIZE(g_mode_tbl));
if ((index == CHARGE_MODE_TYPE_HVC) &&
(hvdcp_get_charging_stage() == HVDCP_STAGE_SUCCESS))
return hvdcp_check_running_current(ibat_th);
if (direct_charge_get_stage_status() == DC_STAGE_CHARGING)
direct_charge_get_bat_current(&ibat);
hwlog_info("ibat = %d ibat_th = %d\n", ibat, ibat_th);
if (ibat >= ibat_th)
return true;
return false;
}
电流判断逻辑:
3.4 测试结果更新
static void charge_mode_update_result(struct charge_mode_dev *di)
{
int index;
if (di->mode_idx == INVALID_INDEX)
return;
index = charge_mode_get_map_index(di->mode_para[di->mode_idx].mode,
g_mode_tbl, ARRAY_SIZE(g_mode_tbl));
if (charge_mode_valid(di) == CHARGE_MODE_SUCCESS) {
di->mode_para[di->mode_idx].result = CHARGE_MODE_RESULT_SUCC;
di->temp_err_flag = false;
di->voltage_invalid_flag = false;
return;
}
if ((di->mode_para[di->mode_idx].result == CHARGE_MODE_RESULT_SUCC) &&
(di->mode_para[di->mode_idx].ext == ENABLE)) {
di->mode_para[di->mode_idx].sub_result = CHARGE_MODE_SUB_SUCC;
hwlog_info("end the mode test in advance\n");
return;
}
if (di->curr_time - di->start_time >= di->mode_para[di->mode_idx].time) {
hwlog_info("this mode test timeout\n");
if (di->mode_para[di->mode_idx].result == CHARGE_MODE_RESULT_INIT)
charge_mode_set_result(&di->mode_para[di->mode_idx],
CHARGE_MODE_RESULT_FAIL,
CHARGE_MODE_IBAT_FAIL);
if (di->mode_para[di->mode_idx].result == CHARGE_MODE_RESULT_SUCC)
di->mode_para[di->mode_idx].sub_result = CHARGE_MODE_SUB_SUCC;
return;
}
if (index == CHARGE_MODE_TYPE_HVC) {
hwlog_info("hvc test\n");
return;
}
if (di->ping_result == CHARGE_MODE_FAILURE) {
charge_mode_set_result(&di->mode_para[di->mode_idx],
CHARGE_MODE_RESULT_FAIL,
CHARGE_MODE_ADP_PROTOCOL_FAIL);
di->ping_result = CHARGE_MODE_SUCCESS;
hwlog_info("adapter not support protocol %s\n",
di->mode_para[di->mode_idx].protocol);
return;
}
if ((di->adp_mode != 0 && (di->adp_mode & g_adp_mode_map[index]) == 0) &&
(di->mode_para[di->mode_idx].force == DISABLE)) {
charge_mode_set_result(&di->mode_para[di->mode_idx],
CHARGE_MODE_RESULT_SUCC,
CHARGE_MODE_ADP_UNSUPPORT);
hwlog_err("adapter not support mode %s\n",
di->mode_para[di->mode_idx].mode);
}
}
结果更新流程:
检查异常状态(CC潮湿/温度/电压)
↓
检查提前结束条件(ext=1 且已达阈值)
↓
检查超时条件
├─> 从未达阈值 -> FAIL (IBAT_FAIL)
└─> 曾达阈值 -> SUCC (SUB_SUCC)
↓
检查协议 PING 失败
↓
检查适配器能力不支持
3.5 测试监控任务
static void charge_mode_monitor(struct work_struct *work)
{
struct charge_mode_dev *di = NULL;
di = container_of(work, struct charge_mode_dev, test_work.work);
di->curr_time = ktime_to_ms(ktime_get_boottime());
if (charge_mode_caculate(di))
di->mode_para[di->mode_idx].result = CHARGE_MODE_RESULT_SUCC;
else
charge_mode_set_result(&di->mode_para[di->mode_idx],
CHARGE_MODE_RESULT_INIT,
CHARGE_MODE_SUB_INIT);
charge_mode_update_result(di);
if (charge_mode_jump_mode(di)) {
di->mode_idx++;
di->adp_mode = 0;
di->ping_result = 0;
if (di->mode_idx >= di->mode_num) {
charge_mode_state_reset(di);
return;
}
if (charge_mode_select_protocol(di)) {
charge_mode_state_reset(di);
return;
}
charge_mode_select_mode(di->mode_para[di->mode_idx].mode);
di->start_time = ktime_to_ms(ktime_get_boottime());
}
schedule_delayed_work(&di->test_work, msecs_to_jiffies(CHARGE_MODE_WORK_TIME));
}
监控任务流程:
更新当前时间
↓
检查充电电流是否达标
├─> 达标 -> 标记 SUCC
└─> 未达标 -> 保持 INIT
↓
更新测试结果(超时/异常判断)
↓
判断是否跳转下一个模式
├─> 不跳转 -> 继续监控当前模式
└─> 跳转
↓
mode_idx++
↓
选择下一个协议
↓
使能下一个模式
↓
记录开始时间
↓
调度下一次监控(5秒后)
3.6 事件通知处理
static int charge_mode_notifier_call(struct notifier_block *nb,
unsigned long event, void *data)
{
struct charge_mode_dev *di = NULL;
di = container_of(nb, struct charge_mode_dev, charge_mode_nb);
if (!di)
return NOTIFY_OK;
switch (event) {
case POWER_NE_DC_PING_FAIL:
di->ping_result = CHARGE_MODE_FAILURE;
break;
case POWER_NE_DC_ADAPTER_MODE:
di->adp_mode = *((int *)data);
break;
case POWER_NE_DC_TEMP_ERR:
di->temp_err_flag = true;
break;
case POWER_NE_DC_VOLTAGE_INVALID:
di->voltage_invalid_flag = true;
break;
case POWER_NE_DC_CHECK_SUCC:
di->temp_err_flag = false;
di->voltage_invalid_flag = false;
break;
default:
break;
}
return NOTIFY_OK;
}
监听事件:
POWER_NE_DC_PING_FAIL:直充 PING 失败
POWER_NE_DC_ADAPTER_MODE:适配器能力上报
POWER_NE_DC_TEMP_ERR:温度异常
POWER_NE_DC_VOLTAGE_INVALID:电压异常
POWER_NE_DC_CHECK_SUCC:检查成功
4. Sysfs 接口
4.1 接口定义
static struct power_sysfs_attr_info charge_mode_sysfs_field_tbl[] = {
power_sysfs_attr_wo(charge_mode, 0200, CHARGE_MODE_SYSFS_START, start),
power_sysfs_attr_ro(charge_mode, 0440, CHARGE_MODE_SYSFS_RESULT, result),
};
4.2 Sysfs 节点
路径: /sys/class/hw_power/charger/charge_mode_tst/
节点1:start(只写)
功能: 启动充电模式测试
用法:
echo 1 > /sys/class/hw_power/charger/charge_mode_tst/start
内部处理:
static void charge_mode_start(struct charge_mode_dev *di)
{
charge_mode_set_all_result(di, CHARGE_MODE_RESULT_INIT, CHARGE_MODE_SUB_INIT);
charge_mode_init_para(di);
if (di->delay_time)
power_msleep(di->delay_time, 0, NULL);
hwlog_info("charge mode test start\n");
cancel_delayed_work_sync(&di->test_work);
schedule_delayed_work(&di->test_work, 0);
}
节点2:result(只读)
功能: 获取测试结果
用法:
cat /sys/class/hw_power/charger/charge_mode_tst/result
输出格式:
protocol1,mode1,result1,sub_result1;protocol2,mode2,result2,sub_result2;...
示例输出:
scp,lvc,2,1;scp,sc,2,1;scp,sc4,1,3;ufcs,lvc,2,1;ufcs,sc,2,1;
字段说明:
protocol:充电协议(scp/ufcs/fcp)
mode:充电模式(lvc/sc/sc4/hvc等)
result:主结果(0=INIT, 1=SUCC, 2=FAIL)
sub_result:详细结果(见枚举定义)
内部处理:
static int charge_mode_result(struct charge_mode_dev *di, char *buf)
{
int i, k, ret;
k = 0;
for (i = 0; i < di->mode_num; i++) {
ret = sprintf_s(buf + k, PAGE_SIZE, "%s,%s,%d,%d;",
di->mode_para[i].protocol,
di->mode_para[i].mode,
di->mode_para[i].result,
di->mode_para[i].sub_result);
if (ret == INVALID_RESULT)
return CHARGE_MODE_FAILURE;
k += ret;
}
return k;
}
4.3 调试节点
路径: /sys/kernel/debug/hw_power/charge_mode_tst/delay
功能: 设置测试启动延迟时间
用法:
echo 5000 > /sys/kernel/debug/hw_power/charge_mode_tst/delay
cat /sys/kernel/debug/hw_power/charge_mode_tst/delay
5. DTS 配置
5.1 配置示例
charge_mode_test {
compatible = "huawei,charge_mode_test";
status = "ok";
test_para =
/* protocol, mode, ibat_th, time, ext, force */
"scp", "lvc", "3000", "60", "0", "0",
"scp", "sc", "5000", "60", "0", "0",
"scp", "sc4", "8000", "60", "0", "0",
"ufcs", "lvc", "3000", "60", "0", "0",
"ufcs", "sc", "5000", "60", "0", "0",
"ufcs", "sc4", "8000", "60", "0", "0",
"fcp", "hvc", "2000", "60", "0", "0";
};
5.2 参数说明
| 参数 | 类型 | 说明 | 示例 |
|---|
| protocol | string | 充电协议 | "scp"/"ufcs"/"fcp" |
| mode | string | 充电模式 | "lvc"/"sc"/"sc4"/"hvc" |
| ibat_th | int | 电流阈值(mA) | "3000" = 3A |
| time | int | 测试时间(秒) | "60" = 60秒 |
| ext | int | 提前结束标志 | "1"=达标即结束, "0"=持续到超时 |
| force | int | 强制测试标志 | "1"=忽略适配器能力, "0"=适配器不支持则跳过 |
5.3 解析逻辑
static void charge_mode_parse_dts(struct device_node *np, struct charge_mode_dev *di)
{
int i, row, col, array_len, ret;
const char *tmp_string = NULL;
array_len = power_dts_read_count_strings(power_dts_tag(HWLOG_TAG), np,
"test_para", CHARGE_MODE_NUM_MAX, CHARGE_MODE_PARA_TOTAL);
if (array_len < 0)
return;
for (i = 0; i < array_len; i++) {
if (power_dts_read_string_index(power_dts_tag(HWLOG_TAG),
np, "test_para", i, &tmp_string))
continue;
row = i / CHARGE_MODE_PARA_TOTAL;
col = i % CHARGE_MODE_PARA_TOTAL;
ret = g_parse_tbl[col](di, row, tmp_string, (col - CHARGE_MODE_IBAT_TH));
if (ret)
return;
if (col == CHARGE_MODE_TIME)
di->mode_para[row].time *= MSEC_PER_SEC;
}
}
6. 典型使用场景
6.1 标准测试流程
echo 1 > /sys/class/hw_power/charger/charge_mode_tst/start
cat /sys/class/hw_power/charger/charge_mode_tst/result
6.2 测试场景示例
场景1:全协议全模式测试
test_para =
"scp", "lvc", "3000", "60", "0", "0",
"scp", "sc", "5000", "60", "0", "0",
"scp", "sc4", "8000", "60", "0", "0",
"ufcs", "lvc", "3000", "60", "0", "0",
"ufcs", "sc", "5000", "60", "0", "0",
"ufcs", "sc4", "8000", "60", "0", "0",
"fcp", "hvc", "2000", "60", "0", "0";
测试顺序:
SCP + LVC(3A,60秒)
SCP + SC(5A,60秒)
SCP + SC4(8A,60秒)
UFCS + LVC(3A,60秒)
UFCS + SC(5A,60秒)
UFCS + SC4(8A,60秒)
FCP + HVC(2A,60秒)
场景2:快速验证(提前结束模式)
test_para =
"scp", "lvc", "3000", "60", "1", "0", // ext=1,达标即结束
"scp", "sc", "5000", "60", "1", "0";
说明: 一旦充电电流达到阈值,立即结束当前模式测试,进入下一个模式
场景3:强制测试(忽略适配器能力)
test_para =
"scp", "sc4", "8000", "60", "0", "1"; // force=1,强制测试
说明: 即使适配器不支持 SC4,也会尝试测试(用于调试)
场景4:主辅路单独测试
test_para =
"scp", "sc_main", "3000", "60", "0", "0", // 主路 SC
"scp", "sc_aux", "2000", "60", "0", "0"; // 辅路 SC
6.3 测试结果解读
成功示例
协议:SCP
模式:LVC
结果:2(SUCC)
详细结果:1(SUB_SUCC)
解读:LVC 模式测试成功,充电电流达到阈值
失败示例1:电流不达标
协议:SCP
模式:SC
结果:1(FAIL)
详细结果:3(IBAT_FAIL)
解读:SC 模式测试失败,超时仍未达到电流阈值
失败示例2:适配器不支持
失败示例3:协议不支持
7. 调试方法
7.1 日志分析
日志标签: charge_mode_tst
关键日志输出:
[charge_mode_tst] charge mode test start
[charge_mode_tst] select protocol scp
[charge_mode_tst] select mode lvc
[charge_mode_tst] ibat = 3200 ibat_th = 3000
[charge_mode_tst] end the mode test in advance
[charge_mode_tst] this mode test timeout
[charge_mode_tst] adapter not support mode sc4
[charge_mode_tst] not support protocol ufcs
7.2 常见问题诊断
问题1:测试无法启动
lsmod | grep charge_mode_test
ls /sys/class/hw_power/charger/charge_mode_tst/
cat /proc/device-tree/charge_mode_test/status
问题2:所有模式测试失败
cat /sys/class/power_supply/usb/present
cat /sys/class/power_supply/usb/type
cat /sys/class/power_supply/usb/voltage_now
dmesg | grep charge_mode_tst
问题3:部分模式跳过(ADP_UNSUPPORT)
cat /sys/class/hw_power/adapter/adapter_support_mode
适配器能力掩码:
0x01:UNDEFINED
0x02:LVC
0x04:SC
0x08:SC4
0x10:HV(HVDCP)
问题4:电流不达标(IBAT_FAIL)
watch -n 1 cat /sys/class/power_supply/battery/current_now
cat /sys/class/hw_power/direct_charger/charge_stage
cat /sys/class/power_supply/battery/temp
cat /sys/class/power_supply/battery/voltage_now
7.3 手动控制测试
echo 5000 > /sys/kernel/debug/hw_power/charge_mode_tst/delay
echo 1 > /sys/class/hw_power/charger/charge_mode_tst/start
logcat -s charge_mode_tst
cat /sys/class/hw_power/charger/charge_mode_tst/result
cat /sys/class/hw_power/charger/charge_mode_tst/result | \
awk -F';' '{for(i=1;i<=NF;i++) print $i}'
8. 关键技术要点
8.1 测试自动化
顺序执行机制:
通过 mode_idx 索引顺序遍历测试项
每个模式测试完成后自动切换到下一个
支持协议复用(连续相同协议的模式无需重新切换)
时间管理:
使用 ktime_get_boottime() 获取启动时间(不受休眠影响)
每个模式独立计时(start_time 和 curr_time)
5秒监控周期(CHARGE_MODE_WORK_TIME)
8.2 结果判定逻辑
电流达标判断:
↓
YES → 标记 RESULT_SUCC
NO → 保持 RESULT_INIT
↓
超时判断:
↓
从未达标 → FAIL (IBAT_FAIL)
曾经达标 → SUCC (SUB_SUCC)
↓
异常检测:
↓
CC潮湿 → SUCC (CC_MOISTURE)
温度异常 → SUCC (TEMP_ERR)
电压异常 → SUCC (VOL_INVALID)
↓
适配器能力检测:
↓
协议不支持 → FAIL (ADP_PROTOCOL_FAIL/UE_PROTOCOL_FAIL)
模式不支持 → SUCC (ADP_UNSUPPORT)
8.3 与其他模块的交互
charge_mode_test 依赖模块:
├── direct_charger # 获取直充状态和电池电流
├── hvdcp_charge # HVC 模式电流验证
├── adapter_detect # 协议类型和适配器能力
├── power_interface # sysfs 接口控制充电模式
└── power_event # 事件通知(PING失败、适配器能力等)
事件订阅:
└── POWER_BNT_DC
├── POWER_NE_DC_PING_FAIL # PING 失败
├── POWER_NE_DC_ADAPTER_MODE # 适配器能力
├── POWER_NE_DC_TEMP_ERR # 温度异常
├── POWER_NE_DC_VOLTAGE_INVALID # 电压异常
└── POWER_NE_DC_CHECK_SUCC # 检查成功
8.4 工作队列机制
struct delayed_work test_work;
INIT_DELAYED_WORK(&di->test_work, charge_mode_monitor);
schedule_delayed_work(&di->test_work, 0);
schedule_delayed_work(&di->test_work, msecs_to_jiffies(CHARGE_MODE_WORK_TIME));
cancel_delayed_work_sync(&di->test_work);
9. 总结
9.1 模块特点
自动化程度高:配置后一键启动,自动完成全流程测试
灵活配置:支持多种协议、模式、参数组合
结果详细:不仅记录成功/失败,还记录详细失败原因
智能跳过:自动识别适配器能力,跳过不支持的模式
异常检测:实时监测 CC 潮湿、温度、电压等异常
9.2 适用场景
研发测试:新适配器兼容性验证
生产测试:出厂快充功能测试
故障诊断:充电问题定位分析
性能评估:充电电流性能评估
9.3 注意事项
测试时间:总测试时间 = Σ(每个模式的time) + 协议切换时间
适配器要求:需使用支持多协议的快充适配器
电池状态:建议电池电量 < 80% 以保证充电电流
温度控制:避免温度过高触发保护
并发限制:测试期间禁用其他充电控制操作