✨ 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 按需截图工作方式 - 列出错误码表和对接故障排查步骤
234 lines
10 KiB
Markdown
234 lines
10 KiB
Markdown
# CH32V307 固件系统总览
|
||
|
||
> 文档版本:1.0 · 日期:2026-03-15 · 状态:已发布
|
||
|
||
---
|
||
|
||
## 1. 项目背景与硬件平台
|
||
|
||
### 1.1 项目概述
|
||
|
||
本固件运行于 CH32V307WCU6 微控制器,连接 Mini212G2(256×192)红外热像传感器,通过 1000M RGMII 以太网实时向上位机(ConfigServer)上报温度数据。
|
||
|
||
系统支持两种主要工作模式,均在 FreeRTOS 多任务框架下运行:
|
||
|
||
- **2D 模式**:矩阵温度帧触发采集(外部 GPIO 触发或内部温度阈值触发)
|
||
- **1D 模式**:时间轴温度序列采集(外部 GPIO 触发或内部连续热帧检测)
|
||
|
||
### 1.2 硬件配置
|
||
|
||
| 项目 | 规格 |
|
||
|------|------|
|
||
| MCU | CH32V307WCU6,RISC-V,144 MHz |
|
||
| FLASH | 128 KB(Option Bytes 配置 `FLASH_128_SRAM_192`) |
|
||
| SRAM | 192 KB |
|
||
| FreeRTOS Heap | 16 KB(Heap_4) |
|
||
| 传感器 | Mini212G2,256×192,TMP 模式(0.1°C/LSB) |
|
||
| 传感器接口 | DVP 8-bit CMOS,硬件 DMA ping-pong |
|
||
| 以太网 | 1000M RGMII |
|
||
| 调试串口 | USART3(PB10 TX / PB11 RX),921600 baud |
|
||
| 外部触发输入 | PA15 / EXTI15,上升沿,内部下拉 |
|
||
| NG 输出 | PA8,推挽,高电平有效 |
|
||
|
||
> **TMP 模式说明**:传感器必须预配置为 TMP 模式(非 Y16 原始 ADC),输出值为 0.1°C/LSB 的绝对温度,无需 MCU 换算。配置方法见 `Doc/Mini212G2预配置指南.md`。
|
||
|
||
---
|
||
|
||
## 2. FreeRTOS 任务拓扑
|
||
|
||
### 2.1 任务列表
|
||
|
||
| 任务名 | 优先级 | 栈(words) | 条件 | 职责 |
|
||
|--------|--------|-------------|------|------|
|
||
| `task_wchnet_entry` | 6(最高) | 512 | 始终创建 | WCHNET 协议栈驱动,每 5 ms 轮询 |
|
||
| `task_business_entry` | 5 | 512 | 始终创建 | DVP 帧消费、2D/1D 状态机、TCP 发送 |
|
||
| `task_test_pattern_entry` | 4 | 256 | `TEST_PATTERN_MODE=1` 时 | 仿真传感器数据(不含真实DVP) |
|
||
| `task_heartbeat_entry` | 3(最低) | 256 | 始终创建 | 调试心跳打印,每 2 s 一次 |
|
||
|
||
### 2.2 任务间数据流
|
||
|
||
```
|
||
传感器(DVP 硬件)
|
||
│ 每行 512 B,DMA ping-pong
|
||
↓
|
||
DVP_IRQHandler(WCH-Interrupt-fast)
|
||
│ ① STR_FRM → current_line_idx = 0
|
||
│ ② ROW_DONE → memcpy → FrameBuffer[idx]
|
||
│ ③ idx == 191 → Frame_Ready_Flag = 1
|
||
↓
|
||
task_business_entry(优先级 5)
|
||
│ 轮询 Frame_Ready_Flag
|
||
│ 读取 FrameBuffer(共享内存)
|
||
│ 执行 Preprocess_Execute / get_1d_sample
|
||
↓
|
||
TcpLogic_BuildAndSendTemperatureFrame
|
||
│ 零拷贝写入帧头(HeadOffset 空间复用)
|
||
↓
|
||
task_wchnet_entry(优先级 6)
|
||
│ WCHNET_MainTask / WCHNET_HandleGlobalInt
|
||
↓
|
||
以太网 → ConfigServer
|
||
```
|
||
|
||
**关键同步机制**:
|
||
- `Frame_Ready_Flag`:`volatile uint8_t`,IRQ 置 1,业务任务读取后清 0
|
||
- `FrameBuffer`:`uint8_t[192][512]`,IRQ 写入,业务任务只读
|
||
- 双缓冲 TX:`g_TxNetBuffer_A` / `g_TxNetBuffer_B`,`use_buffer_A` 标志交替,保证一帧发送未完时下一帧可立即写入
|
||
- `qdx_port_net_lock/unlock`:互斥量保护 WCHNET API,防止业务任务和网络任务并发
|
||
|
||
---
|
||
|
||
## 3. 系统启动序列
|
||
|
||
`main()` 按以下顺序执行初始化,各步骤依赖前序完成:
|
||
|
||
```
|
||
SystemCoreClockUpdate() → 更新 SystemCoreClock(144 MHz)
|
||
Delay_Init() → SysTick 初始化,提供 sys_tick_ms 计时
|
||
USART_Printf_Init(921600) → USART3 调试串口(PB10/PB11)
|
||
Config_Flash_SRAM(FLASH_128_SRAM_192) → Option Bytes:FLASH=128K,SRAM=192K
|
||
(若已配置跳过;否则写入后系统复位)
|
||
DVP_Init() → GPIO 配置、DMA ping-pong 缓冲、IRQ 使能
|
||
TIM2_Init() → WCHNET 定时器(1 ms 周期)
|
||
ExtTrigger_GPIO_Init() → PA15 EXTI15,上升沿中断
|
||
NG_GPIO_Init() → PA8 推挽输出,默认低
|
||
ETH_LibInit(IP, GW, Mask, MAC) → WCHNET 协议栈初始化,1000M RGMII
|
||
WCHNET_ConfigKeepLive(20000,15000,9) → TCP Keepalive
|
||
qdx_port_init() → QDX 网络层 socket/互斥量初始化
|
||
Preprocess_Init(256, 192) → 图像预处理模块
|
||
TcpLogic_Init(MACAddr, NULL) → TCP 逻辑层,注册 DeviceUUID=MAC
|
||
TcpLogic_Register*Callback() → 注册 OnConfigUpdate / OnDetectionResult / OnTempFrameRequest
|
||
TcpLogic_Start() → 启动后台连接状态机(控制流 → 握手 → 数据流)
|
||
xTaskCreate(×3 或 ×4) → 创建 RTOS 任务
|
||
vTaskStartScheduler() → 启动调度器(不返回)
|
||
```
|
||
|
||
> **Option Bytes 说明**:首次上电若 Flash/SRAM 分配不符,`Config_Flash_SRAM` 会写入 Option Bytes 并触发 `NVIC_SystemReset()`,复位后以新分配重新启动。正常运行时该函数直接返回。
|
||
|
||
---
|
||
|
||
## 4. 2D 状态机
|
||
|
||
2D 模式在 `task_business_entry` 中,每帧调用 `handle_2d_trigger()`,由 4 个状态变量组成隐式状态机:
|
||
|
||
### 4.1 状态转换图
|
||
|
||
```
|
||
┌─────────────────── IDLE ──────────────────────────┐
|
||
│ │
|
||
│ TriggerMode=1(外部) │ TriggerMode=0(内部)
|
||
│ PA15 上升沿 → g_ext_trigger_flag=1 │ Preprocess_CheckInternalTrigger2D()==1
|
||
↓ ↓
|
||
DEBOUNCE (直接)
|
||
等待 DebounceIntervalMs │
|
||
│ │
|
||
└──────────────────────────────────────────────────→┤
|
||
↓
|
||
DELAY
|
||
等待 TriggerDelayMs
|
||
│
|
||
↓
|
||
BURST(循环)
|
||
发送第 1 帧(立即)
|
||
+ 剩余 BurstCount-1 帧
|
||
@ TriggerInternalIntervalMs 间隔
|
||
│
|
||
burst_remaining == 0
|
||
│
|
||
↓
|
||
→ IDLE
|
||
```
|
||
|
||
### 4.2 状态参数
|
||
|
||
| 配置字段 | 默认值 | 说明 |
|
||
|----------|--------|------|
|
||
| `TriggerMode` | 0 | 0=内部温度阈值,1=外部 GPIO |
|
||
| `TriggerDebounceIntervalMs` | 0 | 外部触发防抖等待时间(ms) |
|
||
| `TriggerDelayMs` | 0 | 触发确认到第一帧采集的延迟(ms) |
|
||
| `TriggerBurstCount` | 3 | 每次触发发送帧数(DEFAULT_BURST_COUNT=3) |
|
||
| `TriggerInternalIntervalMs` | 200 | 连拍帧间隔(DEFAULT_BURST_INTERVAL_MS=200 ms) |
|
||
| `TriggerCondition` | 0 | 内部触发判据:0=Avg,1=Max |
|
||
| `TriggerTemperatureThreshold` | — | 内部触发温度阈值(0.1°C/LSB) |
|
||
| `TriggerRoiX/Y/W/H` | — | 内部触发检测 ROI 区域 |
|
||
|
||
### 4.3 双缓冲 TX 策略
|
||
|
||
每次 `do_2d_capture_send()` 交替选择 `g_TxNetBuffer_A` / `g_TxNetBuffer_B`,通过 `use_buffer_A` 标志取反实现切换。TCP 发送入队后立即切换,保证下一帧填充不覆盖正在传输的缓冲区。
|
||
|
||
---
|
||
|
||
## 5. 1D 状态机
|
||
|
||
1D 模式以每帧全帧最大温度作为一个采样点,在 `task_business_entry` 中每帧调用 `handle_1d_trigger()`。
|
||
|
||
### 5.1 状态图
|
||
|
||
```
|
||
S1D_IDLE
|
||
│
|
||
├─ TriggerType=2(外部):PA15 上升沿
|
||
│ → S1D_DEBOUNCE(等待 HighTimerLimit ms)
|
||
│ → S1D_COLLECTING
|
||
│
|
||
└─ TriggerType=1(内部):维护 3 帧滑动窗口
|
||
连续 3 帧最大温度 ≥ TriggerTempLimit
|
||
→ S1D_COLLECTING(直接,含预触发 3 帧数据)
|
||
|
||
S1D_COLLECTING(每帧采一个样本)
|
||
├─ 记录 sample = 全帧最大温度,time_offset = ms - start_time
|
||
├─ 热帧(≥ thresh):s1d_consec_hot++,consec_cold=0
|
||
│ 满足 3 次热 → s1d_triggered=1
|
||
└─ 停止条件(任意一满足):
|
||
① s1d_count ≥ MAX_1D_POINTS(512)
|
||
② s1d_count ≥ BufferSize
|
||
③ s1d_triggered && s1d_consec_cold ≥ NgCountLimit
|
||
└─ 若 triggered → send_1d_collection()
|
||
否则 → 丢弃,reset
|
||
→ S1D_IDLE
|
||
```
|
||
|
||
### 5.2 数据格式
|
||
|
||
每个样本 **4 字节**,小端序:
|
||
|
||
| 字节 | 字段 | 类型 | 说明 |
|
||
|------|------|------|------|
|
||
| 0–1 | `TimeOffset` | uint16_t LE | 相对采集开始的 ms 偏移 |
|
||
| 2–3 | `Temperature` | uint16_t LE | 全帧最大温度,0.1°C/LSB |
|
||
|
||
### 5.3 切片参数
|
||
|
||
发送前对采集缓冲区切片:有效区间 = `[LSizeStart, count - RSizeStart)`,去除头尾噪声点。若切片越界则退化为全量发送并打印告警。
|
||
|
||
---
|
||
|
||
## 6. TEMP_REQ 辅助通道
|
||
|
||
服务器可通过控制流随时请求单帧快照,无需等待自主采集触发:
|
||
|
||
```
|
||
服务器发送 TEMP_REQ(含 is2dRequest 字段)
|
||
→ OnTempFrameRequest() 回调
|
||
→ g_temp_req_pending = 1,g_temp_req_is2d = is2dRequest
|
||
|
||
task_business_entry 业务循环检测到 g_temp_req_pending:
|
||
→ TcpLogic_GetLatestConfig() 确认对应模式 Enabled
|
||
→ is2d=1:Preprocess_Execute() + TcpLogic_BuildAndSendTemperatureFrame(SocketType=0x02)
|
||
is2d=0:send_1d_snapshot()(中心行 30 个等间距采样点,时间偏移仿真 0~600 ms)
|
||
```
|
||
|
||
**限制**:仅在对应模式(`t2.Enabled` / `t1.Enabled`)为 1 时响应;若未 Enabled,打印 DBG_ERR 并忽略请求。
|
||
|
||
---
|
||
|
||
## 7. 相关文档
|
||
|
||
| 文档 | 内容 |
|
||
|------|------|
|
||
| [DVP模块设计.md](DVP模块设计.md) | DVP 硬件初始化、DMA、IRQ、FrameBuffer 格式 |
|
||
| [QDX协议设计.md](QDX协议设计.md) | TLV 帧结构、零拷贝 TX、分片机制 |
|
||
| [TCP通信模块设计.md](TCP通信模块设计.md) | 双流连接、心跳、配置缓存 |
|
||
| [对接集成指南.md](对接集成指南.md) | 外部对接方接入手册 |
|
||
| [Mini212G2预配置指南.md](../Mini212G2预配置指南.md) | 传感器 TMP 模式配置 HEX 命令 |
|