chrg: 完成V1.1.31版本迭代更新
1. 更新各文件版本号至V1.1.31,固件版本寄存器设为0x012F 2. 南向通道选通:仅在GPIO选通成功后才更新物理通道缓存 3. 重构寄存器地址解码逻辑,统一0x06/0x10功能码的地址校验 4. 新增功率板短路/OCP/动态测试状态定义0x05/0x06/0x07 5. 移除电流命令覆盖逻辑,改为按顺序排队等待回码 6. 优化轮询线程:每次发送前重新选通通道,选通失败则跳过当前任务 7. 新增测试态退出确认流程,初始化和关机时需确认功率板退出测试态 8. 增加跨通道写入保护,拒绝多寄存器写跨通道操作 9. 补充多处中文注释,优化调试日志输出格式
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_comm.c
|
||||
完成日期 :
|
||||
当前版本号 : V1.1.26
|
||||
当前版本号 : V1.1.31
|
||||
主要功能 : 实现对外通讯协议 MODBUS 服务端,以独立线程等待处理响应请求数据。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -955,6 +955,41 @@ static rt_uint16_t src_type_lookup(rt_uint16_t reg_val,struct chrg_switch_t *pSW
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************
|
||||
函数名称: chrg_comm_reg_decode
|
||||
函数描述: 将上位机分区地址解码为0起始通道号和通道内寄存器偏移
|
||||
输入参数: partition:分区高字节 address:分区低字节地址
|
||||
ch:通道输出 reg_offset:通道内偏移输出
|
||||
输出参数: ch、reg_offset
|
||||
返回说明: 0:地址有效 <0:分区、地址或参数无效
|
||||
其它说明: 统一供0x06和0x10使用,避免两条写入路径采用不同通道算法
|
||||
*****************************************************************/
|
||||
static int chrg_comm_reg_decode(rt_uint8_t partition,
|
||||
rt_uint16_t address, eIDX_SOU_CH *ch, rt_uint16_t *reg_offset)
|
||||
{
|
||||
rt_uint16_t regs_per_channel;
|
||||
|
||||
if ((ch == RT_NULL) || (reg_offset == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (partition == HOLD_REG_SINK_BASE) {
|
||||
regs_per_channel = TOTAL_SINK_CH_REGS;
|
||||
} else if (partition == HOLD_REG_SRC_BASE) {
|
||||
regs_per_channel = TOTAL_SRC_CH_REGS;
|
||||
} else if (partition == HOLD_REG_SYS_BASE) {
|
||||
regs_per_channel = TOTAL_SYS_CH_REGS;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (address >= (regs_per_channel * TOTAL_SOU_CHS)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ch = (eIDX_SOU_CH)(address / regs_per_channel);
|
||||
*reg_offset = address % regs_per_channel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: funcWriteHoldingRegister
|
||||
函数描述: 写单个保持寄存器(0x06功能码)
|
||||
@@ -963,7 +998,7 @@ static rt_uint16_t src_type_lookup(rt_uint16_t reg_val,struct chrg_switch_t *pSW
|
||||
输出参数: -
|
||||
返回说明: MB_EX_NONE=成功, 其他=Modbus异常码
|
||||
其它说明: 新协议采用标准0x06功能码,寄存器地址区分功能区块:
|
||||
0x0000~0x0073 负载, 0x0080~0x0097 电源, 0x00A0~0x00A7 系统
|
||||
高字节选择分区,低字节按每通道50个地址计算通道和寄存器偏移
|
||||
*****************************************************************/
|
||||
eMBException funcWriteHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
|
||||
rt_uint8_t *resFrame, rt_uint16_t *resLen)
|
||||
@@ -975,8 +1010,9 @@ eMBException funcWriteHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
|
||||
rt_uint8_t regAddress_H = 0;
|
||||
rt_uint16_t sou_value = 0;
|
||||
/* ---- 提取通道号和区块内偏移 ---- */
|
||||
eIDX_SOU_CH ch;
|
||||
rt_uint16_t reg_offset; // 区块内寄存器偏移
|
||||
/* 使用越界枚举作为无效初值,禁止地址校验失败后误用随机通道。 */
|
||||
eIDX_SOU_CH ch = TOTAL_SOU_CHS;
|
||||
rt_uint16_t reg_offset = 0; // 区块内寄存器偏移
|
||||
|
||||
eMBException eStatus = MB_EX_NONE;
|
||||
eMBErrorCode eRegStatus;
|
||||
@@ -1010,26 +1046,8 @@ eMBException funcWriteHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
|
||||
}
|
||||
|
||||
/* ---- 地址范围校验 ---- */
|
||||
if(regAddress_H == HOLD_REG_SINK_BASE){
|
||||
if (REG_IS_SINK(regAddress)) {
|
||||
ch = (eIDX_SOU_CH)REG_GET_SINK_CH(regAddress);
|
||||
reg_offset = REG_GET_SINK_OFFSET(regAddress);
|
||||
}
|
||||
}else if (regAddress_H == HOLD_REG_SRC_BASE) {
|
||||
if (REG_IS_SRC(regAddress)) {
|
||||
ch = (eIDX_SOU_CH)REG_GET_SRC_CH(regAddress);
|
||||
reg_offset = REG_GET_SRC_OFFSET(regAddress);
|
||||
}
|
||||
} else if (regAddress_H == HOLD_REG_SYS_BASE) {
|
||||
if (REG_IS_SYS(regAddress)) {
|
||||
ch = (eIDX_SOU_CH)REG_GET_SYS_CH(regAddress);
|
||||
reg_offset = REG_GET_SYS_OFFSET(regAddress);
|
||||
}
|
||||
} else {
|
||||
return MB_EX_ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
|
||||
if (ch > IDX_SOU_CH4) {
|
||||
if (chrg_comm_reg_decode(regAddress_H, regAddress,
|
||||
&ch, ®_offset) != 0) {
|
||||
return MB_EX_ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
|
||||
@@ -1139,6 +1157,11 @@ eMBException funcWriteMultipleHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t
|
||||
#else
|
||||
rt_uint8_t regAddress_H = 0;
|
||||
rt_uint16_t regBaseOffset = 0;
|
||||
rt_uint16_t regEndOffset = 0;
|
||||
rt_uint16_t first_reg_offset = 0;
|
||||
rt_uint16_t last_reg_offset = 0;
|
||||
eIDX_SOU_CH first_ch = TOTAL_SOU_CHS;
|
||||
eIDX_SOU_CH last_ch = TOTAL_SOU_CHS;
|
||||
#endif
|
||||
|
||||
// ========== 公共校验逻辑(只写一遍)==========
|
||||
@@ -1211,17 +1234,21 @@ eMBException funcWriteMultipleHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t
|
||||
// 正常产品模式:分区地址逻辑
|
||||
regAddress_H = reqFrame[2];
|
||||
regBaseOffset = reqFrame[3];
|
||||
regEndOffset = regBaseOffset + cntReg - 1U;
|
||||
/* 起止地址必须属于同一有效通道,禁止一帧0x10跨通道改写参数。 */
|
||||
if ((chrg_comm_reg_decode(regAddress_H, regBaseOffset,
|
||||
&first_ch, &first_reg_offset) != 0) ||
|
||||
(chrg_comm_reg_decode(regAddress_H, regEndOffset,
|
||||
&last_ch, &last_reg_offset) != 0) ||
|
||||
(first_ch != last_ch) ||
|
||||
(last_reg_offset != (first_reg_offset + cntReg - 1U))) {
|
||||
return MB_EX_ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cntReg; i++)
|
||||
{
|
||||
rt_uint16_t curr_part_offset = regBaseOffset + i;
|
||||
eIDX_SOU_CH ch = (eIDX_SOU_CH)(curr_part_offset / TOTAL_HOLD_CH_REGS);
|
||||
rt_uint16_t ch_reg_offset = curr_part_offset % TOTAL_HOLD_CH_REGS;
|
||||
|
||||
if (ch > IDX_SOU_CH4) {
|
||||
//rt_kprintf("WRITE MULTI REG: CH ERROR, ch=%d (part offset=%d)\n", ch, curr_part_offset);
|
||||
return MB_EX_ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
eIDX_SOU_CH ch = first_ch;
|
||||
rt_uint16_t ch_reg_offset = first_reg_offset + i;
|
||||
pSW = &g_shadow_sw[ch];
|
||||
chrg_shadow_sync(ch); // 首次写同步真实状态
|
||||
rt_uint16_t sou_value = u8v_to_u16(&pWriteData[i * 2]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_comm.h
|
||||
完成日期 :
|
||||
当前版本号 : V1.1.24
|
||||
当前版本号 : V1.1.31
|
||||
主要功能 : 实现对外通讯协议 MODBUS 服务端,以独立线程等待处理响应请求数据。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -40,10 +40,10 @@ typedef enum {
|
||||
// ========== 新寄存器地址映射 (使用0x06/0x10标准Modbus功能码) ==========
|
||||
// 详细寄存器偏移定义见 chrg_regs.h
|
||||
|
||||
// 判断寄存器地址属于哪个区块的宏
|
||||
#define REG_IS_SINK(addr) (((addr / 4) < TOTAL_SINK_CH_REGS))
|
||||
#define REG_IS_SRC(addr) (((addr / 4) < TOTAL_SRC_CH_REGS))
|
||||
#define REG_IS_SYS(addr) (((addr / 4) < TOTAL_SYS_CH_REGS))
|
||||
// 分区低字节按4通道连续排列,每通道占用TOTAL_xxx_CH_REGS个地址
|
||||
#define REG_IS_SINK(addr) ((addr) < (TOTAL_SINK_CH_REGS * 4U))
|
||||
#define REG_IS_SRC(addr) ((addr) < (TOTAL_SRC_CH_REGS * 4U))
|
||||
#define REG_IS_SYS(addr) ((addr) < (TOTAL_SYS_CH_REGS * 4U))
|
||||
|
||||
// 根据地址提取通道号和区块内偏移
|
||||
#define REG_GET_SINK_CH(addr) ((addr) / TOTAL_SINK_CH_REGS)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_roll_sou.c
|
||||
完成日期 :
|
||||
当前版本号 : V1.1.24
|
||||
当前版本号 : V1.1.31
|
||||
主要功能 : 实现南向通信轮巡请求命令。以独立线程处理。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -168,23 +168,7 @@ int chrg_sou_com_batch_submit(eIDX_SOU_CH ch, const rt_uint16_t *regs,
|
||||
pBatch->cur_idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 电流调节采用最新值有效策略。若同一通道仍有尚未发送的电流命令,
|
||||
* 直接覆盖旧值,避免四通道快速测试时队列积累过时的电流设置。
|
||||
* 当前命令已经发送时不覆盖,保证响应仍与原命令匹配。
|
||||
*/
|
||||
if ((count == 1) && (regs[0] == (REG_CURRENT_OUT + 1))) {
|
||||
for (i = pBatch->cur_idx; i < pBatch->reg_cnt; i++) {
|
||||
if (pBatch->reg_list[i] == regs[0]) {
|
||||
pBatch->val_list[i] = vals[0];
|
||||
pBatch->pending = RT_TRUE;
|
||||
pROLL->run = RUN_COM;
|
||||
rt_mutex_release(pTHR->mutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 电流命令与其它写命令一致,完整追加并等待回码,不再覆盖旧命令。 */
|
||||
if ((pBatch->reg_cnt > SOU_COM_BATCH_REG_MAX) ||
|
||||
(count > (SOU_COM_BATCH_REG_MAX - pBatch->reg_cnt))) {
|
||||
LOG_E("sou com batch reg full: ch=%d queued=%d append=%d max=%d",
|
||||
@@ -923,10 +907,13 @@ void chrg_roll_sou_thread_entry (void *data)
|
||||
measure_once = RT_TRUE;
|
||||
response_part = MB_R_PART1;
|
||||
chrg_led_flashing(IDX_LED3, TIMES_ONE, PULSE_TIME*2, PULSE_TIME*2);
|
||||
if (idx != (rt_uint8_t)pROLL->idx) {
|
||||
pROLL->idx = (eIDX_SOU_CH)idx;
|
||||
chrg_south_switch((eIDX_SOU_CH)idx);
|
||||
/* 插入命令可能改变物理选通,每次自动查询前必须重新选择通道。 */
|
||||
if (chrg_south_switch((eIDX_SOU_CH)idx) != 0) {
|
||||
sou_measure_once_finish(idx);
|
||||
rt_thread_mdelay(1);
|
||||
continue;
|
||||
}
|
||||
pROLL->idx = (eIDX_SOU_CH)idx;
|
||||
if (g_sou_version_ready[idx] == 0U) {
|
||||
version_probe = RT_TRUE;
|
||||
chrg_eload_read_version(ID_ELOAD);
|
||||
@@ -943,11 +930,14 @@ void chrg_roll_sou_thread_entry (void *data)
|
||||
continue;
|
||||
} else { // 通道启用
|
||||
chrg_led_flashing(IDX_LED3, TIMES_ONE, PULSE_TIME*2, PULSE_TIME*2);
|
||||
if (idx != (rt_uint8_t)pROLL->idx) {
|
||||
pROLL->idx = (eIDX_SOU_CH)idx;
|
||||
chrg_south_switch((eIDX_SOU_CH)idx);
|
||||
pROLL->part = MB_R_PART1;
|
||||
/* 不信任缓存通道,发送普通轮询前重新写入选通GPIO。 */
|
||||
if (chrg_south_switch((eIDX_SOU_CH)idx) != 0) {
|
||||
CHRG_CHANNEL_NEXT(index);
|
||||
rt_thread_mdelay(1);
|
||||
continue;
|
||||
}
|
||||
pROLL->idx = (eIDX_SOU_CH)idx;
|
||||
pROLL->part = response_part;
|
||||
if (g_sou_version_ready[idx] == 0U) {
|
||||
version_probe = RT_TRUE;
|
||||
chrg_eload_read_version(ID_ELOAD);
|
||||
@@ -962,7 +952,11 @@ void chrg_roll_sou_thread_entry (void *data)
|
||||
break;
|
||||
|
||||
case RUN_LCD: {
|
||||
chrg_south_switch((eIDX_SOU_CH)single_ch);
|
||||
if (chrg_south_switch((eIDX_SOU_CH)single_ch) != 0) {
|
||||
sou_single_command_finish(run);
|
||||
continue;
|
||||
}
|
||||
pROLL->idx = (eIDX_SOU_CH)single_ch;
|
||||
chrg_eload_write_reg(ID_ELOAD, single_reg, single_value);
|
||||
}
|
||||
break;
|
||||
@@ -976,9 +970,17 @@ void chrg_roll_sou_thread_entry (void *data)
|
||||
}
|
||||
batch_ch = command_ch;
|
||||
command_valid = RT_TRUE;
|
||||
chrg_south_switch((eIDX_SOU_CH)command_ch);
|
||||
/* COM队列通道必须与物理选通一致,选通失败时禁止发送本条命令。 */
|
||||
if (chrg_south_switch((eIDX_SOU_CH)command_ch) != 0) {
|
||||
sou_com_command_failed(batch_ch, command_reg, command_value,
|
||||
"channel switch", &retry_count[batch_ch]);
|
||||
continue;
|
||||
}
|
||||
pROLL->idx = (eIDX_SOU_CH)command_ch;
|
||||
#if SOUTH_COMMAND_DEBUG
|
||||
rt_kprintf("ch=%d",command_ch);
|
||||
rt_kprintf("[SOU_CMD] queue_ch=%u phy_ch=%u reg=0x%04X value=%u\r\n",
|
||||
command_ch + 1U, chrgsouth.idx + 1U,
|
||||
command_reg, command_value);
|
||||
#endif
|
||||
chrg_eload_write_reg(ID_ELOAD, command_reg, command_value);
|
||||
}
|
||||
@@ -995,7 +997,14 @@ void chrg_roll_sou_thread_entry (void *data)
|
||||
rt_thread_mdelay(1);
|
||||
continue;
|
||||
}
|
||||
chrg_south_switch((eIDX_SOU_CH)single_ch);
|
||||
if (chrg_south_switch((eIDX_SOU_CH)single_ch) != 0) {
|
||||
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
|
||||
pROLL->updata_result = -1;
|
||||
pROLL->send_flag = 0;
|
||||
rt_mutex_release(pTHR->mutex);
|
||||
continue;
|
||||
}
|
||||
pROLL->idx = (eIDX_SOU_CH)single_ch;
|
||||
ret = chrg_eload_send_ymodem_data(pROLL->updata_buf, pROLL->leng);
|
||||
|
||||
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
|
||||
@@ -1007,7 +1016,11 @@ void chrg_roll_sou_thread_entry (void *data)
|
||||
}
|
||||
|
||||
case RUN_CONSOLE: {
|
||||
chrg_south_switch((eIDX_SOU_CH)single_ch);
|
||||
if (chrg_south_switch((eIDX_SOU_CH)single_ch) != 0) {
|
||||
sou_single_command_finish(run);
|
||||
continue;
|
||||
}
|
||||
pROLL->idx = (eIDX_SOU_CH)single_ch;
|
||||
chrg_eload_refresh(ID_ELOAD, single_part);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_south.c
|
||||
完成日期 :
|
||||
当前版本号 : V1.1.24
|
||||
当前版本号 : V1.1.31
|
||||
主要功能 : 实现南向通信交互,包括接收命令解析,发送请求命令,切换通路。以独立线程处理。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -141,6 +141,10 @@ int chrg_south_switch (eIDX_SOU_CH ch)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/* 仅在GPIO选通成功后更新物理通道,供发送日志和轮询校验使用。 */
|
||||
if (ret == 0) {
|
||||
chrgsouth.idx = ch;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_eload.h
|
||||
完成日期 :
|
||||
当前版本号 : V1.1.24
|
||||
当前版本号 : V1.1.28
|
||||
主要功能 : 源载命令数据解析,封装,读写请求,寄存器定义,数据结构定义。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -61,6 +61,9 @@ static const rt_uint8_t LOAD[30] = {
|
||||
#define STA1_READY (0x01) // 就绪/停止
|
||||
#define STA1_RUNNING (0x02) // 运行
|
||||
#define STA1_FAULT (0x03) // 故障
|
||||
#define STA1_SHORT_TEST (0x05) // 短路测试中
|
||||
#define STA1_OCP_TEST (0x06) // OCP测试中
|
||||
#define STA1_DYNA_TEST (0x07) // 动态测试中
|
||||
#define REG_CV 0X07 // 电压地址
|
||||
|
||||
#define REG_REL_ON (0X01) // 主继电器控制寄存器
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_sink.c
|
||||
完成日期 :
|
||||
当前版本号 : V1.1.26
|
||||
当前版本号 : V1.1.28
|
||||
主要功能 : 北向数据sink请求数据填充及发送。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -25,11 +25,13 @@
|
||||
#define SINK_UNLOAD_CONFIRM_COUNT 2U // 连续满足低电流条件的量测帧数
|
||||
#define SINK_SHORT_KEEPALIVE_MS 30U // 短路测试WORK_START保活下发周期
|
||||
#define SINK_INIT_NORTH_RELAY_DELAY_MS 30U // 辅助继电器回码后打开北向继电器的等待时间
|
||||
#define SINK_TEST_STATUS_RETRY_MAX 3U // 测试态退出确认的连续重发计数上限
|
||||
|
||||
#define SINK_INIT_STAGE_CLEAR_RELAY 0U
|
||||
#define SINK_INIT_STAGE_AUX_RELAY 1U
|
||||
#define SINK_INIT_STAGE_DELAY 2U
|
||||
#define SINK_INIT_STAGE_REST 3U
|
||||
#define SINK_INIT_STAGE_TEST_STOP 0U
|
||||
#define SINK_INIT_STAGE_TEST_STATUS 1U
|
||||
#define SINK_INIT_STAGE_AUX_RELAY 2U
|
||||
#define SINK_INIT_STAGE_DELAY 3U
|
||||
#define SINK_INIT_STAGE_REST 4U
|
||||
|
||||
static rt_uint8_t g_sink_init_stage[TOTAL_SOU_CHS] = {0};
|
||||
static rt_tick_t g_sink_init_north_relay_tick[TOTAL_SOU_CHS] = {0};
|
||||
@@ -61,6 +63,43 @@ static rt_uint32_t g_sink_von_voltage_seq[TOTAL_SOU_CHS] = {0};
|
||||
static rt_uint8_t g_sink_von_stable_count[TOTAL_SOU_CHS] = {0};
|
||||
/* 自动停止带载后的恢复确认计数,独立于首次握手的电压确认计数。 */
|
||||
static rt_uint8_t g_sink_load_restart_confirm_count[TOTAL_SOU_CHS] = {0};
|
||||
static rt_uint32_t g_sink_init_test_sample_seq[TOTAL_SOU_CHS] = {0};
|
||||
static rt_uint8_t g_sink_init_test_stop_retry[TOTAL_SOU_CHS] = {0};
|
||||
static rt_uint32_t g_sink_stop_test_sample_seq[TOTAL_SOU_CHS] = {0};
|
||||
static rt_uint8_t g_sink_stop_test_stop_retry[TOTAL_SOU_CHS] = {0};
|
||||
static rt_bool_t g_sink_stop_test_confirmed[TOTAL_SOU_CHS] = {RT_FALSE};
|
||||
|
||||
static rt_uint8_t chrg_sink_power_status_get(eIDX_SOU_CH idx)
|
||||
{
|
||||
rt_uint16_t status1;
|
||||
|
||||
if (idx >= TOTAL_SOU_CHS) {
|
||||
return 0U;
|
||||
}
|
||||
status1 = chrgsouth.eload[idx].status1;
|
||||
if (((status1 & 0x00FFU) == 0U) && ((status1 >> 8) != 0U)) {
|
||||
status1 >>= 8;
|
||||
}
|
||||
return (rt_uint8_t)status1;
|
||||
}
|
||||
|
||||
static rt_bool_t chrg_sink_power_test_active(eIDX_SOU_CH idx)
|
||||
{
|
||||
rt_uint8_t status1 = chrg_sink_power_status_get(idx);
|
||||
|
||||
return (status1 == STA1_SHORT_TEST) ||
|
||||
(status1 == STA1_OCP_TEST) ||
|
||||
(status1 == STA1_DYNA_TEST);
|
||||
}
|
||||
|
||||
static rt_bool_t chrg_sink_test_exit_required(eIDX_SOU_CH idx,
|
||||
const struct chrg_switch_t *pSW)
|
||||
{
|
||||
return chrg_sink_power_test_active(idx) ||
|
||||
((pSW != RT_NULL) &&
|
||||
((pSW->sink.test.test_mode != SINK_NO_TEST) ||
|
||||
(pSW->sink.test.test_mode_old != SINK_NO_TEST)));
|
||||
}
|
||||
|
||||
enum {
|
||||
SINK_UNLOAD_NEXT_RUNNING = 0,
|
||||
@@ -304,7 +343,7 @@ static int chrg_sink_init_submit_stage(eIDX_SOU_CH idx,
|
||||
total = chrg_sink_init_build_commands(pSW, regs, vals);
|
||||
|
||||
switch (g_sink_init_stage[idx]) {
|
||||
case SINK_INIT_STAGE_CLEAR_RELAY:
|
||||
case SINK_INIT_STAGE_TEST_STOP:
|
||||
start = 0U;
|
||||
count = 1U;
|
||||
break;
|
||||
@@ -344,7 +383,11 @@ static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
|
||||
return -1;
|
||||
}
|
||||
g_sink_init_in_progress[idx] = RT_TRUE;
|
||||
g_sink_init_stage[idx] = SINK_INIT_STAGE_CLEAR_RELAY;
|
||||
/* 功率板回读处于Short/OCP/DYNA时,先用WORK_STOP退出测试态。 */
|
||||
g_sink_init_stage[idx] = chrg_sink_test_exit_required(idx, pSW) ?
|
||||
SINK_INIT_STAGE_TEST_STOP : SINK_INIT_STAGE_AUX_RELAY;
|
||||
g_sink_init_test_sample_seq[idx] = 0U;
|
||||
g_sink_init_test_stop_retry[idx] = 0U;
|
||||
g_sink_init_north_relay_tick[idx] = 0U;
|
||||
/* 入队失败也保留事务和等待入口,由等待分支持续重提当前阶段。 */
|
||||
pSW->sink.On_work = 1;
|
||||
@@ -398,7 +441,29 @@ static int chrg_sink_work_init_aux_wait(eIDX_SOU_CH idx,
|
||||
if (batch_result <= 0) {
|
||||
return chrg_sink_init_submit_stage(idx, pSW);
|
||||
}
|
||||
if (g_sink_init_stage[idx] == SINK_INIT_STAGE_CLEAR_RELAY) {
|
||||
if (g_sink_init_stage[idx] == SINK_INIT_STAGE_TEST_STOP) {
|
||||
g_sink_init_stage[idx] = SINK_INIT_STAGE_TEST_STATUS;
|
||||
g_sink_init_test_sample_seq[idx] = chrg_eload_get_sample_seq(idx);
|
||||
return (chrg_sou_measure_once_submit(idx) == 0) ? 0 : -1;
|
||||
}
|
||||
if (g_sink_init_stage[idx] == SINK_INIT_STAGE_TEST_STATUS) {
|
||||
rt_uint32_t sample_seq = chrg_eload_get_sample_seq(idx);
|
||||
|
||||
if (sample_seq == g_sink_init_test_sample_seq[idx]) {
|
||||
return (chrg_sou_measure_once_submit(idx) == 0) ? 0 : -1;
|
||||
}
|
||||
g_sink_init_test_sample_seq[idx] = sample_seq;
|
||||
if (chrg_sink_power_test_active(idx)) {
|
||||
if (g_sink_init_test_stop_retry[idx] >=
|
||||
SINK_TEST_STATUS_RETRY_MAX) {
|
||||
/* 达到一轮上限后重新计数,但仍保持在安全确认流程。 */
|
||||
g_sink_init_test_stop_retry[idx] = 0U;
|
||||
}
|
||||
g_sink_init_test_stop_retry[idx]++;
|
||||
g_sink_init_stage[idx] = SINK_INIT_STAGE_TEST_STOP;
|
||||
return chrg_sink_init_submit_stage(idx, pSW);
|
||||
}
|
||||
g_sink_init_test_stop_retry[idx] = 0U;
|
||||
g_sink_init_stage[idx] = SINK_INIT_STAGE_AUX_RELAY;
|
||||
return chrg_sink_init_submit_stage(idx, pSW);
|
||||
}
|
||||
@@ -636,29 +701,43 @@ static int chrg_sink_work_low_aux_wait(eIDX_SOU_CH idx,
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: 清除运行、使能和在线标志,关闭北向继电器
|
||||
返回说明: 0:关机成功 <0:停止命令提交失败
|
||||
其它说明: 短路关机先退出短路再发送WORK_STOP,普通关机只发送WORK_STOP
|
||||
其它说明: 功率板处于测试态时先发送WORK_STOP;短路兼容退出命令随后发送
|
||||
*****************************************************************/
|
||||
static int chrg_sink_work_stop_prepare(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW)
|
||||
{
|
||||
rt_uint16_t regs[2];
|
||||
rt_uint16_t values[2];
|
||||
rt_uint16_t regs[3];
|
||||
rt_uint16_t values[3];
|
||||
rt_uint8_t count = 0U;
|
||||
rt_bool_t was_short;
|
||||
rt_bool_t power_test_active;
|
||||
rt_bool_t preserve_test_retry;
|
||||
|
||||
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
was_short = (pSW->sink.test.test_mode_old == SINK_TEST_SHORT) ||
|
||||
preserve_test_retry = (pSW->sink.work_mode == SINK_WORK_STOP_WAIT) &&
|
||||
!g_sink_stop_test_confirmed[idx] &&
|
||||
(g_sink_stop_test_stop_retry[idx] != 0U);
|
||||
power_test_active = chrg_sink_power_test_active(idx);
|
||||
was_short = (power_test_active &&
|
||||
(chrg_sink_power_status_get(idx) == STA1_SHORT_TEST)) ||
|
||||
(pSW->sink.test.test_mode_old == SINK_TEST_SHORT) ||
|
||||
(pSW->sink.test.test_mode == SINK_TEST_SHORT) ||
|
||||
g_sink_stop_from_short[idx];
|
||||
g_sink_stop_from_short[idx] = was_short;
|
||||
g_sink_stop_test_sample_seq[idx] = 0U;
|
||||
if (!preserve_test_retry) {
|
||||
g_sink_stop_test_stop_retry[idx] = 0U;
|
||||
}
|
||||
g_sink_stop_test_confirmed[idx] = RT_FALSE;
|
||||
/* WORK_STOP必须是退出Short/OCP/DYNA的第一条南向命令。 */
|
||||
regs[count] = REG_WORK;
|
||||
values[count++] = WORK_STOP;
|
||||
if (was_short) {
|
||||
regs[count] = ModbusRTU_ShortTest_CMD_MODE_FLAG;
|
||||
values[count++] = ModbusRTU_DYNA_CMD_MODE_STOP;
|
||||
}
|
||||
regs[count] = REG_WORK;
|
||||
values[count++] = WORK_STOP;
|
||||
g_sink_init_in_progress[idx] = RT_FALSE;
|
||||
g_sink_init_stage_submitted[idx] = RT_FALSE;
|
||||
if (chrg_sou_com_batch_cancel(idx) != 0) {
|
||||
@@ -887,6 +966,30 @@ static int chrg_sink_work_current_wait(eIDX_SOU_CH idx,
|
||||
return chrg_sink_work_protocol_unload(idx, pSW);
|
||||
}
|
||||
|
||||
if ((next_action == SINK_UNLOAD_NEXT_STOP_RELAY) &&
|
||||
!g_sink_stop_test_confirmed[idx]) {
|
||||
rt_uint32_t test_sample_seq = chrg_eload_get_sample_seq(idx);
|
||||
|
||||
if (g_sink_stop_test_sample_seq[idx] == 0U) {
|
||||
g_sink_stop_test_sample_seq[idx] = test_sample_seq;
|
||||
return (chrg_sou_measure_once_submit(idx) == 0) ? 0 : -1;
|
||||
}
|
||||
if (test_sample_seq == g_sink_stop_test_sample_seq[idx]) {
|
||||
return (chrg_sou_measure_once_submit(idx) == 0) ? 0 : -1;
|
||||
}
|
||||
g_sink_stop_test_sample_seq[idx] = test_sample_seq;
|
||||
if (chrg_sink_power_test_active(idx)) {
|
||||
if (g_sink_stop_test_stop_retry[idx] >=
|
||||
SINK_TEST_STATUS_RETRY_MAX) {
|
||||
/* 达到一轮上限后重新计数,但仍保持在安全确认流程。 */
|
||||
g_sink_stop_test_stop_retry[idx] = 0U;
|
||||
}
|
||||
g_sink_stop_test_stop_retry[idx]++;
|
||||
return chrg_sink_work_stop_prepare(idx, pSW);
|
||||
}
|
||||
g_sink_stop_test_confirmed[idx] = RT_TRUE;
|
||||
}
|
||||
|
||||
if (!g_sink_unload_batch_confirmed[idx]) {
|
||||
/* 从最后一条写回码之后建立基线,排除RUN_COM之前残留的旧量测。 */
|
||||
g_sink_unload_sample_seq[idx] = chrg_eload_get_sample_seq(idx);
|
||||
|
||||
Reference in New Issue
Block a user