diff --git a/src/protocol/libicp67/src/icp67_decode.c b/src/protocol/libicp67/src/icp67_decode.c index dc67a24..a45dd08 100644 --- a/src/protocol/libicp67/src/icp67_decode.c +++ b/src/protocol/libicp67/src/icp67_decode.c @@ -654,6 +654,7 @@ static int icp67_decode_ti_200(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l stru_ti_200_201_202 *p_asdu; uint16_t pos; uint16_t i; + uint16_t asdu_len; if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len) { @@ -664,9 +665,21 @@ static int icp67_decode_ti_200(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l p_head = (stru_head *)p_rx; p_asdu = (stru_ti_200_201_202 *)p_head->data; + if(rx_len < ICP67_FRAME_OVERHEAD) + { + LOG_E("icp67_decode_ti_200: frame too short"); + return -1; + } + asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD); + pos = 0; for(i = 0; p_icp67->method.mx_trans_cb && i < p_asdu->num; i++) { + if(pos + sizeof(float) > asdu_len) + { + LOG_E("icp67_decode_ti_200: data overflow, num=%d, pos=%d", p_asdu->num, pos); + break; + } p_icp67->method.mx_trans_cb(p_icp67, p_asdu->addr + i, *(float *)&p_asdu->data[pos]); pos += sizeof(float); @@ -683,6 +696,7 @@ static int icp67_decode_ti_201(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l stru_ti_200_201_202 *p_asdu; uint16_t pos; uint16_t i; + uint16_t asdu_len; if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len) { @@ -693,9 +707,21 @@ static int icp67_decode_ti_201(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l p_head = (stru_head *)p_rx; p_asdu = (stru_ti_200_201_202 *)p_head->data; + if(rx_len < ICP67_FRAME_OVERHEAD) + { + LOG_E("icp67_decode_ti_201: frame too short"); + return -1; + } + asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD); + pos = 0; for(i = 0; p_icp67->method.st_trans_cb && i < p_asdu->num; i++) { + if(pos + 1 > asdu_len) + { + LOG_E("icp67_decode_ti_201: data overflow, num=%d, pos=%d", p_asdu->num, pos); + break; + } p_icp67->method.st_trans_cb(p_icp67, p_asdu->addr + i, p_asdu->data[pos++]); } @@ -711,6 +737,7 @@ static int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l stru_ti_200_201_202 *p_asdu; uint16_t pos; uint16_t i; + uint16_t asdu_len; if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len) { @@ -721,9 +748,21 @@ static int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l p_head = (stru_head *)p_rx; p_asdu = (stru_ti_200_201_202 *)p_head->data; + if(rx_len < ICP67_FRAME_OVERHEAD) + { + LOG_E("icp67_decode_ti_202: frame too short"); + return -1; + } + asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD); + pos = 0; for(i = 0; p_icp67->method.dd_trans_cb && i < p_asdu->num; i++) { + if(pos + sizeof(float) > asdu_len) + { + LOG_E("icp67_decode_ti_202: data overflow, num=%d, pos=%d", p_asdu->num, pos); + break; + } p_icp67->method.dd_trans_cb(p_icp67, p_asdu->addr + i, *(float *)&p_asdu->data[pos]); pos += sizeof(float); diff --git a/src/public/libfunc/src/myFunc.c b/src/public/libfunc/src/myFunc.c index 1bd5ef5..20f8986 100644 --- a/src/public/libfunc/src/myFunc.c +++ b/src/public/libfunc/src/myFunc.c @@ -107,7 +107,7 @@ uint16_t func_cal_sum_word(const uint8_t *d, uint32_t n) uint16_t func_cal_crc16(const uint8_t *d, uint32_t n) { - if (!n) + if (!d || !n) { return 0xFFFF; } @@ -124,7 +124,7 @@ uint16_t func_cal_crc16(const uint8_t *d, uint32_t n) uint32_t func_cal_crc32(const uint8_t *d, uint32_t n) { - if (!n) + if (!d || !n) { return 0xFFFFFFFF; } diff --git a/src/system/libcom_router/src/com_router.cpp b/src/system/libcom_router/src/com_router.cpp index d349dcf..f061b69 100644 --- a/src/system/libcom_router/src/com_router.cpp +++ b/src/system/libcom_router/src/com_router.cpp @@ -565,6 +565,7 @@ void *app_com_router(void *arg) * 巡检通道 socket_fd, 断开则记录。 * 未来可在此加自动重连逻辑。 */ + static int last_state[MAX_CHANNELS]; int i; for(i = 0; i < g_channel_count; i++) @@ -574,8 +575,6 @@ void *app_com_router(void *arg) if(ch->socket_fd < 0) { /* 已断开, 仅第一次打印 */ - static int last_state[MAX_CHANNELS]; - if(last_state[i] >= 0) { LOG_I("com_router: %s disconnected", ch->key); @@ -584,7 +583,10 @@ void *app_com_router(void *arg) } else { - static int last_state[MAX_CHANNELS]; + if(last_state[i] <= 0) + { + LOG_I("com_router: %s connected", ch->key); + } last_state[i] = 1; } } @@ -615,6 +617,12 @@ void *app_com_router(void *arg) { p_app->run_cnt++; } + + if(EV_STOP & event) + { + LOG_I("app_com_router: received EV_STOP, exiting"); + break; + } } return NULL; diff --git a/src/system/libmodbus_m/src/modbus_m.cpp b/src/system/libmodbus_m/src/modbus_m.cpp index 0caadd8..2f4be1e 100644 --- a/src/system/libmodbus_m/src/modbus_m.cpp +++ b/src/system/libmodbus_m/src/modbus_m.cpp @@ -1000,29 +1000,35 @@ void *app_modbus_m(void *arg) while (1) { task_event_recv(p_app->p_event, - 0x01 | 0x02 | 0x04, - 0x02 | 0x04, + EV_TIMER1 | EV_TIMER2 | EV_TIMER3, + TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR, TASK_EVENT_WAIT_FOREVER, &event); - if(event & 0x01) + if(event & EV_TIMER1) { - // 处理写请求队列 + // 处理写请求队列 (10ms) process_write_queue(); } - if(event & 0x02) + if(event & EV_TIMER2) { - // 轮询遥信(100ms) + // 轮询遥信 (100ms) poll_groups(st_groups); } - if(event & 0x04) + if(event & EV_TIMER3) { - // 轮询遥测/参数(1000ms) + // 轮询遥测/参数 (1000ms) poll_groups(mx_groups); p_app->run_cnt++; } + + if(EV_STOP & event) + { + LOG_I("app_modbus_m: received EV_STOP, exiting"); + break; + } } return NULL; diff --git a/src/system/libself_ptl/src/self_ptl.cpp b/src/system/libself_ptl/src/self_ptl.cpp index dd1ec96..be56334 100644 --- a/src/system/libself_ptl/src/self_ptl.cpp +++ b/src/system/libself_ptl/src/self_ptl.cpp @@ -132,13 +132,21 @@ static void put_rx_data(stru_self_rx *p_self_rx, uint8_t *p_rx, uint16_t len) { p_self_rx->buf[p_self_rx->wptr] = p_rx[i]; p_self_rx->wptr = (p_self_rx->wptr + 1) % p_self_rx->size; - p_self_rx->cnt++; - if(p_self_rx->cnt > p_self_rx->size) + if(p_self_rx->cnt >= p_self_rx->size) { - p_self_rx->cnt--; + /* 环形缓冲区已满: 丢弃最旧字节, 只警告一次 */ + static int overflow_warned = 0; + if(!overflow_warned) + { + LOG_E("put_rx_data: ring buffer overflow, dropping old data"); + overflow_warned = 1; + } p_self_rx->rptr = (p_self_rx->rptr + 1) % p_self_rx->size; - LOG_E("put_rx_data overflow, rptr=%d, wptr=%d", p_self_rx->rptr, p_self_rx->wptr); + } + else + { + p_self_rx->cnt++; } } @@ -170,6 +178,27 @@ static void get_rx_data(stru_self_rx *p_self_rx, uint8_t *p_data, uint16_t *p_da pthread_mutex_unlock(&p_self_rx->mutex); } +/* get_rx_data 的无锁版本 (调用者已持锁) */ +static void get_rx_data_locked(stru_self_rx *p_self_rx, uint8_t *p_data, uint16_t *p_data_len) +{ + uint16_t pos; + uint16_t i; + + if(NULL == p_self_rx || NULL == p_data || NULL == p_data_len) + { + return; + } + + pos = p_self_rx->rptr; + for(i = 0; i < p_self_rx->cnt; i++) + { + p_data[i] = p_self_rx->buf[pos]; + pos = (pos + 1) % p_self_rx->size; + } + + (*p_data_len) = p_self_rx->cnt; +} + static void clear_rx_data(stru_self_rx *p_self_rx) { if(NULL == p_self_rx) @@ -341,6 +370,8 @@ static void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp uint16_t pos = 0; uint16_t valid_len = 0; stru_self_rx *ring = &g_self_ptl.icp67_rx; + uint8_t iec_buf[SELF_PTL_BUF_SIZE]; + uint16_t iec_buf_len = 0; if(NULL == p_rx || 0 == len || NULL == p_icp67) { @@ -350,14 +381,13 @@ static void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp /* 写入环形缓冲区 */ put_rx_data(ring, p_rx, len); - /* 锁住读取 */ + /* 一次持锁: ICP67 帧处理 + IEC 帧快照, 避免竞态 */ pthread_mutex_lock(&ring->mutex); /* ICP67 帧搜索: 直接从环形缓冲读取, 零拷贝 */ while(0 == icp67_search_frame_in_ring(ring->buf, ring->size, ring->rptr, ring->cnt, &pos, &valid_len)) { - /* 解码: 帧跨环边界时需临时拷贝 */ uint8_t frame_buf[ICP67_TX_BUF_SIZE]; uint16_t i; @@ -368,23 +398,22 @@ static void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp p_icp67->decode_cb(p_icp67, frame_buf, valid_len); - /* 滑窗: advance ring pointer */ + /* 滑窗 */ pos += valid_len; ring->cnt -= pos; ring->rptr = (ring->rptr + pos) % ring->size; pos = 0; } + /* IEC-104 帧快照 (持锁下拷贝完整剩余数据) */ + get_rx_data_locked(ring, iec_buf, &iec_buf_len); + pthread_mutex_unlock(&ring->mutex); - /* IEC-104 帧: 需要读取字节序列, 做一次全量拷贝 */ + /* IEC-104 帧搜索 (锁外执行, 操作快照数据) */ + if(iec_buf_len > 0) { - uint8_t buf[SELF_PTL_BUF_SIZE]; - uint16_t buf_len = 0; - - get_rx_data(ring, buf, &buf_len); - - if(0 == self_ptl_search_iec_frame(buf, buf_len, &pos, &valid_len)) + if(0 == self_ptl_search_iec_frame(iec_buf, iec_buf_len, &pos, &valid_len)) { LOG_I("self_ptl: found IEC-104 frame at pos=%d, len=%d", pos, valid_len); /* TODO: 将 IEC-104 帧转发到 libiec 解码模块 (待实现) */ @@ -627,6 +656,13 @@ void *app_self_ptl(void *arg) { p_app->run_cnt++; } + + /* EV_STOP: 优雅退出 */ + if(EV_STOP & event) + { + LOG_I("app_self_ptl: received EV_STOP, exiting"); + break; + } } return NULL;