✨ 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 按需截图工作方式 - 列出错误码表和对接故障排查步骤
203 lines
7.2 KiB
Markdown
203 lines
7.2 KiB
Markdown
# QDX 协议设计文档
|
||
|
||
> 文档版本:1.0 · 日期:2026-03-15 · 状态:已发布
|
||
|
||
---
|
||
|
||
## 1. 模块概述
|
||
|
||
QDXnetworkStack 是本固件使用的应用层通信协议栈,基于 TLV(Type-Length-Value)帧格式,运行在 TCP/IP 之上。协议设计重点:
|
||
|
||
- **零拷贝 TX**:预留帧头空间(HeadOffset),像素数据直接写入发送缓冲区,帧头在发送前原地写入
|
||
- **双流架构**:控制流(5511)与数据流(5512)职责分离
|
||
- **平台无关**:所有结构体 `#pragma pack(push, 1)`,1 字节对齐,可在任意平台解析
|
||
|
||
源文件:`Middle/QDXnetworkStack/`
|
||
|
||
---
|
||
|
||
## 2. 帧结构
|
||
|
||
### 2.1 完整帧布局
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ FrameHeader(16 字节) │
|
||
│ TLV Header(3 字节) │
|
||
│ Value(N 字节) │
|
||
│ CRC16(2 字节,Modbus CRC16,覆盖 FrameHeader+TLV+Value)│
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
总帧长 = 16 + 3 + N + 2 = **N + 21** 字节
|
||
|
||
### 2.2 FrameHeader(16 字节)
|
||
|
||
```c
|
||
typedef struct {
|
||
uint16_t Magic; /* [0-1] 0x55AA — 帧同步魔数 */
|
||
uint8_t Version; /* [2] 0x20 — 协议版本 v2.0 */
|
||
uint16_t Length; /* [3-4] 整帧字节数(含 Header,不含 CRC) */
|
||
uint16_t Sequence; /* [5-6] 单调递增帧序号(LE) */
|
||
uint32_t Timestamp; /* [7-10] Unix 时间戳或 ms 计数(LE) */
|
||
uint8_t Source; /* [11] 0x01=MCU,0x02=Server */
|
||
uint16_t DevID; /* [12-13]设备 ID(LE) */
|
||
uint8_t Class; /* [14] 消息类别 */
|
||
uint8_t Flags; /* [15] 控制标志位 */
|
||
} FrameHeader_t; /* 共 16 字节,1 字节对齐 */
|
||
```
|
||
|
||
### 2.3 TLV Header(3 字节)
|
||
|
||
```c
|
||
typedef struct {
|
||
uint8_t Type; /* [0] 帧类型 */
|
||
uint16_t Length; /* [1-2] Value 区域字节数(LE) */
|
||
} TLV_t;
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Class 与 Type 映射表
|
||
|
||
### 3.1 消息类别(Class)
|
||
|
||
| 常量 | 值 | 说明 |
|
||
|------|----|------|
|
||
| `CLASS_CONTROL` | `0x01` | 配置 / 控制命令(服务器 → MCU) |
|
||
| `CLASS_DATA` | `0x02` | 实时数据上报(MCU → 服务器) |
|
||
| `CLASS_RESPONSE` | `0x03` | ACK / NACK / 错误响应 |
|
||
| `CLASS_SYSTEM` | `0x04` | 握手 / 心跳 / 系统同步 |
|
||
|
||
### 3.2 帧类型(Type)
|
||
|
||
| 常量 | 值 | 方向 | 说明 |
|
||
|------|----|------|------|
|
||
| `TYPE_HANDSHAKE` | `0x01` | 双向 | 握手,Class=SYSTEM |
|
||
| `TYPE_HEARTBEAT` | `0x02` | 双向 | 心跳保活,Class=SYSTEM |
|
||
| `TYPE_SYNC_TIME` | `0x03` | Server→MCU | 时间同步 |
|
||
| `TYPE_DEVID_ASSIGN` | `0x05` | Server→MCU | 设备 ID 分配 |
|
||
| `TYPE_TEMP_FRAME` | `0x10` | MCU→Server | 温度帧(2D/1D),Class=DATA |
|
||
| `TYPE_RAW_FRAME` | `0x11` | MCU→Server | 原始帧(预留) |
|
||
| `TYPE_CONFIG_COMMON` | `0x20` | Server→MCU | 公共配置 |
|
||
| `TYPE_CONFIG_2D` | `0x22` | Server→MCU | 2D 模式配置 |
|
||
| `TYPE_CONFIG_1D` | `0x23` | Server→MCU | 1D 模式配置 |
|
||
| `TYPE_ACK_PAYLOAD` | `0x30` | 双向 | ACK 响应体 |
|
||
| `TYPE_DETECTION_RESULT` | `0x40` | Server→MCU | 检测结果(含 NG 判定) |
|
||
|
||
### 3.3 Flags 字段位定义
|
||
|
||
| 位掩码 | 常量 | 说明 |
|
||
|--------|------|------|
|
||
| `0x03` | `FLAG_PRIORITY_MASK` | 优先级 0-3(0=最低) |
|
||
| `0x04` | `FLAG_COMPRESSED` | 压缩标志(当前固件未使用) |
|
||
| `0x08` | `FLAG_ENCRYPTED` | 加密标志(当前固件未使用) |
|
||
| `0x10` | `FLAG_ACK_REQ` | 要求接收方回复 ACK |
|
||
| `0x20` | `FLAG_LAST_FRAGMENT` | 分片末片标志 |
|
||
|
||
---
|
||
|
||
## 4. 零拷贝 TX 架构
|
||
|
||
### 4.1 TcpTxBuffer_t 结构
|
||
|
||
```c
|
||
typedef struct {
|
||
uint8_t *pBuffer; /* 分配的内存起点 */
|
||
uint32_t TotalCapacity; /* 总容量 = 9216 字节 */
|
||
uint32_t HeadOffset; /* 预留帧头空间 = 64 字节 */
|
||
uint32_t ValidPayloadLen;/* 当前有效 Value 数据长度 */
|
||
} TcpTxBuffer_t;
|
||
```
|
||
|
||
### 4.2 缓冲区内存布局
|
||
|
||
```
|
||
pBuffer
|
||
│
|
||
├──[0 ... 63]────────────────── HeadOffset(64 字节预留区)
|
||
│ ← 发送前:写入 FrameHeader(16B) + TLV_Header(3B) = 19 字节
|
||
│ 从 HeadOffset - 19 = 偏移 45 处开始写入(帧头向前填充)
|
||
│
|
||
├──[64 ... 64+ValidPayloadLen-1]── Value 数据(Preprocess 写入)
|
||
│ ← 图像像素 / 1D 样本 / 其他 payload
|
||
│
|
||
└──[64+ValidPayloadLen ... 9215] ── 未使用空间
|
||
+ [尾部 2 字节] CRC16(追加在 Value 之后)
|
||
```
|
||
|
||
### 4.3 有效载荷容量计算
|
||
|
||
```
|
||
最大可用 Value 大小
|
||
= TotalCapacity(9216) - HeadOffset(64) - CRC(2) - TLV_Header(3) - FrameHeader(16)
|
||
= 9131 字节
|
||
|
||
对于 2D 温度帧(每像素 2 字节):
|
||
最多传输 9131 / 2 = 4565 个像素(约 67×67 ROI)
|
||
```
|
||
|
||
### 4.4 双缓冲设计
|
||
|
||
```c
|
||
/* main.c 中声明 */
|
||
uint8_t g_TxNetBuffer_A_Mem[9216];
|
||
uint8_t g_TxNetBuffer_B_Mem[9216];
|
||
|
||
TcpTxBuffer_t g_TxNetBuffer_A = { .pBuffer = g_TxNetBuffer_A_Mem, .TotalCapacity = 9216, .HeadOffset = 64 };
|
||
TcpTxBuffer_t g_TxNetBuffer_B = { .pBuffer = g_TxNetBuffer_B_Mem, .TotalCapacity = 9216, .HeadOffset = 64 };
|
||
```
|
||
|
||
切换逻辑:`use_buffer_A` 标志在每次调用发送函数时取反,保证本帧发送入队后下一帧可立即填写另一个缓冲区。
|
||
|
||
---
|
||
|
||
## 5. 分片机制
|
||
|
||
### 5.1 分片限制
|
||
|
||
| 参数 | 值 | 说明 |
|
||
|------|-----|------|
|
||
| `MAX_FRAGMENT_PAYLOAD` | 1400 字节 | 受 TCP MSS=1460 制约(1460 - HEADER=1400) |
|
||
| TX 缓冲区容量 | 9216 字节 | 单次发送通常不超过此限制,无需分片 |
|
||
|
||
### 5.2 分片标志
|
||
|
||
末片帧的 `Flags` 字段 `FLAG_LAST_FRAGMENT(0x20)` 置位,接收端以此判断分片结束。中间片段该位为 0。
|
||
|
||
> **当前固件实践**:绝大多数 2D 温度帧(最大 9131 字节)直接作为单个 TCP send 调用发送。WCHNET 底层在必要时分拆为多个 TCP 段,但协议层不显式分片。
|
||
|
||
---
|
||
|
||
## 6. Sequence 字段规则
|
||
|
||
- `Sequence` 字段为 `uint16_t`,每发送一帧单调递增
|
||
- 溢出后自然回滚(65535 → 0)
|
||
- 接收端 **不强制要求连续**,但可通过 Sequence 检测丢包(非连续 = 有帧丢失)
|
||
- 不同流(控制流 / 数据流)的 Sequence 互相独立计数
|
||
|
||
---
|
||
|
||
## 7. 错误码
|
||
|
||
| 常量 | 值 | 触发场景 |
|
||
|------|----|---------|
|
||
| `ERR_NONE` | `0x0000` | 无错误 |
|
||
| `ERR_CRC` | `0x1001` | CRC 校验失败 |
|
||
| `ERR_VERSION` | `0x1002` | 协议版本不匹配 |
|
||
| `ERR_LENGTH` | `0x1003` | 帧长度字段与实际不符 |
|
||
| `ERR_AUTH` | `0x2001` | 认证失败(AuthToken 不匹配) |
|
||
| `ERR_BUSY` | `0x2002` | 设备忙,拒绝处理 |
|
||
| `ERR_DEV_ID_CONFLICT` | `0x2003` | DevID 冲突 |
|
||
| `ERR_PARAM` | `0x3001` | 参数非法(配置值越界等) |
|
||
|
||
---
|
||
|
||
## 8. 相关文档
|
||
|
||
| 文档 | 内容 |
|
||
|------|------|
|
||
| [系统总览.md](系统总览.md) | 双缓冲 TX 策略、任务调度 |
|
||
| [TCP通信模块设计.md](TCP通信模块设计.md) | `TcpLogic_BuildAndSendTemperatureFrame` 调用链 |
|
||
| [对接集成指南.md](对接集成指南.md) | 外部接入方协议帧构造示例 |
|