# TCPClient FreeRTOS 集成测试指南

## 1. 测试环境准备

### 1.1 硬件

| 项目 | 说明 |
|------|------|
| MCU 开发板 | CH32V307WCU6（需支持 FLASH/SRAM 分配配置） |
| 红外传感器 | 256×192 DVP 接口热成像模组 |
| 网络 | RJ45 网线，连接到与上位机同一局域网的交换机/路由器 |
| NG 输出 | PA8 引脚可接 LED 或示波器观察脉冲 |
| 串口 | USART1 (115200 baud)，连接 USB-TTL 调试串口 |

### 1.2 网络参数（代码默认值）

| 参数 | 值 | 对应文件 |
|------|-----|----------|
| MCU IP | `192.168.1.10` | `main.c` → `IPAddr` |
| 网关 | `192.168.1.1` | `main.c` → `GWIPAddr` |
| 子网掩码 | `255.255.255.0` | `main.c` → `IPMask` |
| 上位机 IP | `192.168.1.50` | `main.c` → `DESIP`，`qdx_tcp_logic.c` → `SERVER_IP` |
| 控制流端口 | `5511` | `qdx_tcp_logic.c` → `CONTROL_PORT` |
| 数据流端口 | `5512` | `qdx_tcp_logic.c` → `DATA_PORT` |

> **注意**：如果需要修改上位机 IP，需同时修改 `main.c` 中的 `DESIP` 和 `qdx_tcp_logic.c` 中的 `SERVER_IP`，保持一致。

### 1.3 上位机软件

将上位机 IP 设为 `192.168.1.50`，确保防火墙放行端口 5511 和 5512。

**方式 A — PC Demo 程序**（推荐先用此方式验证基本通信）：

```bash
cd pc/
build.bat          # 需要 MinGW GCC (C:\MinGW\bin\gcc.exe)
api_demo.exe       # 运行后作为 TCP 服务端监听 5511/5512
```

**方式 B — 网络调试工具**（如 NetAssist / Packet Sender / Wireshark）：
- 创建 2 个 TCP Server，分别监听 5511 和 5512
- 用于观察裸数据收发

---

## 2. 编译与烧录

### 2.1 编译

1. 打开 MounRiver Studio (MRS)
2. 导入工程：`prj/TCPClient/TCPClient.wvproj`
3. 点击 **Build** (锤子图标) 或 `Ctrl+B`
4. 确认编译成功，**无 RAM overflow 错误**

### 2.2 烧录

1. WCH-Link 连接开发板 SWD 接口
2. MRS 菜单 → **Flash → Download**
3. 烧录完成后芯片自动复位

> 首次烧录后，如果 Option Bytes 的 FLASH/SRAM 分配不是 128K/192K 模式，
> 代码会自动写入 Option Bytes 并触发复位。串口可看到：
> `Flash/SRAM config changed to 3, resetting...`
> 第二次复位后进入正常运行。

---

## 3. 分阶段测试

### 阶段一：基础启动与 FreeRTOS 调度器

**目的**：确认 MCU 正常启动、FreeRTOS 调度器运行、心跳任务工作。

**操作**：
1. 连接串口终端（115200, 8N1）
2. 上电或复位

**预期串口输出**：
```
TCPClient Test
SystemClk:144000000
UserByte: c7
net version:...
mac addr:XX XX XX XX XX XX
WCHNET_LibInit Success
[HB] 0  tick=xxx
[HB] 1  tick=xxx
[HB] 2  tick=xxx
...
```

**检查项**：

| # | 检查点 | 通过条件 |
|---|--------|----------|
| 1 | 系统时钟 | 显示 `SystemClk:144000000` |
| 2 | Option Bytes | UserByte 的高 3 位为 `110`（即 `0xC?`） |
| 3 | WCHNET 初始化 | 显示 `WCHNET_LibInit Success` |
| 4 | 心跳打印 | `[HB]` 每 2 秒递增一次 |
| 5 | 无 assert/HardFault | 不出现 `err at line` 或 `mcause` 等错误 |

**故障排查**：

| 现象 | 可能原因 | 解决方案 |
|------|----------|----------|
| 无任何输出 | 串口未连接/波特率错误 | 检查 USART1 TX 引脚连线，确认 115200 |
| 反复重启打印 `Flash/SRAM config changed` | Option Bytes 写入但未生效 | 先用 WCH-ISP 工具手动设置 Option Bytes |
| `err at line XXX of file "../FreeRTOS/tasks.c"` | Heap 不足 | 检查 `configTOTAL_HEAP_SIZE`（当前 12KB） |
| 卡死无心跳 | HardFault / startup 配置错 | 检查 mstatus=0x7800、CSR 0x804=0x1f |

---

### 阶段二：以太网物理链路

**目的**：确认 PHY 芯片链路正常。

**操作**：
1. 插入网线
2. 观察串口

**预期输出**：
```
PHY Link Success
```

**检查项**：

| # | 检查点 | 通过条件 |
|---|--------|----------|
| 1 | PHY 链路 | 插入网线后出现 `PHY Link Success` |
| 2 | 上位机 ping | 上位机执行 `ping 192.168.1.10` 能通 |

**故障排查**：

| 现象 | 可能原因 | 解决方案 |
|------|----------|----------|
| 无 PHY Link Success | 网线/PHY 硬件问题 | 检查 RJ45 座子焊接、网线 |
| ping 不通 | IP 冲突或子网不同 | 确认上位机 IP 在 192.168.1.x 段 |

---

### 阶段三：TCP 双通道连接

**目的**：验证 Control（5511）和 Data（5512）两条 TCP 连接成功建立。

**操作**：
1. 上位机启动 TCP 服务端监听 5511 和 5512（PC Demo 或网络工具）
2. MCU 上电（或已在阶段一上电，此时它会自动重连）

**预期串口输出**：
```
TCP Connected, socket 0
TCP Connected, socket 1
```

> `TcpLogic_Start()` 内部会创建管理线程，自动以 3 秒间隔尝试连接。
> 如果上位机未就绪，串口可能显示 `qdx_port: connect timeout`，属正常行为。

**检查项**：

| # | 检查点 | 通过条件 |
|---|--------|----------|
| 1 | Socket 0 连接 | 串口显示 `TCP Connected, socket 0` |
| 2 | Socket 1 连接 | 串口显示 `TCP Connected, socket 1` |
| 3 | 上位机收到握手包 | PC Demo 显示收到 Handshake |

**故障排查**：

| 现象 | 可能原因 | 解决方案 |
|------|----------|----------|
| `connect timeout` 循环出现 | 上位机未监听/防火墙 | 确认上位机 TCP Server 已启动、端口未被占用 |
| `SocketCreat fail XX` | WCHNET socket 数不够 | 检查 `WCHNET_NUM_TCP >= 2` |
| `no free SocketCtx` | 连接泄漏 | 排查上次断开是否正确释放了 context |

---

### 阶段四：心跳与协议通信

**目的**：验证 QDX 协议心跳包在 TCP 通道上正常收发。

**操作**：
1. 保持双通道连接
2. Wireshark 抓包或 PC Demo 观察

**预期行为**：
- MCU 每 2 秒发送心跳包到 Control 通道
- 若 6 秒无响应，MCU 主动断开并重连

**检查项**：

| # | 检查点 | 通过条件 |
|---|--------|----------|
| 1 | 心跳发送 | Wireshark 可见每 ~2s 一个小包到端口 5511 |
| 2 | 超时断开 | 强制关闭上位机后，串口显示 `TCP Timeout` / `TCP Disconnected` |
| 3 | 自动重连 | 重新启动上位机后，MCU 自动重连成功 |

---

### 阶段五：配置下发

**目的**：验证上位机通过 Control 通道下发配置，MCU 正确接收并回调。

**操作**（使用 PC Demo）：
1. 连接成功后，PC Demo 控制台输入操作选项
2. 选择下发配置（2D 模式参数）

**预期行为**：
- MCU 串口输出配置回调信息（如有添加 printf）
- `OnConfigUpdate()` 被调用，参数传入 `Preprocess_Settings_Change()`

---

### 阶段六：图像采集与发送

**目的**：验证 DVP 图像采集 → 预处理 → TCP 数据发送完整流程。

**前提**：红外传感器模组已连接并正常输出。

**操作**：
1. 保持 TCP 双通道连接
2. 传感器开始输出图像

**预期行为**：
1. `DVP_Task()` 检测到 `Frame_Ready_Flag`
2. `Preprocess_CheckInternalTrigger2D()` 判断触发条件
3. `Preprocess_Execute()` 执行预处理
4. `TcpLogic_BuildAndSendTemperatureFrame()` 将数据通过 Data 通道发送
5. 上位机在 5512 端口收到温度帧数据

**检查项**：

| # | 检查点 | 通过条件 |
|---|--------|----------|
| 1 | DVP 中断 | 确认 DMA 完成中断正常置位 `Frame_Ready_Flag` |
| 2 | 数据发送 | Wireshark 抓到到 5512 端口的大数据包 |
| 3 | 帧率 | 发送频率与传感器帧率大致匹配 |

---

### 阶段七：NG 输出脉冲

**目的**：验证上位机下发检测结果为 NG 时，PA8 输出 200ms 高电平脉冲。

**操作**：
1. 上位机通过 Control 通道下发检测结果（resultStatus = 0 → NG）
2. 示波器/逻辑分析仪接 PA8，或接 LED 观察

**预期行为**：
- PA8 拉高 → 持续 200ms → 自动拉低
- 串口无额外打印（NG 逻辑在 `task_business_entry` 中轮询 `sys_tick_ms`）

---

## 4. 压力测试

| 测试场景 | 操作 | 观察 |
|----------|------|------|
| 长时间运行 | 持续运行 24 小时 | 心跳持续、无 assert、无内存泄漏 |
| 反复断线重连 | 每 30 秒拔插网线 | 每次重连后双通道恢复 |
| 高频图像发送 | 传感器满帧率连续采集 | 无丢帧、无栈溢出 |
| 上位机先断后连 | MCU 先开机，30s 后再启动上位机 | MCU 自动重连成功 |

---

## 5. 关键配置速查

| 参数 | 当前值 | 文件 |
|------|--------|------|
| `configTOTAL_HEAP_SIZE` | 12 KB | `FreeRTOSConfig.h` |
| `configTICK_RATE_HZ` | 500 | `FreeRTOSConfig.h` |
| `configMINIMAL_STACK_SIZE` | 256 words | `FreeRTOSConfig.h` |
| task_wchnet 栈 | 512 words (2 KB) | `main.c` |
| task_business 栈 | 512 words (2 KB) | `main.c` |
| task_heartbeat 栈 | 256 words (1 KB) | `main.c` |
| FLASH / SRAM | 128 KB / 192 KB | `Link.ld` + `Config_Flash_SRAM()` |
| `WCHNET_NUM_TCP` | 2 | `net_config.h` |
| `RECE_BUF_LEN` | 2920 (MSS×2) | `net_config.h` |
| `RX_RING_SIZE` | 2920 | `qdx_port.c` |
| DVP 分辨率 | 256×192 | `dvp.h` |

---

## 6. 常见问题 FAQ

**Q: 心跳正常但 TCP 连不上？**
> 检查：① 上位机 IP 是否为 `192.168.1.50`；② 防火墙是否放行 5511/5512；③ `qdx_tcp_logic.c` 中 `SERVER_IP` 是否与 `main.c` 中 `DESIP` 一致。

**Q: 编译报 RAM overflow？**
> 检查 `.bss` 总量。FrameBuffer (96KB) + ETH buffers (~32KB) + ucHeap (12KB) + 应用缓冲区 (~47KB) ≈ 187KB。如果增大了某个缓冲区导致超 192KB，需要相应缩减其他部分。

**Q: 运行时 assert (`err at line XXX`)?**
> 通常是 Heap 不足导致 `pvPortMalloc` 失败。确认 `configTOTAL_HEAP_SIZE` 为 12KB，任务栈未超预算。

**Q: 如何启用栈溢出检测进行调试？**
> 在 `FreeRTOSConfig.h` 中设置 `configCHECK_FOR_STACK_OVERFLOW` 为 `2`，并实现 `vApplicationStackOverflowHook()` 函数打印任务名。**仅用于调试，发布时关闭**。

**Q: 如何调整上位机 IP？**
> 同时修改两处（保持一致）：
> 1. `main.c` 第 107 行：`DESIP[4] = {x, x, x, x};`
> 2. `qdx_tcp_logic.c` 第 58 行：`SERVER_IP = "x.x.x.x";`
