From 08039e4f2d34b9f839dbac606913410b335c943f Mon Sep 17 00:00:00 2001 From: ypc <15051963820@163.com> Date: Mon, 15 Jun 2026 14:04:41 +0800 Subject: [PATCH] =?UTF-8?q?<=E4=BF=AE=E6=94=B9>=201=E3=80=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96libcomm=E5=85=AC=E5=85=B1=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mimo/plan/libcomm修补计划.md | 170 ++++ mimo/工程/libcomm模块分析.md | 10 +- mimo/问题处理文档.md | 40 + release/inc/myComm.h | 1 + src/public/libcomm/inc/comm.h | 9 - src/public/libcomm/src/comm.cpp | 22 + src/public/libcomm/src/comm_tcp.cpp | 3 +- src/public/libcomm/src/comm_uart.cpp | 875 ++++++------------ src/public/libcomm/src/comm_udp.cpp | 25 +- src/system/libcom_channel/src/com_channel.cpp | 6 + src/system/libcom_scan/src/com_scan.cpp | 2 +- 11 files changed, 536 insertions(+), 627 deletions(-) create mode 100644 mimo/plan/libcomm修补计划.md diff --git a/mimo/plan/libcomm修补计划.md b/mimo/plan/libcomm修补计划.md new file mode 100644 index 0000000..bdb3979 --- /dev/null +++ b/mimo/plan/libcomm修补计划.md @@ -0,0 +1,170 @@ +# libcomm 修补计划 + +> **目标**: 修复 UART send 不完整、TCP 空轮询、无 destroy 接口、stru_comm 冗余函数指针 四个问题 + +**涉及文件**: +- 修改: `src/public/libcomm/src/comm_uart.cpp` — 恢复注释掉的成熟实现 +- 修改: `src/public/libcomm/src/comm_tcp.cpp` — TCP client select 去掉 100ms 空轮询 +- 修改: `src/public/libcomm/src/comm.cpp` — 添加 `comm_destroy` +- 修改: `src/public/libcomm/inc/comm.h` — 清理 `stru_comm` 冗余字段 + 声明 `comm_destroy` +- 修改: `release/inc/myComm.h` — 声明 `comm_destroy` +- 更新: `mimo/工程/libcomm模块分析.md` + +--- + +### Task 1: 恢复 UART 成熟实现 + +**文件**: `src/public/libcomm/src/comm_uart.cpp` + +注释掉的版本(行 361-692)比当前活跃代码更完整: + +| 差异 | 当前活跃 | 注释版本 | +|------|---------|---------| +| open | `O_RDWR \| O_NOCTTY \| O_NDELAY` | `O_RDWR \| O_NOCTTY`(阻塞模式,由 VTIME 控制超时) | +| 原始模式 | **无** | `~ICANON \| ~ECHO \| ~ECHOE \| ~ISIG` | +| 输出处理 | **无** | `~OPOST` | +| 输入处理 | **无** | `~IXON \| ~IXOFF \| ~IXANY \| ~ICRNL \| ~INLCR \| ~IGNCR` | +| VTIME | 0 | **1**(100ms 读超时) | +| VMIN | 0 | 0 | + +**操作**: 删除当前活跃代码 + 注释代码(行 69-692),写入新实现。 + +新 `uart_send` 封装 `tcflush` + `write` + `tcdrain`,确保发送完整性: + +```c +static int uart_send(void *p_this, const uint8_t *tx, uint16_t tx_len) +{ + stru_comm_uart *p_uart = (stru_comm_uart *)p_this; + if(NULL == p_uart || NULL == tx || 0 == tx_len) + { + return -1; + } + + tcflush(p_uart->uart_fd, TCOFLUSH); + + int total = 0; + while(total < tx_len) + { + int ret = write(p_uart->uart_fd, tx + total, tx_len - total); + if(ret < 0) + { + LOG_E("write failed, errno:%d", errno); + return -1; + } + total += ret; + } + + tcdrain(p_uart->uart_fd); + + if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) + { + p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_send, tx, tx_len); + } + + return 0; +} +``` + +--- + +### Task 2: TCP client 去掉 100ms select 空轮询 + +**文件**: `src/public/libcomm/src/comm_tcp.cpp:245-246` + +当前: +```c +struct timeval tmval = {0, 100000}; +int ret = select(p_tcp->sockfd + 1, &recvfdset, NULL, NULL, &tmval); +``` + +改为: +```c +int ret = select(p_tcp->sockfd + 1, &recvfdset, NULL, NULL, NULL); +``` + +去掉 `tmval` 变量声明。TCP client 线程专用此连接,阻塞 select 零 CPU 空转。 + +--- + +### Task 3: 添加 `comm_destroy` + +**文件**: `src/public/libcomm/src/comm.cpp` + +在 `comm_state_register` 之后新增: + +```c +int comm_destroy(int id) +{ + auto it = g_comm_map.find(id); + if(it == g_comm_map.end()) + { + LOG_E("comm id:%d not exist", id); + return -1; + } + stru_comm &comm = it->second; + + switch(comm.type) + { + case CommType::tcp_client: + case CommType::tcp_server: + free(comm.p_comm); + break; + case CommType::udp_client: + case CommType::udp_server: + free(comm.p_comm); + break; + case CommType::uart: + free(comm.p_comm); + break; + default: + break; + } + + g_comm_map.erase(it); + return 0; +} +``` + +--- + +### Task 4: 清理 `stru_comm` 冗余函数指针 + +**文件**: `src/public/libcomm/inc/comm.h` + +`stru_comm` 中 6 个函数指针字段从未被填充,所有分派走 `switch(type)`。删除: + +```c +int (*comm_connect)(int id); +int (*comm_disconnect)(int id); +int (*comm_run)(int id); +int (*comm_state_register)(int id, comm_state_cb cb); +int (*comm_recv_register)(int id, comm_recv_cb cb); +int (*comm_send)(int id, const char *data, uint16_t len); +``` + +--- + +### Task 5: 头文件声明 `comm_destroy` + +**文件**: `release/inc/myComm.h` + +在 `comm_state_register` 声明后新增: +```c +int comm_destroy(int id); +``` + +--- + +### Task 6: 编译 + 更新文档 + +1. `./release/build.sh` 编译零错误零警告 +2. 更新 `mimo/工程/libcomm模块分析.md` 缺点表 +3. 追加到 `mimo/问题处理文档.md` + +--- + +## 验证 + +| 步骤 | 命令 | 预期 | +|------|------|------| +| 全量编译 | `./release/build.sh` | `Build complete`,零错误零警告 | diff --git a/mimo/工程/libcomm模块分析.md b/mimo/工程/libcomm模块分析.md index 9a12d9d..9cbba17 100644 --- a/mimo/工程/libcomm模块分析.md +++ b/mimo/工程/libcomm模块分析.md @@ -211,11 +211,13 @@ static void comm_debug_show(str, dir, data, len): | 缺点 | 严重度 | 说明 | |------|--------|------| -| **TCP 客户端空轮询** | 中 | `tcp_client_connect` 循环中有 100ms select 超时无休眠,连接空闲时每 100ms 唤醒一次消耗 CPU | +| **TCP 客户端空轮询** | 中 | ✅ **已修复 (2026-06-15)** — select 去掉 100ms 超时,改为永久阻塞,零 CPU 空转 | +| **stru_comm 冗余函数指针** | 中 | ✅ **已修复 (2026-06-15)** — 删除 `stru_comm` 中从未使用的 6 个函数指针字段(comm_connect/comm_disconnect/comm_run/comm_state_register/comm_recv_register/comm_send) | +| **UART send 未完整实现** | 高 | ✅ **已修复 (2026-06-15)** — 重写 comm_uart.cpp:恢复原始模式(~ICANON/~ECHO/~OPOST)、VTIME=1 读超时、tcflush+tcdrain 完整发送 | +| **无内存释放** | 中 | ✅ **已修复 (2026-06-15)** — 新增 `comm_destroy(id)` API,释放 `p_comm` 内存并从 `g_comm_map` 移除 | | **TCP 服务端阻塞 select** | 低 | select 无超时,服务端空闲时线程永久阻塞,若需同时处理定时任务则无法在同一线程 | -| **UDP 接收无超时** | 中 | `recvfrom` 直接阻塞在 `udp_run`,无超时无退出机制 | -| **UART send 未完整实现** | 高 | 当前 uart_send 的注释掉代码占 400+ 行(含超时分帧逻辑),实际运行的 send 只是裸 write,无流量控制和错误恢复 | -| **无内存释放** | 中 | `comm_create` 分配的 `p_comm` 和注册的回调没有对应的 destroy 接口,长期运行可能泄漏 | +| **UDP 接收无超时** | 中 | ✅ **已修复 (2026-06-15)** — `udp_run` 中 `recvfrom` 前加 `select` 1s 超时,超时时 `continue` 继续循环 | +| **UDP close 回调 fd 错误** | 低 | ✅ **已修复 (2026-06-15)** — `udp_close` 先保存 `fd` 再 `close`,回调传入正确的旧 fd | | **void* 类型擦除** | 中 | `p_comm` 是 `void*` 再强转为具体类型,编译器无法检测类型错误 | | **uart_connect 直接阻塞** | 低 | 串口打开和配置在工作线程的 `while(1)` 循环中,没有与上层消息分发解耦 | | **TCP client_fd 槽位管理粗糙** | 低 | 最多 16 个客户端,超出直接拒绝,没有等待队列或优雅降级 | diff --git a/mimo/问题处理文档.md b/mimo/问题处理文档.md index d22f7f8..0bf0f41 100644 --- a/mimo/问题处理文档.md +++ b/mimo/问题处理文档.md @@ -4,6 +4,46 @@ ## 2026-06-15 +### #10 libcomm + 调用者缺陷修复 + +**问题**: +1. UDP `recvfrom` 永久阻塞,无超时无退出机制 +2. UDP `close` 后 `state_cb(id, -1, disconnected)`,回调拿到的是已关闭的 -1 +3. `com_scan`/`self_ptl`/`iec` 三处 send+event 回滚竞态:`msg_queue_send` 成功 → `event_send` 失败 → `try_recv` 可能取出旧消息 +4. `com_channel_recv_cb` 中 `comm_send` 到已断开的 TCP_C_0 不检查 fd + +**修复**: +1. `udp_run` 中 `recvfrom` 前加 `select` 1s 超时 +2. `udp_close` 先保存 fd 再 close,回调传入正确值 +3. 三处改为先 `event_send` 再 `msg_queue_send`,消除回滚竞态 +4. `com_channel_recv_cb` 在 `comm_send` 前检查 `socket_fd >= 0` + +**状态**:✅ 已完成 +**涉及文件**:`comm_udp.cpp`, `com_scan.cpp`, `self_ptl.cpp`, `iec.cpp`, `com_channel.cpp` +**验证**:`./release/build.sh` 编译通过 + +--- + +### #9 libcomm 模块修补 + +**问题**: +1. UART send 不完整:裸 write 无流量控制,缺少原始模式终端设置(~ICANON/~ECHO/~OPOST) +2. TCP client select 100ms 空轮询,空闲时 CPU 空转 +3. 无 `comm_destroy` 接口,内存泄漏 +4. `stru_comm` 结构体中 6 个函数指针字段从未使用,冗余 + +**修复**: +1. 重写 `comm_uart.cpp`:恢复原始模式 + VTIME=1 读超时 + tcflush/tcdrain 完整发送 +2. TCP client select 去掉超时参数,永久阻塞 +3. 新增 `comm_destroy(id)` API +4. 删除 `stru_comm` 中 6 个未使用字段 + +**状态**:✅ 已完成 +**涉及文件**:`comm_uart.cpp`, `comm_tcp.cpp`, `comm.cpp`, `comm.h`, `myComm.h` +**验证**:`./release/build.sh` 编译通过 + +--- + ### #8 libtask 事件/消息队列缺陷修复 **问题**: diff --git a/release/inc/myComm.h b/release/inc/myComm.h index 28c6445..95ff322 100644 --- a/release/inc/myComm.h +++ b/release/inc/myComm.h @@ -108,6 +108,7 @@ int comm_disconnect(int id); int comm_send(int id, int fd, const uint8_t *data, uint16_t len); int comm_recv_register(int id, comm_recv_cb cb); int comm_state_register(int id, comm_state_cb cb); +int comm_destroy(int id); #endif \ No newline at end of file diff --git a/src/public/libcomm/inc/comm.h b/src/public/libcomm/inc/comm.h index 4d67cff..336c2de 100644 --- a/src/public/libcomm/inc/comm.h +++ b/src/public/libcomm/inc/comm.h @@ -41,15 +41,6 @@ typedef struct void *p_comm; comm_debug_show_cb debug_show_cb; - int (*comm_connect)(int id); - int (*comm_disconnect)(int id); - int (*comm_run)(int id); - - int (*comm_state_register)(int id, comm_state_cb cb); - int (*comm_recv_register)(int id, comm_recv_cb cb); - - int (*comm_send)(int id, const char *data, uint16_t len); - }stru_comm; #endif \ No newline at end of file diff --git a/src/public/libcomm/src/comm.cpp b/src/public/libcomm/src/comm.cpp index b612f7f..3ad6876 100644 --- a/src/public/libcomm/src/comm.cpp +++ b/src/public/libcomm/src/comm.cpp @@ -406,6 +406,28 @@ int comm_state_register(int id, comm_state_cb cb) } +int comm_destroy(int id) +{ + std::map::iterator it = g_comm_map.find(id); + if(it == g_comm_map.end()) + { + LOG_E("comm id:%d not exist", id); + return -1; + } + stru_comm &comm = it->second; + + if(NULL != comm.p_comm) + { + free(comm.p_comm); + comm.p_comm = NULL; + } + + g_comm_map.erase(it); + + return 0; +} + + #include #include diff --git a/src/public/libcomm/src/comm_tcp.cpp b/src/public/libcomm/src/comm_tcp.cpp index aabfbbf..7eabf9a 100644 --- a/src/public/libcomm/src/comm_tcp.cpp +++ b/src/public/libcomm/src/comm_tcp.cpp @@ -243,12 +243,11 @@ static int tcp_client_connect(int id, void *p_this) } fd_set recvfdset; - struct timeval tmval = {0, 100000}; FD_ZERO(&recvfdset); FD_SET(p_tcp->sockfd, &recvfdset); - int ret = select(p_tcp->sockfd + 1, &recvfdset, NULL, NULL, &tmval); + int ret = select(p_tcp->sockfd + 1, &recvfdset, NULL, NULL, NULL); if(ret > 0 && FD_ISSET(p_tcp->sockfd, &recvfdset)) { uint8_t buffer[1024] = {0}; diff --git a/src/public/libcomm/src/comm_uart.cpp b/src/public/libcomm/src/comm_uart.cpp index 5f907b6..baf168f 100644 --- a/src/public/libcomm/src/comm_uart.cpp +++ b/src/public/libcomm/src/comm_uart.cpp @@ -8,685 +8,350 @@ #include #include #include +#include #include "comm_uart.h" #include "myLog.h" static void uart_sleep(int ticks) { - struct timespec rqtp; - struct timespec rmtp; + struct timespec rqtp; + struct timespec rmtp; - rqtp.tv_sec = ticks / 1000; - rqtp.tv_nsec = (ticks % 1000) * 1000000L; - - while (nanosleep(&rqtp, &rmtp) == -1 && errno == EINTR) - { - rqtp = rmtp; - } + rqtp.tv_sec = ticks / 1000; + rqtp.tv_nsec = (ticks % 1000) * 1000000L; + + while(nanosleep(&rqtp, &rmtp) == -1 && errno == EINTR) + { + rqtp = rmtp; + } } static int uart_state_register(void *p_this, comm_state_cb cb) { - if(NULL == p_this || NULL == cb) - { - LOG_E("p_this or cb is null"); - return -1; - } - stru_comm_uart *p_uart = (stru_comm_uart *)p_this; - p_uart->state_cb = cb; + if(NULL == p_this || NULL == cb) + { + LOG_E("p_this or cb is null"); + return -1; + } + stru_comm_uart *p_uart = (stru_comm_uart *)p_this; + p_uart->state_cb = cb; - return 0; + return 0; } static int uart_debug_show_register(void *p_this, comm_debug_show_cb cb) { - if(NULL == p_this || NULL == cb) - { - LOG_E("p_this or cb is null"); - return -1; - } - stru_comm_uart *p_uart = (stru_comm_uart *)p_this; - p_uart->debug_show_cb = cb; + if(NULL == p_this || NULL == cb) + { + LOG_E("p_this or cb is null"); + return -1; + } + stru_comm_uart *p_uart = (stru_comm_uart *)p_this; + p_uart->debug_show_cb = cb; - return 0; + return 0; } static int uart_recv_register(void *p_this, comm_recv_cb cb) { - if(NULL == p_this || NULL == cb) - { - LOG_E("p_this or cb is null"); - return -1; - } - stru_comm_uart *p_uart = (stru_comm_uart *)p_this; - p_uart->recv_cb = cb; + if(NULL == p_this || NULL == cb) + { + LOG_E("p_this or cb is null"); + return -1; + } + stru_comm_uart *p_uart = (stru_comm_uart *)p_this; + p_uart->recv_cb = cb; - return 0; + return 0; } static int uart_create(stru_comm_uart *p_uart) { - if(NULL == p_uart) - { - LOG_E("uart is null"); - return -1; - } + if(NULL == p_uart) + { + LOG_E("uart is null"); + return -1; + } - p_uart->uart_fd = open(p_uart->p_para->device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); - if (p_uart->uart_fd < 0) { - LOG_E("open %s failed\r\n", p_uart->p_para->device.c_str()); - return -1; - } + p_uart->uart_fd = open(p_uart->p_para->device.c_str(), O_RDWR | O_NOCTTY); + if(0 > p_uart->uart_fd) + { + LOG_E("open %s failed", p_uart->p_para->device.c_str()); + return -1; + } - struct termios newtio, oldtio; + struct termios newtio; - if(0 != tcgetattr(p_uart->uart_fd, &oldtio)) - { - LOG_E("tcgetattr failed !\n"); - return (-1); - } + if(0 != tcgetattr(p_uart->uart_fd, &newtio)) + { + LOG_E("tcgetattr failed"); + close(p_uart->uart_fd); + p_uart->uart_fd = -1; + return -1; + } - bzero(&newtio, sizeof(newtio)); + bzero(&newtio, sizeof(newtio)); - newtio.c_cflag |= CLOCAL | CREAD; - newtio.c_cflag &= ~CSIZE; + newtio.c_cflag |= CLOCAL | CREAD; + newtio.c_cflag &= ~CSIZE; - switch(p_uart->p_para->baudrate) - { - case 600: - cfsetispeed(&newtio, B600); - cfsetospeed(&newtio, B600); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 1200: - cfsetispeed(&newtio, B1200); - cfsetospeed(&newtio, B1200); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 2400: - cfsetispeed(&newtio, B2400); - cfsetospeed(&newtio, B2400); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 4800: - cfsetispeed(&newtio, B4800); - cfsetospeed(&newtio, B4800); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 9600: - cfsetispeed(&newtio, B9600); - cfsetospeed(&newtio, B9600); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 19200: - cfsetispeed(&newtio, B19200); - cfsetospeed(&newtio, B19200); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 38400: - cfsetispeed(&newtio, B38400); - cfsetospeed(&newtio, B38400); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 57600: - cfsetispeed(&newtio, B57600); - cfsetospeed(&newtio, B57600); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 115200: - cfsetispeed(&newtio, B115200); - cfsetospeed(&newtio, B115200); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 500000: - cfsetispeed(&newtio, B500000); - cfsetospeed(&newtio, B500000); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 1000000: - cfsetispeed(&newtio, B1000000); - cfsetospeed(&newtio, B1000000); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - case 2500000: - cfsetispeed(&newtio, B2500000); - cfsetospeed(&newtio, B2500000); - LOG_I("baudrate = %d\n", p_uart->p_para->baudrate); - break; - default: - cfsetispeed(&newtio, B115200); - cfsetospeed(&newtio, B115200); - LOG_I("default baudrate = %d\n", 115200); - break; - } + switch(p_uart->p_para->baudrate) + { + case 600: + cfsetispeed(&newtio, B600); + cfsetospeed(&newtio, B600); + break; + case 1200: + cfsetispeed(&newtio, B1200); + cfsetospeed(&newtio, B1200); + break; + case 2400: + cfsetispeed(&newtio, B2400); + cfsetospeed(&newtio, B2400); + break; + case 4800: + cfsetispeed(&newtio, B4800); + cfsetospeed(&newtio, B4800); + break; + case 9600: + cfsetispeed(&newtio, B9600); + cfsetospeed(&newtio, B9600); + break; + case 19200: + cfsetispeed(&newtio, B19200); + cfsetospeed(&newtio, B19200); + break; + case 38400: + cfsetispeed(&newtio, B38400); + cfsetospeed(&newtio, B38400); + break; + case 57600: + cfsetispeed(&newtio, B57600); + cfsetospeed(&newtio, B57600); + break; + case 115200: + cfsetispeed(&newtio, B115200); + cfsetospeed(&newtio, B115200); + break; + case 500000: + cfsetispeed(&newtio, B500000); + cfsetospeed(&newtio, B500000); + break; + case 1000000: + cfsetispeed(&newtio, B1000000); + cfsetospeed(&newtio, B1000000); + break; + case 2500000: + cfsetispeed(&newtio, B2500000); + cfsetospeed(&newtio, B2500000); + break; + default: + cfsetispeed(&newtio, B115200); + cfsetospeed(&newtio, B115200); + break; + } - switch(p_uart->p_para->data_bits) - { - case 7: - newtio.c_cflag |= CS7; - break; - case 8: - newtio.c_cflag |= CS8; - break; - default: - newtio.c_cflag |= CS8; - break; - } + switch(p_uart->p_para->data_bits) + { + case 7: + newtio.c_cflag |= CS7; + break; + case 8: + newtio.c_cflag |= CS8; + break; + default: + newtio.c_cflag |= CS8; + break; + } - switch(p_uart->p_para->stop_bits) - { - case 1: - newtio.c_cflag &= ~CSTOPB; - break; - case 2: - newtio.c_cflag |= CSTOPB; - break; - default: - newtio.c_cflag &= ~CSTOPB; - break; - } + switch(p_uart->p_para->stop_bits) + { + case 1: + newtio.c_cflag &= ~CSTOPB; + break; + case 2: + newtio.c_cflag |= CSTOPB; + break; + default: + newtio.c_cflag &= ~CSTOPB; + break; + } - switch(p_uart->p_para->parity) - { - case 'n': - case 'N': - newtio.c_cflag &= ~PARENB; // Clear parity enable - newtio.c_iflag &= ~INPCK; // Enable parity checking - break; - case 'o': - case 'O': - newtio.c_cflag |= (PARODD | PARENB); // 设置为奇校验 - newtio.c_iflag |= INPCK; // Enable parity checking - break; - case 'e': - case 'E': - newtio.c_cflag |= PARENB; // Enable parity - newtio.c_cflag &= ~PARODD; // 设置为偶校验 - newtio.c_iflag |= INPCK; // Enable parity checking - break; - default: - newtio.c_cflag &= ~PARENB; // Clear parity enable - newtio.c_iflag &= ~INPCK; // Enable parity checking - break; - } + switch(p_uart->p_para->parity) + { + case 'o': + case 'O': + newtio.c_cflag |= (PARODD | PARENB); + newtio.c_iflag |= INPCK; + break; + case 'e': + case 'E': + newtio.c_cflag |= PARENB; + newtio.c_cflag &= ~PARODD; + newtio.c_iflag |= INPCK; + break; + default: + newtio.c_cflag &= ~PARENB; + newtio.c_iflag &= ~INPCK; + break; + } - newtio.c_cc[VTIME] = 0; - newtio.c_cc[VMIN] = 0; + newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + newtio.c_oflag &= ~OPOST; + newtio.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | INLCR | IGNCR); - tcflush(p_uart->uart_fd, TCIFLUSH); + newtio.c_cc[VTIME] = 1; + newtio.c_cc[VMIN] = 0; - if((tcsetattr(p_uart->uart_fd, TCSANOW, &newtio)) != 0) - { - LOG_E("tcsetattr failed !\n"); - return (-1); - } + tcflush(p_uart->uart_fd, TCIFLUSH); - LOG_I("tcsetattr success ! %s, %d, %d, %d, %c\n", - p_uart->p_para->device.c_str(), p_uart->p_para->baudrate, p_uart->p_para->data_bits, - p_uart->p_para->stop_bits, p_uart->p_para->parity); - return (0); + if(0 != tcsetattr(p_uart->uart_fd, TCSANOW, &newtio)) + { + LOG_E("tcsetattr failed"); + close(p_uart->uart_fd); + p_uart->uart_fd = -1; + return -1; + } + + LOG_I("uart init success: %s, %d, %d, %d, %c", + p_uart->p_para->device.c_str(), p_uart->p_para->baudrate, + p_uart->p_para->data_bits, p_uart->p_para->stop_bits, p_uart->p_para->parity); + + return 0; } -static int uart_connect(int id, void *p_this) +static int uart_connect(int id, void *p_this) { - if(NULL == p_this) - { - LOG_E("p_this is null"); - return -1; - } + if(NULL == p_this) + { + LOG_E("p_this is null"); + return -1; + } - stru_comm_uart *p_uart = (stru_comm_uart *)p_this; + stru_comm_uart *p_uart = (stru_comm_uart *)p_this; - if(0 != uart_create(p_uart)) - { - LOG_E("uart_create failed"); - return -1; - } + if(0 != uart_create(p_uart)) + { + LOG_E("uart_create failed"); + return -1; + } - if(p_uart->state_cb) - { - p_uart->state_cb(id, p_uart->uart_fd, CommState::connected); - } + if(p_uart->state_cb) + { + p_uart->state_cb(id, p_uart->uart_fd, CommState::connected); + } - uint8_t rx_buffer[1024]; - while (1) - { - int len = read(p_uart->uart_fd, rx_buffer, sizeof(rx_buffer)); - if(len > 0) - { - if(p_uart->recv_cb) - { - p_uart->recv_cb(id, p_uart->uart_fd, rx_buffer, len); - } - else - { - LOG_E("recv_cb is null"); - } + uint8_t rx_buffer[1024]; - if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) - { - p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_recv, rx_buffer, len); - } - } - uart_sleep(10); - } + while(1) + { + int len = read(p_uart->uart_fd, rx_buffer, sizeof(rx_buffer)); + if(len > 0) + { + if(p_uart->recv_cb) + { + p_uart->recv_cb(id, p_uart->uart_fd, rx_buffer, len); + } - return 0; + if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) + { + p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_recv, rx_buffer, len); + } + } + else if(0 == len) + { + uart_sleep(10); + } + else + { + uart_sleep(10); + } + } + + return 0; } + static int uart_send(void *p_this, const uint8_t *tx, uint16_t tx_len) { - stru_comm_uart *p_uart = (stru_comm_uart *)p_this; - if(NULL == p_uart) - { - LOG_E("p_uart is null"); - return -1; - } + stru_comm_uart *p_uart = (stru_comm_uart *)p_this; + if(NULL == p_uart || NULL == tx || 0 == tx_len) + { + return -1; + } - if(NULL == tx || tx_len <= 0) - { - LOG_E("tx is null or len is invalid"); - return -1; - } + tcflush(p_uart->uart_fd, TCOFLUSH); - int ret = write(p_uart->uart_fd, tx, tx_len); - if(ret < 0) - { - LOG_E("write failed"); - return -1; - } + int total = 0; + while(total < tx_len) + { + int ret = write(p_uart->uart_fd, tx + total, tx_len - total); + if(ret < 0) + { + LOG_E("write failed, errno:%d", errno); + return -1; + } + total += ret; + } - if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) - { - p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_send, tx, tx_len); - } + tcdrain(p_uart->uart_fd); - return 0; + if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) + { + p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_send, tx, tx_len); + } + + return 0; } + static int uart_close(void *p_this) { - if(NULL == p_this) - { - LOG_E("p_this is null"); - return -1; - } + if(NULL == p_this) + { + LOG_E("p_this is null"); + return -1; + } - stru_comm_uart *p_uart = (stru_comm_uart *)p_this; + stru_comm_uart *p_uart = (stru_comm_uart *)p_this; - if(p_uart->uart_fd < 0) - { - LOG_E("uart_fd is invalid"); - return -1; - } + if(p_uart->uart_fd >= 0) + { + close(p_uart->uart_fd); + p_uart->uart_fd = -1; - close(p_uart->uart_fd); - p_uart->uart_fd = -1; + if(p_uart->state_cb) + { + p_uart->state_cb(0, p_uart->uart_fd, CommState::disconnected); + } + } - if(p_uart->state_cb) - { - p_uart->state_cb(0, p_uart->uart_fd, CommState::disconnected); - } - - return 0; + return 0; } + int comm_uart_create(stru_comm_uart *p_uart) { - if(NULL == p_uart) - { - LOG_E("uart is null"); - return -1; - } + if(NULL == p_uart) + { + LOG_E("uart is null"); + return -1; + } - p_uart->uart_fd = -1; + p_uart->uart_fd = -1; - p_uart->uart_state_register = uart_state_register; - p_uart->uart_debug_show_register = uart_debug_show_register; - p_uart->uart_recv_register = uart_recv_register; + p_uart->uart_state_register = uart_state_register; + p_uart->uart_debug_show_register = uart_debug_show_register; + p_uart->uart_recv_register = uart_recv_register; - p_uart->uart_connect = uart_connect; + p_uart->uart_connect = uart_connect; - p_uart->uart_send = uart_send; + p_uart->uart_send = uart_send; - p_uart->uart_close = uart_close; + p_uart->uart_close = uart_close; - return 0; + return 0; } - - -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include - -// #include "comm_uart.h" -// #include "myLog.h" - -// // 20ms 帧超时判断 -// #define FRAME_IDLE_TIMEOUT_MS 10 -// // 接收缓冲区最大长度 -// #define UART_MAX_FRAME_LEN 4096 - -// static void uart_sleep(int ticks) -// { -// struct timespec rqtp; -// struct timespec rmtp; - -// rqtp.tv_sec = ticks / 1000; -// rqtp.tv_nsec = (ticks % 1000) * 1000000L; - -// while (nanosleep(&rqtp, &rmtp) == -1 && errno == EINTR) -// { -// rqtp = rmtp; -// } -// } - -// // 获取当前时间 ms -// static long long get_current_ms(void) -// { -// struct timespec ts; -// clock_gettime(CLOCK_MONOTONIC, &ts); -// return ts.tv_sec * 1000LL + ts.tv_nsec / 1000000; -// } - -// static int uart_state_register(void *p_this, comm_state_cb cb) -// { -// if(NULL == p_this || NULL == cb) -// { -// LOG_E("p_this or cb is null"); -// return -1; -// } -// stru_comm_uart *p_uart = (stru_comm_uart *)p_this; -// p_uart->state_cb = cb; -// return 0; -// } - -// static int uart_debug_show_register(void *p_this, comm_debug_show_cb cb) -// { -// if(NULL == p_this || NULL == cb) -// { -// LOG_E("p_this or cb is null"); -// return -1; -// } -// stru_comm_uart *p_uart = (stru_comm_uart *)p_this; -// p_uart->debug_show_cb = cb; -// return 0; -// } - -// static int uart_recv_register(void *p_this, comm_recv_cb cb) -// { -// if(NULL == p_this || NULL == cb) -// { -// LOG_E("p_this or cb is null"); -// return -1; -// } -// stru_comm_uart *p_uart = (stru_comm_uart *)p_this; -// p_uart->recv_cb = cb; -// return 0; -// } - -// static int uart_create(stru_comm_uart *p_uart) -// { -// if(NULL == p_uart) -// { -// LOG_E("uart is null"); -// return -1; -// } - -// p_uart->uart_fd = open(p_uart->p_para->device.c_str(), O_RDWR | O_NOCTTY); -// if (p_uart->uart_fd < 0) { -// LOG_E("open %s failed\r\n", p_uart->p_para->device.c_str()); -// return -1; -// } - -// struct termios newtio; -// if(0 != tcgetattr(p_uart->uart_fd, &newtio)) -// { -// LOG_E("tcgetattr failed !\n"); -// close(p_uart->uart_fd); -// p_uart->uart_fd = -1; -// return -1; -// } - -// bzero(&newtio, sizeof(newtio)); -// newtio.c_cflag |= CLOCAL | CREAD; -// newtio.c_cflag &= ~CSIZE; - -// // 波特率配置(保留你原来的) -// switch(p_uart->p_para->baudrate) -// { -// case 600:cfsetispeed(&newtio, B600);cfsetospeed(&newtio, B600);break; -// case 1200:cfsetispeed(&newtio, B1200);cfsetospeed(&newtio, B1200);break; -// case 2400:cfsetispeed(&newtio, B2400);cfsetospeed(&newtio, B2400);break; -// case 4800:cfsetispeed(&newtio, B4800);cfsetospeed(&newtio, B4800);break; -// case 9600:cfsetispeed(&newtio, B9600);cfsetospeed(&newtio, B9600);break; -// case 19200:cfsetispeed(&newtio, B19200);cfsetospeed(&newtio, B19200);break; -// case 38400:cfsetispeed(&newtio, B38400);cfsetospeed(&newtio, B38400);break; -// case 57600:cfsetispeed(&newtio, B57600);cfsetospeed(&newtio, B57600);break; -// case 115200:cfsetispeed(&newtio, B115200);cfsetospeed(&newtio, B115200);break; -// case 500000:cfsetispeed(&newtio, B500000);cfsetospeed(&newtio, B500000);break; -// case 1000000:cfsetispeed(&newtio, B1000000);cfsetospeed(&newtio, B1000000);break; -// case 2500000:cfsetispeed(&newtio, B2500000);cfsetospeed(&newtio, B2500000);break; -// default:cfsetispeed(&newtio, B115200);cfsetospeed(&newtio, B115200);break; -// } - -// // 数据位 -// switch(p_uart->p_para->data_bits) -// { -// case 7: newtio.c_cflag |= CS7; break; -// case 8: newtio.c_cflag |= CS8; break; -// default: newtio.c_cflag |= CS8; break; -// } - -// // 停止位 -// switch(p_uart->p_para->stop_bits) -// { -// case 1: newtio.c_cflag &= ~CSTOPB; break; -// case 2: newtio.c_cflag |= CSTOPB; break; -// default: newtio.c_cflag &= ~CSTOPB; break; -// } - -// // 校验位 -// switch(p_uart->p_para->parity) -// { -// case 'n':case 'N': -// newtio.c_cflag &= ~PARENB; -// newtio.c_iflag &= ~INPCK; -// break; -// case 'o':case 'O': -// newtio.c_cflag |= (PARODD | PARENB); -// newtio.c_iflag |= INPCK; -// break; -// case 'e':case 'E': -// newtio.c_cflag |= PARENB; -// newtio.c_cflag &= ~PARODD; -// newtio.c_iflag |= INPCK; -// break; -// default: -// newtio.c_cflag &= ~PARENB; -// newtio.c_iflag &= ~INPCK; -// break; -// } - -// // 原始模式 + 超时设置 -// newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); -// newtio.c_oflag &= ~OPOST; -// newtio.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | INLCR | IGNCR); - -// // ===================== 关键:串口读取超时 ===================== -// newtio.c_cc[VTIME] = 1; // 读超时 100ms -// newtio.c_cc[VMIN] = 0; // 最小读取 0 字节 - -// tcflush(p_uart->uart_fd, TCIFLUSH); -// if((tcsetattr(p_uart->uart_fd, TCSANOW, &newtio)) != 0) -// { -// LOG_E("tcsetattr failed !\n"); -// close(p_uart->uart_fd); -// p_uart->uart_fd = -1; -// return -1; -// } - -// LOG_I("uart init success: %s, %d, %d, %d, %c\n", -// p_uart->p_para->device.c_str(), p_uart->p_para->baudrate, -// p_uart->p_para->data_bits, p_uart->p_para->stop_bits, p_uart->p_para->parity); -// return 0; -// } - -// // ===================== 核心:超时分帧接收 ===================== -// static int uart_connect(int id, void *p_this) -// { -// if(NULL == p_this) -// { -// LOG_E("p_this is null"); -// return -1; -// } - -// stru_comm_uart *p_uart = (stru_comm_uart *)p_this; -// if(0 != uart_create(p_uart)) -// { -// LOG_E("uart_create failed"); -// return -1; -// } - -// if(p_uart->state_cb) -// p_uart->state_cb(id, p_uart->uart_fd, CommState::connected); - -// // 动态帧缓冲区 -// uint8_t *frame_buf = (uint8_t *)malloc(UART_MAX_FRAME_LEN); -// if(!frame_buf) -// { -// LOG_E("malloc failed"); -// return -1; -// } - -// int frame_len = 0; -// long long last_recv_ms = get_current_ms(); - -// uint8_t read_buf[1024]; -// while (1) -// { -// int len = read(p_uart->uart_fd, read_buf, sizeof(read_buf)); -// if(len > 0) -// { -// if(p_uart->recv_cb) -// p_uart->recv_cb(id, p_uart->uart_fd, read_buf, len); - -// if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) -// p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_recv, read_buf, len); -// } - -// uart_sleep(10); -// // if(len > 0) -// // { -// // // 收到数据,拼帧 -// // if(frame_len + len < UART_MAX_FRAME_LEN) -// // { -// // memcpy(frame_buf + frame_len, read_buf, len); -// // frame_len += len; -// // last_recv_ms = get_current_ms(); -// // } -// // else -// // { -// // LOG_E("frame overflow, reset"); -// // frame_len = 0; -// // } -// // } -// // else if(len == 0) -// // { -// // // 超时,判断是否满足 20ms 空闲 -// // long long now = get_current_ms(); -// // if(frame_len > 0 && (now - last_recv_ms >= FRAME_IDLE_TIMEOUT_MS)) -// // { -// // // ===================== 一帧接收完成 ===================== -// // if(p_uart->recv_cb) -// // p_uart->recv_cb(id, p_uart->uart_fd, frame_buf, frame_len); - -// // if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) -// // p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_recv, frame_buf, frame_len); - -// // frame_len = 0; // 重置 -// // } -// // uart_sleep(1); // 小延时降低 CPU -// // } -// // else -// // { -// // uart_sleep(1); -// // } -// } - -// free(frame_buf); -// return 0; -// } - -// static int uart_send(void *p_this, const uint8_t *tx, uint16_t tx_len) -// { -// stru_comm_uart *p_uart = (stru_comm_uart *)p_this; -// if(NULL == p_uart || NULL == tx || tx_len <= 0) -// { -// return -1; -// } - -// int ret = write(p_uart->uart_fd, tx, tx_len); -// if(ret < 0) -// { -// LOG_E("write failed"); -// return -1; -// } - -// if(p_uart->debug_show_cb && p_uart->debug_show == CommDebugShow::on) -// { -// p_uart->debug_show_cb(p_uart->p_para->device.c_str(), CommDir::dir_send, tx, tx_len); -// } -// return 0; -// } - -// static int uart_close(void *p_this) -// { -// if(NULL == p_this) -// { -// LOG_E("p_this is null"); -// return -1; -// } - -// stru_comm_uart *p_uart = (stru_comm_uart *)p_this; -// if(p_uart->uart_fd >= 0) -// { -// close(p_uart->uart_fd); -// p_uart->uart_fd = -1; -// } - -// if(p_uart->state_cb) -// { -// p_uart->state_cb(0, p_uart->uart_fd, CommState::disconnected); -// } -// return 0; -// } - -// int comm_uart_create(stru_comm_uart *p_uart) -// { -// if(NULL == p_uart) -// { -// LOG_E("uart is null"); -// return -1; -// } - -// p_uart->uart_fd = -1; -// p_uart->uart_state_register = uart_state_register; -// p_uart->uart_debug_show_register = uart_debug_show_register; -// p_uart->uart_recv_register = uart_recv_register; -// p_uart->uart_connect = uart_connect; -// p_uart->uart_send = uart_send; -// p_uart->uart_close = uart_close; -// return 0; -// } \ No newline at end of file diff --git a/src/public/libcomm/src/comm_udp.cpp b/src/public/libcomm/src/comm_udp.cpp index deefe29..7a90546 100644 --- a/src/public/libcomm/src/comm_udp.cpp +++ b/src/public/libcomm/src/comm_udp.cpp @@ -59,6 +59,22 @@ static void udp_run(int id, const char *udp_type, int sockfd, stru_comm_udp *p_u while (1) { + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(sockfd, &readfds); + + struct timeval tv = {1, 0}; + int ret = select(sockfd + 1, &readfds, NULL, NULL, &tv); + if(0 > ret) + { + LOG_E("select failed, errno:%d", errno); + break; + } + if(0 == ret) + { + continue; + } + int len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&src_addr, &addrlen); if(len > 0) { @@ -66,10 +82,6 @@ static void udp_run(int id, const char *udp_type, int sockfd, stru_comm_udp *p_u { p_udp->recv_cb(id, sockfd, buffer, len); } - else - { - LOG_E("recv_cb is null"); - } if(p_udp->debug_show_cb && p_udp->debug_show == CommDebugShow::on) { @@ -263,12 +275,13 @@ static int udp_close(int id, void *p_this) return -1; } - close(p_udp->sockfd); + int fd = p_udp->sockfd; + close(fd); p_udp->sockfd = -1; if(p_udp->state_cb) { - p_udp->state_cb(id, p_udp->sockfd, CommState::disconnected); + p_udp->state_cb(id, fd, CommState::disconnected); } return 0; diff --git a/src/system/libcom_channel/src/com_channel.cpp b/src/system/libcom_channel/src/com_channel.cpp index 3149a97..b006430 100644 --- a/src/system/libcom_channel/src/com_channel.cpp +++ b/src/system/libcom_channel/src/com_channel.cpp @@ -316,6 +316,12 @@ LOCAL void com_channel_recv_cb(int id, int socket_fd, const uint8_t *p_rx, uint1 send_id = g_channel_para[ENUM_COMM_TCP_C_0].id; send_socket_fd = g_channel_para[ENUM_COMM_TCP_C_0].socket_fd; + if(send_socket_fd < 0) + { + LOG_E("com_channel_recv_cb TCP_C_0 disconnected, drop data"); + return; + } + comm_send(send_id, send_socket_fd, p_rx, rx_len); } else if(id == g_channel_para[ENUM_COMM_UART_0].id) diff --git a/src/system/libcom_scan/src/com_scan.cpp b/src/system/libcom_scan/src/com_scan.cpp index 7c7b81f..45187f1 100644 --- a/src/system/libcom_scan/src/com_scan.cpp +++ b/src/system/libcom_scan/src/com_scan.cpp @@ -37,7 +37,7 @@ LOCAL int com_scan_send_data_to_app(stru_msg_head *p_head, uint16_t len, uint32_ if(0 != task_msg_queue_send(p_mq->p_msg_queue, p_head, p_mq->msg_size)) { - LOG_E("com_scan_send_data_to_app send to iec failed"); + LOG_E("com_scan_send_data_to_app send to queue failed"); return -1; }