refactor(chrg): 调整Sink北向事务流程为先设置CC再协商协议

1.  apps/chrg/applications/thread/chrg_roll_nor.h: 新增两个Sink事务状态ID
2.  apps/chrg/applications/thread/chrg_comm.c: 修改全量握手时的事务跳转逻辑
3.  apps/chrg/applications/thread/chrg_north.c: 调整电压稳定计数阈值,拆分条件判断代码
4.  apps/chrg/applications/utils/chrg_sink.c: 更新注释和初始事务状态,调整握手执行顺序
5.  apps/chrg/applications/thread/chrg_roll_nor.c: 新增CC等待后直接进入协议设置的分支逻辑,更新期望命令和事务处理流程
This commit is contained in:
wrh
2026-08-09 15:20:58 +08:00
parent 8b7f29d0fc
commit 164e9cb4c0
5 changed files with 43 additions and 18 deletions
+4 -4
View File
@@ -2383,22 +2383,22 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
}
pReal->sink.test.test_mode_old = curr_test;
} else {
pReal->sub = IDX_SET_SINK_PD;
pReal->sub = IDX_SET_SINK_CC_BEFORE_PD;
pReal->sink.work_mode = SINK_WORK_INIT;
}
} else if (pReal->sink.On_work == 0) {
pReal->sink.On_work = 1;
pReal->sub = IDX_SET_SINK_PD;
pReal->sub = IDX_SET_SINK_CC_BEFORE_PD;
pReal->sink.work_mode = SINK_WORK_INIT;
} else if (full_handshake_change) {
/*
* 只有CC实际变化时才发送目标CC命令并等待;协议类型或组号
* 单独变化时直接重发PD帧,不重复设置未变化的CC。
* 协议与CC同时变化时先发送协议,协议应答后再设置目标CC;
* 协议与CC同时变化时先设置目标CC,CC稳定后再发送协议;
* 仅协议变化时不重复设置未变化的CC。
*/
if (diff_info.cc_changed && protocol_data_changed) {
pReal->sub = IDX_SET_SINK_PD;
pReal->sub = IDX_SET_SINK_CC_BEFORE_PD;
} else if (diff_info.cc_changed) {
pReal->sub = IDX_SET_SINK_CCLINE;
} else {
+4 -3
View File
@@ -29,7 +29,7 @@
#define SOURCE_QC_MIN_VOLT_MV 5000U // QC2.0/QC3.0允许使用的最低目标电压
#define SOURCE_QC_SWITCH_ERROR 0x04U // Source协议或CC切换失败错误位
#define SINK_CURRENT_START_GRACE_MS 200U // Sink启动后暂不判断无电流的保护时间
#define SINK_VOLT_STABLE_CONFIRM_COUNT 0U // Sink一帧有效稳定电压即进入RUNING
#define SINK_VOLT_STABLE_CONFIRM_COUNT 5U // Sink一帧有效稳定电压即进入RUNING
/*****************************************************************
函数名称: chrg_source_apply_protocol_voltage_rule
@@ -236,14 +236,15 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
* 当前回码不计入稳定电压次数,防止跳过协议设置直接带载。 */
volt_stable_count[idx] = 0;
no_curr[idx] = 0;
pSW->sub = IDX_SET_SINK_PD;
pSW->sub = IDX_SET_SINK_CC_BEFORE_PD;
pSW->sink.work_mode = SINK_WORK_WAIT;
} else if ((pSW->sink.work_mode == SINK_WORK_LOW) ||
(pSW->sink.work_mode == SINK_WORK_LOW_AUX_WAIT)) {
/* 掉电安全批次完成前,即使收到残留回码也不得进入RUNING。 */
volt_stable_count[idx] = 0;
no_curr[idx] = 0;
} else if ((rt_uint32_t)volt_mv + 2000 >= pSW->sink.pro_loadv) {
}
else if ((rt_uint32_t)volt_mv + 2000 >= pSW->sink.pro_loadv) {
if ((pSW->sink.work_mode != SINK_WORK_RUNING) &&
(pSW->sink.work_mode != SINK_WORK_SOFT_RUNNING) &&
(pSW->sink.work_mode != SINK_WORK_LOAD_STANDBY) &&
+25 -3
View File
@@ -311,7 +311,8 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch,
}
}
if (pSW->sub != IDX_WAIT_SINK_CC) {
if ((pSW->sub != IDX_WAIT_SINK_CC) &&
(pSW->sub != IDX_WAIT_SINK_CC_BEFORE_PD)) {
/* COM在等待期间提交新配置时,清理旧事务留下的CC计时记录。 */
g_sink_cc_wait_mask &= (rt_uint8_t)~bit;
g_sink_cc_wait_start[ch] = 0U;
@@ -322,8 +323,12 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch,
}
} else {
if ((g_sink_cc_wait_mask & bit) == 0U) {
if (pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD) {
pSW->sub = IDX_SET_SINK_PD;
} else {
pSW->sub = IDX_GET_SINK_VC;
chrg_roll_nor_sink_query_wait_start(ch);
}
return RT_TRUE;
}
elapsed = (rt_tick_t)(rt_tick_get() - g_sink_cc_wait_start[ch]);
@@ -331,6 +336,17 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch,
return RT_TRUE;
}
if (pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD) {
/* CC先设置完成后进入协议设置,不立即查询电压。 */
g_sink_query_throttle[ch] = RT_FALSE;
g_sink_query_first_pending[ch] = RT_FALSE;
g_sink_query_tick[ch] = 0U;
g_sink_cc_wait_mask &= (rt_uint8_t)~bit;
g_sink_cc_wait_start[ch] = 0U;
pSW->sub = IDX_SET_SINK_PD;
return RT_TRUE;
}
/* 协议已先设置;CC应答并完成保护等待后进入电压查询。 */
g_sink_query_throttle[ch] = RT_TRUE;
g_sink_query_first_pending[ch] = RT_TRUE;
@@ -591,6 +607,7 @@ static rt_uint8_t chrg_roll_nor_expected_cmd(const struct chrg_switch_t *pSW)
case IDX_SET_SINK_PD_ONLY:
return pSW->sink.protocol;
case IDX_SET_SINK_CCLINE:
case IDX_SET_SINK_CC_BEFORE_PD:
return SINK_CMD_SET_CC;
case IDX_SET_SINK_CCLVL:
return SINK_CMD_SET_LEVEL;
@@ -799,10 +816,14 @@ static int chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,
case IDX_SET_SINK_CCLINE: //CC线选择
*next_sub = IDX_WAIT_SINK_CC;
return sink_set_cc_line(pSW->sink.cc_set);
case IDX_SET_SINK_CC_BEFORE_PD:
*next_sub = IDX_WAIT_SINK_CC_BEFORE_PD;
return sink_set_cc_line(pSW->sink.cc_set);
case IDX_SET_SINK_CCLVL: //CC电平
return sink_set_cc_lvl(pSW->sink.cc_lvl);
case IDX_SET_SINK_PD:
*next_sub = IDX_SET_SINK_CCLINE;
/* CC已经在协议前完成设置,协议回码后直接查询电压。 */
*next_sub = IDX_GET_SINK_VC;
return chrg_roll_nor_sink_pro_set(pSW);
case IDX_SET_SINK_PD_ONLY:
*next_sub = IDX_GET_SINK_VC;
@@ -902,7 +923,8 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
/* 0xD0应答后每通道独立等待100ms,再连接目标CC。 */
chrg_roll_nor_source_protocol_wait_start(idx);
} else if ((expected_id == ID_SINK) &&
(request_sub == IDX_SET_SINK_CCLINE)) {
((request_sub == IDX_SET_SINK_CCLINE) ||
(request_sub == IDX_SET_SINK_CC_BEFORE_PD))) {
/* 北向Sink继电器保持接通,仅等待目标CC配置稳定。 */
chrg_roll_nor_sink_cc_wait_start(idx);
} else if ((expected_id == ID_SINK) &&
@@ -50,6 +50,8 @@ enum {
/* Sink北向事务状态追加在末尾,避免改变已有sub数值。 */
IDX_SET_SINK_PD_ONLY, // 仅重发协议,协议应答后直接查询协商电压
IDX_WAIT_SINK_CC, // CC设置应答后的非阻塞稳定等待
IDX_SET_SINK_CC_BEFORE_PD, // 先设置CC,稳定后再设置协议
IDX_WAIT_SINK_CC_BEFORE_PD, // 等待CC稳定后进入协议设置
};
struct chrg_rollnor_t {
+5 -5
View File
@@ -232,7 +232,7 @@ int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf)
输出参数: 立即打开北向Sink继电器和enable,并进入INIT_AUX_WAIT后台确认
返回说明: 0:初始化批次提交成功 <0:参数或命令提交失败
其它说明: 南向顺序为FU_REL_ON、CURRENT=0、MODE、VON和可选测试停止;
北向协议握手不等待南向回码,南北向从批次入队后并行执行
北向按“CC线->协议->电压查询”顺序执行,南北向从批次入队后并行执行
*****************************************************************/
static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
@@ -267,10 +267,10 @@ static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
pSW->sink.On_work = 1;
if (first_start) {
/* 南向批次已入队,北向按“协议->CC”顺序立即开始完整握手。 */
/* 南向批次已入队,北向按“CC->协议”顺序立即开始完整握手。 */
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SINK);
pNOR->enable[idx] = 1;
pSW->sub = IDX_SET_SINK_PD;
pSW->sub = IDX_SET_SINK_CC_BEFORE_PD;
}
pSW->sink.work_mode = SINK_WORK_INIT_AUX_WAIT;
return 0;
@@ -592,8 +592,8 @@ static int chrg_sink_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
/* 停止成功入队后,清除旧Source运行标志。 */
pSW->source.On_Flag = 0;
/* 首次进入Sink时先设置协议,协议应答后再设置目标CC线。 */
pSW->sub = IDX_SET_SINK_PD;
/* 首次进入Sink时先设置目标CC线,CC稳定后再设置协议。 */
pSW->sub = IDX_SET_SINK_CC_BEFORE_PD;
/* SWITCH只负责旧角色退出,后续启动统一交给Sink INIT状态。 */
pSW->sink.work_mode = SINK_WORK_INIT;
return 0;