ch32v307_camera/doc/设计文档/TCP通信模块设计.md
zhoujie b69717b964 📝 docs(design): 新增系统设计文档集
 feat(system-overview): 创建系统总览文档
- 描述项目背景与硬件平台配置
- 提供 FreeRTOS 任务拓扑表(任务优先级、栈大小、职责)
- 详细说明系统启动序列和初始化依赖关系
- 绘制 2D/1D 状态机完整流程图
- 解释 TEMP_REQ 辅助通道工作机制
- 说明任务间同步机制(Frame_Ready_Flag、双缓冲 TX)

 feat(dvp-module-design): 创建 DVP 模块设计文档
- 提供 DVP 硬件连接引脚映射表
- 描述 DVP 时序配置(信号极性、工作模式)
- 解释 DMA ping-pong 行缓冲机制和切换逻辑
- 说明 DVP IRQ 帧组装流程(STR_FRM/ROW_DONE)
- 定义 FrameBuffer 数据格式和像素访问方式
- 说明 TMP 模式温度换算公式和字节序要求

 feat(qdx-protocol-design): 创建 QDX 协议设计文档
- 描述完整 TLV 帧结构(FrameHeader + TLV + CRC)
- 列出所有 Class/Type 映射表和用途说明
- 解释零拷贝 TX 缓冲区架构(HeadOffset 机制)
- 说明分片机制和最大载荷限制
- 定义 Flags 字段各位含义和使用场景

 feat(tcp-module-design): 创建 TCP 通信模块设计文档
- 描述双流连接架构(控制流 5511 / 数据流 5512)
- 说明握手流程和连接建立时序
- 解释心跳机制和 TCP Keepalive 配置
- 描述配置下发与缓存机制
- 说明数据发送队列和背压处理策略
- 解释 WCHNET 网络栈驱动任务工作机制

 feat(integration-guide): 创建对接集成指南
- 提供网络接入参数表(IP、端口、协议)
- 详细说明握手流程和配置下发格式
- 提供 2D/1D 温度帧解析方法和示例代码
- 说明检测结果上报和 NG 响应机制
- 解释 TEMP_REQ 按需截图工作方式
- 列出错误码表和对接故障排查步骤
2026-03-15 19:17:41 +08:00

7.1 KiB
Raw Permalink Blame History

TCP 通信模块设计文档

文档版本1.0 · 日期2026-03-15 · 状态:已发布


1. 模块概述

TCP 通信模块(TcpLogic管理与上位机ConfigServer的所有网络连接包括连接建立、握手认证、配置接收与缓存、温度帧发送和断线重连。模块基于 WCHNET 协议栈构建,通过 QDX TLV 协议封装数据。

源文件:Middle/QDXnetworkStack/qdx_tcp_logic.c / qdx_tcp_logic.h


2. 双流连接架构

2.1 职责分工

端口 方向 职责
控制流 srcport=5511 MCU 主动连接 Server 握手、配置下发、心跳、TEMP_REQ、DetectionResult 上报
数据流 desport=5512 MCU 主动连接 Server 温度帧数据上报TYPE_TEMP_FRAME

两流独立管理,数据流断开不影响控制流的配置和心跳功能。

/* main.c 中的地址配置 */
u8  IPAddr[4]   = {192, 168, 7, 10};   /* MCU IP */
u8  DESIP[4]    = {192, 168, 7, 50};   /* Server IP */
u16 desport     = 5512;                 /* 数据流目标端口 */
u16 srcport     = 5511;                 /* 控制流源端口 */

2.2 连接建立时序

TcpLogic_Start()
    │
    ├─ 1. 控制流 TCP Connect → Server:5511
    │       等待 SINT_STAT_CONNECT 事件
    │
    ├─ 2. 发送 TYPE_HANDSHAKEClass=CLASS_SYSTEM
    │       含 ProtocolVersion=0x0200DeviceUUID=MAC 地址6 字节扩展为 UUID 格式)
    │       AuthToken=全零(当前不鉴权)
    │
    ├─ 3. 等待服务器握手响应
    │       收到响应后标记控制流"就绪"
    │
    └─ 4. 数据流 TCP Connect → Server:5512
            连接成功后数据流"就绪"

3. 心跳与 Keepalive 机制

3.1 应用层心跳

TcpLogic 内部定时通过控制流发送 TYPE_HEARTBEAT 帧,包含:

typedef struct {
    uint32_t UpTime;    /* 设备运行时间ms */
    uint8_t  CpuLoad;   /* CPU 负载(预留,当前填 0 */
    uint8_t  MemUsage;  /* 内存使用率(预留,当前填 0 */
} Heartbeat_t;  /* 6 字节 */

3.2 TCP Keepalive

main() 中配置:

struct _KEEP_CFG cfg = {
    .idle     = 20000,  /* 空闲 20 秒后开始发送探测包 */
    .interval = 15000,  /* 每次探测间隔 15 秒 */
    .count    = 9       /* 最多 9 次无响应后关闭连接 */
};
WCHNET_ConfigKeepLive(&cfg);
参数 说明
idle 20000 ms 无数据交换后多久开始 Keepalive 探测
interval 15000 ms 相邻两次探测的间隔
count 9 探测无响应的最大次数,超过则断链

总体断线判定时间最坏情况20 + 9×15 = 155 秒


4. 配置下发与缓存机制

4.1 配置接收流程

Server 控制流发送配置帧(可一次发三种):
    ├─ TYPE_CONFIG_COMMONConfigCommon_t
    ├─ TYPE_CONFIG_2DConfig2D_t
    └─ TYPE_CONFIG_1DConfig1D_t
            │
            ↓
TcpLogic 解析后缓存至内部 shadow 寄存器
            │
            ↓
触发 ConfigUpdateCallbackOnConfigUpdate
            │
            ↓
回调内调用 Preprocess_Settings_Change(cfg2d, cfg1d, common)
    → 更新预处理模块的 ROI、阈值、目标尺寸等参数

4.2 读取当前配置

业务任务每帧调用:

ConfigCommon_t tc; Config2D_t t2; Config1D_t t1;
int8_t has_cfg = TcpLogic_GetLatestConfig(&tc, &t2, &t1);

返回值:

  • 0:有有效配置,tc/t2/t1 已填充
  • -1:服务器尚未下发配置

4.3 无配置时的默认行为

TcpLogic_GetLatestConfig 返回 -1 时,task_business_entry 跳过 2D/1D 处理,仅响应 TEMP_REQ如有

默认 Burst 参数(代码中 fallback 常量):

参数 默认值
DEFAULT_BURST_COUNT 3 帧
DEFAULT_BURST_INTERVAL_MS 200 ms

5. 数据发送队列与背压处理

5.1 发送接口

int8_t TcpLogic_BuildAndSendTemperatureFrame(
    TcpTxBuffer_t    *tx_buf,
    PreprocessResult_t *meta,
    uint8_t           socket_type,   /* 0x01=数据流0x02=控制流TEMP_REQ 响应) */
    uint8_t           is2d           /* 1=2D矩阵0=1D时序 */
);

返回值:

  • 0:成功入队发送
  • < 0:失败(连接断开或队列满)

5.2 发送失败处理

当前固件对发送失败仅打印 DBG_ERR不重试,帧直接丢弃。原因:热像数据具有实时性,重试旧帧无意义。

5.3 双缓冲保证

业务任务通过 use_buffer_A 标志交替使用 g_TxNetBuffer_A / g_TxNetBuffer_B

帧 N   → g_TxNetBuffer_A → BuildAndSend入队
                           ↓ 切换
帧 N+1 → g_TxNetBuffer_B → BuildAndSend入队
                           ↓ 切换
帧 N+2 → g_TxNetBuffer_A ...

帧 N 入队后立即切换缓冲区,即使 WCHNET 尚未完成实际 TCP 发送,帧 N+1 的填充也不会覆盖帧 N。


6. WCHNET 网络栈驱动任务

6.1 任务职责

task_wchnet_entry(优先级 6每 5 ms 执行一次:

static void task_wchnet_entry(void *pvParameters) {
    while (1) {
        qdx_port_net_lock();          /* 获取互斥量 */
        WCHNET_MainTask();            /* 协议栈心跳TCP 超时检测、重传计时等) */
        if (WCHNET_QueryGlobalInt())
            WCHNET_HandleGlobalInt(); /* 分发 socket 事件 */
        qdx_port_net_unlock();        /* 释放互斥量 */
        vTaskDelay(pdMS_TO_TICKS(5));
    }
}

6.2 事件分发路径

WCHNET_HandleGlobalInt()
    └─ WCHNET_HandleSockInt(socketid, intstat)
            ├─ SINT_STAT_RECV       → qdx_port_sock_recv_notify()
            ├─ SINT_STAT_CONNECT    → WCHNET_ModifyRecvBuf() + qdx_port_sock_connect_notify()
            ├─ SINT_STAT_DISCONNECT → qdx_port_sock_disconnect_notify()
            └─ SINT_STAT_TIM_OUT   → qdx_port_sock_disconnect_notify()(视为断连)

6.3 互斥保护

qdx_port_net_lock/unlock 使用 FreeRTOS 互斥量保护所有 WCHNET API 调用,防止 task_wchnet_entrytask_business_entry 并发访问网络栈导致竞态。

设计说明WCHNET 不是线程安全的,所有 WCHNET 调用(包括业务任务中的发送接口)均须在锁保护下进行。task_wchnet_entry 持锁 5 mstask_business_entry 在发送时短暂竞争该锁,实际竞争窗口极短。


7. 断线重连

  • 控制流或数据流断开(SINT_STAT_DISCONNECT / SINT_STAT_TIM_OUT)后,qdx_tcp_logic 内部状态机自动重置并重新尝试连接
  • 重连成功后重新发送握手帧
  • 配置 shadow 寄存器在断线期间保留,重连后无需服务器重新下发配置即可继续工作

8. 相关文档

文档 内容
系统总览.md TcpLogic_Start 在启动序列中的位置
QDX协议设计.md 零拷贝 TX 缓冲区、帧结构
对接集成指南.md 上位机侧握手和配置下发操作