修复了频繁切换电源PD协议会卡死的问题
refactor(chrg): 重构Source协议切换流程,替换CC断开为复位命令 1. 修改apps/chrg/applications/thread/chrg_north.c:新增SRC_CMD_RESET命令的帧长度校验 2. 修改apps/chrg/applications/thread/chrg_comm.h:新增chrg_comm_source_protocol_ack函数声明 3. 修改apps/chrg/applications/thread/chrg_north.h:开启北向UART调试打印 4. 修改apps/chrg/applications/utils/chrg_source.h:新增SRC_CMD_RESET命令码和source_reset函数声明 5. 修改apps/chrg/applications/thread/chrg_roll_nor.h:替换CC断开相关状态为复位状态 6. 修改apps/chrg/applications/utils/chrg_source.c:实现source_reset函数,修复PD参数硬编码问题 7. 修改apps/chrg/applications/thread/chrg_comm.c:新增协议状态缓存,重构协议切换判断逻辑 8. 修改apps/chrg/applications/thread/chrg_roll_nor.c:移除CC断开相关的共享等待逻辑,更新命令处理流程
This commit is contained in:
@@ -55,6 +55,28 @@ static rt_tick_t g_ymodem_c_tick = 0;
|
||||
static struct chrg_switch_t g_shadow_sw[TOTAL_NOR_CHS];
|
||||
static rt_uint8_t g_shadow_dirty[TOTAL_NOR_CHS] = {0}; /* 0=已生效 1=待生效,防止重复覆盖 */
|
||||
|
||||
/* Source协议类别缓存:0xFF表示本通道尚未成功下发过协议。 */
|
||||
#define SOURCE_PD_STATE_UNKNOWN 0xFFU
|
||||
#define SOURCE_PD_STATE_NON_PD 0x00U
|
||||
#define SOURCE_PD_STATE_PD 0x01U
|
||||
static rt_uint8_t last_pd_pro[TOTAL_NOR_CHS] = {
|
||||
SOURCE_PD_STATE_UNKNOWN, SOURCE_PD_STATE_UNKNOWN,
|
||||
SOURCE_PD_STATE_UNKNOWN, SOURCE_PD_STATE_UNKNOWN
|
||||
};
|
||||
|
||||
static rt_uint8_t chrg_comm_source_pd_state(rt_uint8_t protocol)
|
||||
{
|
||||
return ((protocol == PRO_PD0PSS) || (protocol == PRO_PD31AVS)) ?
|
||||
SOURCE_PD_STATE_PD : SOURCE_PD_STATE_NON_PD;
|
||||
}
|
||||
|
||||
void chrg_comm_source_protocol_ack(rt_uint8_t ch, rt_uint8_t protocol)
|
||||
{
|
||||
if (ch < TOTAL_NOR_CHS) {
|
||||
last_pd_pro[ch] = chrg_comm_source_pd_state(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Source和Sink共用的参数差异结果。前五项是两个角色都具备的控制属性,
|
||||
* pd_changed用于Source完整协议参数比较,后三项用于Sink快充协议配置。
|
||||
@@ -2519,9 +2541,8 @@ static eMBException chrg_comm_apply_source_effect(rt_uint8_t ch,
|
||||
rt_bool_t cc_changed;
|
||||
rt_bool_t north_config_changed;
|
||||
rt_bool_t protocol_switch_requested;
|
||||
rt_bool_t old_is_pd;
|
||||
rt_bool_t new_is_pd;
|
||||
rt_bool_t need_cc_close;
|
||||
rt_bool_t need_source_reset;
|
||||
rt_uint8_t new_pd_state;
|
||||
struct vc_pd_t old_pd_set;
|
||||
eSRC_PRO old_protocol = pReal->source.protocol;
|
||||
rt_uint8_t old_cc_set = pReal->source.CC_Set;
|
||||
@@ -2546,12 +2567,10 @@ static eMBException chrg_comm_apply_source_effect(rt_uint8_t ch,
|
||||
cc_changed = diff_info.cc_changed;
|
||||
north_config_changed = protocol_config_changed || cc_changed;
|
||||
protocol_switch_requested = north_config_changed;
|
||||
old_is_pd = (old_protocol == PRO_PD0PSS) ||
|
||||
(old_protocol == PRO_PD31AVS);
|
||||
new_is_pd = (pShadow->source.protocol == PRO_PD0PSS) ||
|
||||
(pShadow->source.protocol == PRO_PD31AVS);
|
||||
need_cc_close = (new_is_pd && north_config_changed) ||
|
||||
(old_is_pd && !new_is_pd && diff_info.protocol_changed);
|
||||
new_pd_state = chrg_comm_source_pd_state(
|
||||
(rt_uint8_t)pShadow->source.protocol);
|
||||
need_source_reset = (last_pd_pro[ch] != SOURCE_PD_STATE_UNKNOWN) &&
|
||||
(last_pd_pro[ch] != new_pd_state);
|
||||
target_curr = pShadow->source.pd_set.mm.max_cur;
|
||||
|
||||
/* 影子区只拥有COM配置;北向解析产生的运行目标和回读数据继续由pReal持有。 */
|
||||
@@ -2565,6 +2584,8 @@ static eMBException chrg_comm_apply_source_effect(rt_uint8_t ch,
|
||||
|
||||
if (source_work == 0x01) {
|
||||
if (pReal->source.On_Flag == 0) {
|
||||
/* 每次重新启动的第一次协议下发不发送复位。 */
|
||||
last_pd_pro[ch] = SOURCE_PD_STATE_UNKNOWN;
|
||||
/*
|
||||
* 停止状态启动不需要先断开CC,直接从设置协议开始;
|
||||
* 收到0xD0应答并等待保护时间后,再连接目标CC。
|
||||
@@ -2585,12 +2606,8 @@ static eMBException chrg_comm_apply_source_effect(rt_uint8_t ch,
|
||||
*/
|
||||
if (north_config_changed) {
|
||||
chrg_roll_nor_source_switch_reset(ch);
|
||||
if (need_cc_close) {
|
||||
pReal->sub = IDX_SET_SOURCE_CC_CLOSE;
|
||||
chrg_roll_nor_source_cc_close_register(ch);
|
||||
} else {
|
||||
pReal->sub = IDX_SET_SOURCE_PD;
|
||||
}
|
||||
pReal->sub = need_source_reset ?
|
||||
IDX_SET_SOURCE_RESET : IDX_SET_SOURCE_PD;
|
||||
}
|
||||
|
||||
pReal->source.work_mode = SOURCE_WORK_WAIT;
|
||||
@@ -2709,6 +2726,8 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset,
|
||||
chrg_roll_nor_source_switch_reset(ch);
|
||||
rt_memcpy(pReal, pSW, sizeof(struct chrg_switch_t));
|
||||
if (new_id == ID_SOURCE) {
|
||||
/* 角色重新切到Source后,首个协议命令不需要复位。 */
|
||||
last_pd_pro[ch] = SOURCE_PD_STATE_UNKNOWN;
|
||||
pReal->source.work_mode = SOURCE_WORK_SWITCH;
|
||||
switch_ret = chrg_source_work_state(ch, pReal);
|
||||
} else {
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
#define MB_HANDLERS_MAX (16)
|
||||
|
||||
/* 北向Source协议设置成功后,通知COM保存本通道的PD/非PD类别。 */
|
||||
extern void chrg_comm_source_protocol_ack(rt_uint8_t ch, rt_uint8_t protocol);
|
||||
|
||||
typedef enum {
|
||||
MB_REG_READ, /*!< Read register values and pass to protocol stack. */
|
||||
MB_REG_WRITE /*!< Update register values. */
|
||||
|
||||
@@ -471,6 +471,7 @@ static rt_bool_t chrg_north_frame_shape_valid(eIDX_ID id,
|
||||
if (id == ID_SOURCE) {
|
||||
if ((command == SRC_CMD_SET_CC_LEVEL) ||
|
||||
(command == SRC_CMD_SET_CC_CHOOSE) ||
|
||||
(command == SRC_CMD_RESET) ||
|
||||
(command == SRC_CMD_SET_PROTOCOL)) {
|
||||
return (length == MIN_FRAME_LENGTH) ? RT_TRUE : RT_FALSE;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define LEN_FRAME_HEAD (4) // [帧长, 0x00, id, 命令]
|
||||
#define MIN_FRAME_LENGTH (5) // 帧最短5字节
|
||||
#define WORK_MIN_VOLT 3000 // 工作电压下限,单位mV
|
||||
#define NORTH_FRAME_DEBUG 0x00 // 北向UART原始收发帧
|
||||
#define NORTH_FRAME_DEBUG 0x01 // 北向UART原始收发帧
|
||||
#define NORTH_SOURCE_DEBUG 0x00 // Source协议解析及组帧
|
||||
#define NORTH_SINK_DEBUG 0x00 // Sink协议解析及组帧
|
||||
#define SOUTH_FRAME_DEBUG 0x00 // 南向UART原始收发帧
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "chrg_source.h"
|
||||
#include "chrg_roll_nor.h"
|
||||
#include "chrg_roll_sou.h"
|
||||
#include "chrg_comm.h"
|
||||
#include "chrg_north.h"
|
||||
#include "chrg_switch.h"
|
||||
#include "chrg_utils.h"
|
||||
@@ -31,8 +32,6 @@
|
||||
#define NORTH_MEASURE_MAX_ATTEMPTS 1U // 0x20量测查询失败后直接留给下一轮轮询重发
|
||||
#define NORTH_RETRY_INTERVAL_MS 5U // 相同请求两次发送之间的保护间隔
|
||||
#define NORTH_POLL_INTERVAL_MS 10U // 一个通道事务结束后到下一通道的轮询间隔
|
||||
#define SOURCE_CC_CLOSE_VALUE 0x03U // 0x17命令参数:同时断开CC1和CC2
|
||||
#define SOURCE_CC_CLOSE_WAIT_MS 300U // 本轮所有CC_CLOSE应答后的共享保护时间
|
||||
#define SOURCE_PROTOCOL_WAIT_MS 100U // 每通道0xD0应答后的协议生效保护时间
|
||||
#define SINK_CC_WAIT_MS 50U // Sink设置目标CC应答后的非阻塞保护时间
|
||||
#define SINK_HANDSHAKE_FIRST_QUERY_DELAY_MS 50U // 协议/CC回码后首条0x20的等待时间
|
||||
@@ -53,10 +52,6 @@ struct chrg_rollnor_t chrgrollnor = {
|
||||
};
|
||||
|
||||
/* 所有参与CC_CLOSE的通道共享300ms屏障;协议等待仍按通道独立计时。 */
|
||||
static rt_uint8_t g_source_cc_close_pending_mask = 0U;
|
||||
static rt_uint8_t g_source_cc_close_acked_mask = 0U;
|
||||
static rt_bool_t g_source_cc_close_wait_active = RT_FALSE;
|
||||
static rt_tick_t g_source_cc_close_wait_start = 0U;
|
||||
static rt_uint8_t g_source_protocol_wait_mask = 0U;
|
||||
static rt_tick_t g_source_protocol_wait_start[TOTAL_NOR_CHS] = {0};
|
||||
static rt_uint8_t g_sink_cc_wait_mask = 0U;
|
||||
@@ -114,25 +109,12 @@ static void chrg_roll_nor_sink_query_wait_start(rt_uint8_t ch)
|
||||
*****************************************************************/
|
||||
void chrg_roll_nor_source_switch_reset(rt_uint8_t ch)
|
||||
{
|
||||
rt_uint8_t bit;
|
||||
|
||||
if (ch >= TOTAL_NOR_CHS) {
|
||||
return;
|
||||
}
|
||||
bit = SOURCE_CHANNEL_BIT(ch);
|
||||
g_source_cc_close_pending_mask &= (rt_uint8_t)~bit;
|
||||
g_source_cc_close_acked_mask &= (rt_uint8_t)~bit;
|
||||
g_source_protocol_wait_mask &= (rt_uint8_t)~bit;
|
||||
g_source_protocol_wait_mask &=
|
||||
(rt_uint8_t)~SOURCE_CHANNEL_BIT(ch);
|
||||
g_source_protocol_wait_start[ch] = 0U;
|
||||
if (g_source_cc_close_pending_mask == 0U) {
|
||||
g_source_cc_close_wait_active = RT_FALSE;
|
||||
g_source_cc_close_wait_start = 0U;
|
||||
} else if (!g_source_cc_close_wait_active &&
|
||||
((g_source_cc_close_acked_mask & g_source_cc_close_pending_mask) ==
|
||||
g_source_cc_close_pending_mask)) {
|
||||
g_source_cc_close_wait_active = RT_TRUE;
|
||||
g_source_cc_close_wait_start = rt_tick_get();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
@@ -143,41 +125,6 @@ void chrg_roll_nor_source_switch_reset(rt_uint8_t ch)
|
||||
返回说明: -
|
||||
其它说明: 新通道加入已经开始的屏障时重新等待,保证所有登记通道共享完整保护时间
|
||||
*****************************************************************/
|
||||
void chrg_roll_nor_source_cc_close_register(rt_uint8_t ch)
|
||||
{
|
||||
rt_uint8_t bit;
|
||||
|
||||
if (ch >= TOTAL_NOR_CHS) {
|
||||
return;
|
||||
}
|
||||
bit = SOURCE_CHANNEL_BIT(ch);
|
||||
g_source_cc_close_pending_mask |= bit;
|
||||
g_source_cc_close_acked_mask &= (rt_uint8_t)~bit;
|
||||
g_source_protocol_wait_mask &= (rt_uint8_t)~bit;
|
||||
g_source_cc_close_wait_active = RT_FALSE;
|
||||
g_source_cc_close_wait_start = 0U;
|
||||
}
|
||||
|
||||
static void chrg_roll_nor_source_cc_close_ack(rt_uint8_t ch)
|
||||
{
|
||||
rt_uint8_t bit;
|
||||
|
||||
if (ch >= TOTAL_NOR_CHS) {
|
||||
return;
|
||||
}
|
||||
bit = SOURCE_CHANNEL_BIT(ch);
|
||||
if ((g_source_cc_close_pending_mask & bit) == 0U) {
|
||||
return;
|
||||
}
|
||||
g_source_cc_close_acked_mask |= bit;
|
||||
if (!g_source_cc_close_wait_active &&
|
||||
((g_source_cc_close_acked_mask & g_source_cc_close_pending_mask) ==
|
||||
g_source_cc_close_pending_mask)) {
|
||||
g_source_cc_close_wait_active = RT_TRUE;
|
||||
g_source_cc_close_wait_start = rt_tick_get();
|
||||
}
|
||||
}
|
||||
|
||||
static void chrg_roll_nor_source_protocol_wait_start(rt_uint8_t ch)
|
||||
{
|
||||
if (ch >= TOTAL_NOR_CHS) {
|
||||
@@ -211,23 +158,6 @@ static rt_bool_t chrg_roll_nor_source_wait_process(rt_uint8_t ch,
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
if (pSW->sub == IDX_WAIT_SOURCE_CC_CLOSE) {
|
||||
if ((g_source_cc_close_pending_mask & bit) == 0U) {
|
||||
pSW->sub = IDX_SET_SOURCE_PD;
|
||||
return RT_FALSE;
|
||||
}
|
||||
if (!g_source_cc_close_wait_active) {
|
||||
return RT_TRUE;
|
||||
}
|
||||
elapsed = (rt_tick_t)(rt_tick_get() - g_source_cc_close_wait_start);
|
||||
if (elapsed < rt_tick_from_millisecond(SOURCE_CC_CLOSE_WAIT_MS)) {
|
||||
return RT_TRUE;
|
||||
}
|
||||
chrg_roll_nor_source_switch_reset(ch);
|
||||
pSW->sub = IDX_SET_SOURCE_PD;
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
if (pSW->sub == IDX_WAIT_SOURCE_PROTOCOL) {
|
||||
if ((g_source_protocol_wait_mask & bit) == 0U) {
|
||||
pSW->sub = IDX_SET_SOURCE_CC_SET;
|
||||
@@ -592,7 +522,8 @@ static rt_uint8_t chrg_roll_nor_expected_cmd(const struct chrg_switch_t *pSW)
|
||||
return SRC_CMD_GET_PROTOCOL;
|
||||
case IDX_SET_SOURCE_PD:
|
||||
return SRC_CMD_SET_PROTOCOL;
|
||||
case IDX_SET_SOURCE_CC_CLOSE:
|
||||
case IDX_SET_SOURCE_RESET:
|
||||
return SRC_CMD_RESET;
|
||||
case IDX_SET_SOURCE_CC_SET:
|
||||
return SRC_CMD_SET_CC_CHOOSE;
|
||||
case IDX_SET_SOURCE_CCLVL:
|
||||
@@ -793,9 +724,9 @@ static int chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,
|
||||
if(pSW->id==ID_SOURCE){ //电源
|
||||
chrg_roll_nor_sw_uart((eIDX_NOR_CH)ch, ID_SOURCE);
|
||||
switch(pSW->sub){
|
||||
case IDX_SET_SOURCE_CC_CLOSE:
|
||||
*next_sub = IDX_WAIT_SOURCE_CC_CLOSE;
|
||||
return source_set_cc_choose(SOURCE_CC_CLOSE_VALUE);
|
||||
case IDX_SET_SOURCE_RESET:
|
||||
*next_sub = IDX_SET_SOURCE_PD;
|
||||
return source_reset();
|
||||
case IDX_SET_SOURCE_PD:
|
||||
*next_sub = IDX_WAIT_SOURCE_PROTOCOL;
|
||||
return chrg_roll_nor_source_pro_set(pSW);
|
||||
@@ -936,13 +867,14 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
|
||||
}
|
||||
/* ID、命令、CRC和配置版本均确认有效后,才正式推进实时sub。 */
|
||||
if ((expected_id == ID_SOURCE) &&
|
||||
(request_sub == IDX_SET_SOURCE_CC_CLOSE)) {
|
||||
(request_sub == IDX_SET_SOURCE_RESET)) {
|
||||
/* 参与通道全部收到0x17=3应答后,共享一次300ms保护等待。 */
|
||||
chrg_roll_nor_source_cc_close_ack(idx);
|
||||
} else if ((expected_id == ID_SOURCE) &&
|
||||
(request_sub == IDX_SET_SOURCE_PD)) {
|
||||
/* 0xD0应答后每通道独立等待100ms,再连接目标CC。 */
|
||||
chrg_roll_nor_source_protocol_wait_start(idx);
|
||||
chrg_comm_source_protocol_ack(idx,
|
||||
(rt_uint8_t)pSW->source.protocol);
|
||||
} else if ((expected_id == ID_SINK) &&
|
||||
((request_sub == IDX_SET_SINK_CCLINE) ||
|
||||
(request_sub == IDX_SET_SINK_CC_BEFORE_PD))) {
|
||||
|
||||
@@ -43,8 +43,7 @@ enum {
|
||||
IDX_SET_SINK_STORP_WAIT,
|
||||
|
||||
/* Source北向事务状态,追加在末尾以保持原有sub数值不变。 */
|
||||
IDX_SET_SOURCE_CC_CLOSE, // 协议切换前发送0x17=0x03断开CC
|
||||
IDX_WAIT_SOURCE_CC_CLOSE, // 等待参与切换的Source通道完成共享保护时间
|
||||
IDX_SET_SOURCE_RESET, // PD与非PD协议跨类切换前发送Source复位
|
||||
IDX_WAIT_SOURCE_PROTOCOL, // 0xD0应答后的协议生效等待
|
||||
|
||||
/* Sink北向事务状态追加在末尾,避免改变已有sub数值。 */
|
||||
@@ -105,8 +104,6 @@ extern void roll_nor_set(void);
|
||||
返回说明: -
|
||||
其它说明: 仅需要在协议切换入口为IDX_SET_SOURCE_CC_CLOSE时调用
|
||||
*****************************************************************/
|
||||
extern void chrg_roll_nor_source_cc_close_register(rt_uint8_t ch);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_roll_nor_source_switch_reset
|
||||
函数描述: 清理指定Source通道的CC_CLOSE及协议等待记录
|
||||
|
||||
@@ -148,7 +148,7 @@ static int chrg_source_work_protocol_switch(eIDX_SOU_CH idx,
|
||||
int ret;
|
||||
|
||||
if ((pSW->sub != IDX_SET_SOURCE_PD) &&
|
||||
(pSW->sub != IDX_SET_SOURCE_CC_CLOSE)) {
|
||||
(pSW->sub != IDX_SET_SOURCE_RESET)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -316,6 +316,18 @@ int source_get_pd (void)
|
||||
return chrg_north_send(frame, len);
|
||||
}
|
||||
|
||||
int source_reset (void)
|
||||
{
|
||||
rt_uint16_t len = 0;
|
||||
rt_uint8_t data[8] = {0};
|
||||
rt_uint8_t frame[16] = {0};
|
||||
|
||||
data[0] = 0x00;
|
||||
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_RESET, data, 1, frame, &len);
|
||||
|
||||
return chrg_north_send(frame, len);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: source_set_cc_lvl
|
||||
函数描述: source 设置 cc 等级
|
||||
@@ -1017,8 +1029,8 @@ rt_uint8_t pd_fill_single_group_no_src_com(rt_uint8_t *data, rt_uint8_t start_id
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
// 2. 最小电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = mm->min_vol >> 8;
|
||||
data[idx++] = mm->min_vol & 0xFF;
|
||||
data[idx++] = 0x13;//mm->min_vol >> 8;
|
||||
data[idx++] = 0x18;//mm->min_vol & 0xFF;
|
||||
// 3. 最大电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = mm->max_vol >> 8;
|
||||
data[idx++] = mm->max_vol & 0xFF;
|
||||
|
||||
@@ -25,6 +25,8 @@ struct chrg_switch_t;
|
||||
|
||||
#define SRC_CMD_SET_CC_CHOOSE 0x17
|
||||
|
||||
#define SRC_CMD_RESET 0x18
|
||||
|
||||
#define SRC_CMD_SET_PROTOCOL 0xD0
|
||||
|
||||
#define PROTOCOL_NONE 0x00 // 无快充
|
||||
@@ -192,6 +194,8 @@ extern int source_get_vc (rt_uint16_t vol, rt_uint16_t cur);
|
||||
*****************************************************************/
|
||||
extern int source_get_pd (void);
|
||||
|
||||
extern int source_reset (void);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: source_set_cc_lvl
|
||||
函数描述: source 设置 cc 等级
|
||||
|
||||
Reference in New Issue
Block a user