docs: rewrite mux/net/link protocol manuals

This commit is contained in:
2026-04-03 16:47:15 +08:00
parent ac04bfc923
commit 6f4ba247a4
3 changed files with 512 additions and 790 deletions
+144 -230
View File
@@ -1,234 +1,192 @@
# TCP2UART 项目技术实现
## 一、当前实现结论
## 一、文档目的
当前工程已经从原先的 `FreeRTOS + lwIP socket/netconn` 方向,重构为适配 `STM32F103R8T6` 的裸机实现
本文档描述 `TCP2UART` 项目的最终内部实现口径
当前基线特征如下
本文档只围绕最终协议模型展开
1. MCU 目标固定为 `STM32F103R8T6 / STM32F103xB`
2. 软件架构改为 `bare-metal main loop + DMA/IDLE + EXTI`
3. 网络栈采用 `lwIP RAW API + NO_SYS=1`
4. 调试输出采用 `SEGGER RTT`
5. `CH390` 运行时访问已收敛为单一拥有者 `ch390_runtime`
6. 构建目标已通过 `MDK-ARM` 编译,适配 `64KB Flash / 20KB SRAM`
- `MUX`:串口承载层
- `NET`:全局网络配置层
- `LINK[idx]`:实例配置与连接管理层
## 二、硬件与资源约束
不再保留历史 `S1... / C1...` 外部字段模型。
### 2.1 MCU
## 二、当前工程基础
- 型号:`STM32F103R8T6`
- Flash`64 KB`
- SRAM`20 KB`
- 主频:`72 MHz`
当前工程基础约束如下:
### 2.2 主要外设
1. MCU`STM32F103R8T6`
2. 网络芯片:`CH390D`
3. 软件架构:`bare-metal main loop`
4. 协议栈:`lwIP RAW API + NO_SYS=1`
5. 调试输出:`SEGGER RTT`
6. 不使用 `FreeRTOS`
7. 不实现 DHCP
- `SPI1`:连接 `CH390D`
- `USART1`:配置串口
- `USART2`Server 透传串口
- `USART3`Client 透传串口
- `DMA1`UART 收发 DMA
- `EXTI0`CH390 中断输入
- `IWDG`:独立看门狗
- `TIM4`LED 心跳定时器
当前说明:
1. `IWDG` 外设仍保留在工程中,但当前调试基线默认不在 `main()` 中启用 `MX_IWDG_Init()`
2. `App_Poll()` 已对 `HAL_IWDG_Refresh(&hiwdg)` 做句柄保护,避免未初始化句柄导致 `HardFault`
### 2.3 当前引脚分配
| 引脚 | 功能 | 用途 |
|------|------|------|
| PA2 | USART2_TX | Server 透传串口 |
| PA3 | USART2_RX | Server 透传串口 |
| PA4 | GPIO_Output | CH390D 片选 |
| PA5 | SPI1_SCK | CH390D SPI 时钟 |
| PA6 | SPI1_MISO | CH390D SPI 数据输入 |
| PA7 | SPI1_MOSI | CH390D SPI 数据输出 |
| PA9 | USART1_TX | 配置串口 |
| PA10 | USART1_RX | 配置串口 |
| PB0 | EXTI0 | CH390D INT |
| PB1 | GPIO_Output | CH390D RESET |
| PB10 | USART3_TX | Client 透传串口 |
| PB11 | USART3_RX | Client 透传串口 |
| PC13 | GPIO_Output | 状态 LED |
| PD0/PD1 | HSE | 8MHz 外部晶振 |
## 三、架构选择原因
`STM32F103R8T6` 的资源上限不足以稳定承载原方案中的以下组合:
1. `FreeRTOS`
2. `CMSIS-RTOS V2`
3. 多任务栈
4. `lwIP socket/netconn/tcpip` OS 路线
5. `StreamBuffer / Semaphore / Mutex`
因此当前实现采用如下组合:
1. 去掉 `FreeRTOS`
2. 去掉 `CMSIS-RTOS V2`
3. 去掉 `lwIP socket/netconn`
4. 改为 `lwIP RAW API + NO_SYS=1`
5. 串口与网口统一由主循环推进
## 四、当前软件架构
### 4.1 分层
## 三、总体架构
```text
+--------------------------------------------------+
| Application Logic |
| config / tcp_server / tcp_client / uart bridge |
| AT / Control Plane |
| USART1 AT parser + MUX control frame parser |
+--------------------------------------------------+
| Main Poll Loop |
| ethernetif_poll / sys_check_timeouts / watchdog |
| Configuration Model |
| MUX / NET / LINK[idx] |
+--------------------------------------------------+
| CH390 Runtime Owner |
| ch390_runtime (single runtime SPI owner) |
| Routing & Session Layer |
| TCP instance scheduling + UART dispatch |
+--------------------------------------------------+
| Peripheral/Event Layer |
| UART DMA+IDLE / DMA IRQ / EXTI / SysTick |
| Transport Poll Loop |
| ethernetif_poll / sys_check_timeouts / uart poll |
+--------------------------------------------------+
| Drivers |
| CH390 / lwIP netif / HAL |
| Driver Layer |
| CH390 / lwIP netif / UART DMA+IDLE / HAL |
+--------------------------------------------------+
```
### 4.2 执行模型
## 四、最终协议实现模型
当前执行模型为:
### 4.1 MUX 帧承载层
1. `SysTick` 提供全局毫秒时基
2. `EXTI0` 只置位 CH390 待处理标志,不直接做 SPI/CH390 访问
3. `DMA IRQ``UART IRQ` 只完成回调分发与 IDLE 采样
4. `ch390_runtime` 成为唯一的 CH390 运行时访问源
5. 主循环统一执行网络轮询、超时推进、串口桥接和看门狗喂狗
数据口启用 MUX 后,统一处理如下帧:
## 五、当前模块实现状态
```text
SYNC | LEN_H | LEN_L | SRCID | DSTMASK | PAYLOAD | TAIL
```
### 5.1 配置模块
实现职责:
文件:`App/config.c/.h`
1. 识别帧边界
2. 解析长度字段
3. 提取 `SRCID`
4. 解析 `DSTMASK`
5. 按控制帧或数据帧分流
已实现:
### 4.2 控制帧与数据帧分离
1. 从 Flash 加载配置
2. UART1 命令口接收
3. 常用网络与串口参数解析
4. 参数保存与软复位请求
控制规则固定如下:
当前约束:
- `DSTMASK = 0x00`:系统控制帧
- `DSTMASK != 0x00`:业务数据帧
1. 构建已关闭 `DHCP`,因此 `AT+DHCP=1` 会明确返回错误
2. 配置损坏时会回退默认值,但默认值不会自动写回 Flash,仍需手动 `AT+SAVE`
系统控制帧处理要求:
### 5.2 UART 透传模块
1. `PAYLOAD` 解释为 AT 文本
2. AT 文本必须以 `\r\n` 结束
3. 控制帧进入 AT 命令处理链路
文件:`App/uart_trans.c/.h`
业务数据帧处理要求:
已实现:
1. `SRCID` 表示单一源端点
2. `DSTMASK` 表示目标端点集合
3. 路由层根据 `DSTMASK` 做多目标分发
1. `USART2/USART3` 使用 `DMA + IDLE`
2. RX 使用 DMA 缓冲转环形缓冲
3. TX 使用 DMA 发送
4. TX/RX 完成由 `HAL_UART_*Callback` 驱动
### 4.3 统一端点编码
### 5.3 TCP Server 模块
内部与外部文档统一使用以下端点编码:
文件:`App/tcp_server.c/.h`
| 端点 | 编码 |
|------|------|
| `C1` | `0x01` |
| `C2` | `0x02` |
| `UART2` | `0x04` |
| `UART3` | `0x08` |
| `S1` | `0x10` |
| `S2` | `0x20` |
实现:
实现要求
1. `lwIP RAW API` 监听指定端口
2. 单连接接入
3. 网络数据写入本地环形缓冲
4. 主循环中与 UART2 做双向桥接
- `SRCID` 为单值
- `DSTMASK` 为位图
- `DSTMASK=0x00` 仅保留为控制帧
### 5.4 TCP Client 模块
## 五、配置层设计
文件:`App/tcp_client.c/.h`
### 5.1 MUX 记录
已实现:
`MUX` 为全局记录,仅控制设备数据口是否进入 MUX 承载模式。
1. `lwIP RAW API` 主动连接远端地址
2. 断链后按周期重连
3. 网络数据写入本地环形缓冲
4. 主循环中与 UART3 做双向桥接
取值:
### 5.5 CH390 与 netif 模块
- `0`:普通透传
- `1`MUX 透传
文件:`Drivers/CH390/*``Drivers/LwIP/src/netif/*`
### 5.2 NET 记录
已实现
`NET` 为全局静态网络记录
1. `SPI1 + GPIO CS + EXTI0` 驱动 CH390
2. `ethernetif.c` 采用 `NO_SYS=1` 路线
3. 新增 `Drivers/CH390/ch390_runtime.c`,统一负责 CH390 初始化、链路查询、IRQ pending 消费、RX/TX 服务与启动诊断快照
4. `main.c` 不再直接读取 CH390 原始寄存器,启动诊断通过 `ch390_runtime_get_diag()` 获取快照
5. `EXTI0_IRQHandler()` 只投递 IRQ pending,不再直接混入 CH390 访问
6. 配置中的 MAC 地址会在初始化时写入 CH390
```text
IP,MASK,GW,MAC
```
当前状态
说明
1. 运行时架构层面的 `SPI/LwIP/CH390` 多源访问问题已经消除
2. `HardFault` 与“运行一会儿卡死”问题已修复
3. CH390D 当前已恢复基础寄存器读写,调试重点已从“SPI 是否完全不通”转入初始化完整性、链路、中断与收发功能验证
4. 最终实板定位表明,一颗 CH390D 供电滤波电容虚焊会直接导致供电不稳,并放大为网络收发异常
- 设备只有一张网卡,因此不为每个实例单独配置本地 IP
- 当前实现目标中不包含 DHCP
### 5.6 RTT 调试输出
### 5.3 LINK 记录
文件:`Middlewares/Third_Party/SEGGER_RTT/*`
`LINK[idx]` 为统一实例记录:
已实现:
```text
EN,LPORT,RIP,RPORT,UART
```
1. 工程内置最小 `SEGGER RTT` 源文件
2. `main.c``printf/fputc` 已重定向到 RTT
固定索引映射:
### 5.7 TIM4 心跳闪烁
- `0 = S1`
- `1 = S2`
- `2 = C1`
- `3 = C2`
文件:`Core/Src/tim.c``Core/Src/main.c``Core/Src/stm32f1xx_it.c`
字段职责:
已实现:
- `EN`:实例启用状态
- `LPORT`:本地端口
- `RIP / RPORT`:对端地址与端口
- `UART`:对应业务数据口
1. 使用 `TIM4` 作为 LED 心跳定时器
2. `TIM4` 时钟来自 `APB1 Timer Clock = 72 MHz`
3. 通过 `Prescaler = 7199``Period = 9` 生成 `1 ms` 更新中断
4.`HAL_TIM_PeriodElapsedCallback()` 中进行 1ms 计数
5. 累计 `1000` 次后翻转一次 `PC13`,形成 `1 s` 闪烁节拍
说明:
当前实现说明:
- `Server``Client` 共享同一记录结构
- `Server``RIP / RPORT` 可作为对端约束或预设
- `Client``RIP / RPORT` 表示远端目标
1. `PC13` 为低电平点亮、高电平熄灭
2. 当前逻辑为每 `1 s` 翻转一次 LED 状态,即完整亮灭周期为 `2 s`
3. 若后续需要“每 1 秒完整闪烁一次”,可改为 `500 ms` 翻转一次
## 六、模块职责调整
## 六、lwIP 配置策略
### 6.1 配置模块 `config.c/.h`
当前 `lwIP` 配置以适配 `R8T6` 资源为原则,核心策略如下
最终职责
1. `NO_SYS = 1`
2. `LWIP_SOCKET = 0`
3. `LWIP_NETCONN = 0`
4. `LWIP_NETIF_API = 0`
5. `LWIP_DHCP = 0`
6. `LWIP_UDP = 0`
7. `LWIP_DNS = 0`
8. `LWIP_IGMP = 0`
9. 关闭 `lwIP` 平台诊断 `printf`
1. 解析 `AT+MUX`
2. 解析 `AT+NET`
3. 解析 `AT+LINK`
4. 加载与保存配置
5. 处理 `SAVE / RESET / DEFAULT`
同时从 `MDK` 工程中移除了:
不再以历史展开式字段作为外部接口模型。
1. `FreeRTOS` 相关源码
2. `lwIP api/socket/netconn/tcpip` 路线源码
3. `altcp / autoip / acd / dhcp / dns / igmp` 等当前不需要模块
### 6.2 UART 透传模块 `uart_trans.c/.h`
## 七、主循环实际骨架
最终职责:
当前主循环逻辑可概括为:
1. 保持 `USART2 / USART3``DMA + IDLE` 接收发送基线
2.`MUX=0` 时执行普通透传
3.`MUX=1` 时执行 MUX 帧收发
4. 将控制帧与业务数据帧分流
### 6.3 TCP Server / Client 模块
最终职责:
1. 不再从外部协议角度区分不同字段模型
2. 统一受 `LINK[idx]` 配置驱动
3. 由调度层决定实例与 UART 的数据交换路径
## 七、主循环实现方向
主循环仍保持裸机轮询风格:
```c
while (1)
@@ -236,81 +194,37 @@ while (1)
ethernetif_poll();
ethernetif_check_link();
sys_check_timeouts();
tcp_client_poll();
uart_trans_poll();
tcp_link_poll();
uart_mux_poll();
config_poll();
tcp_server <-> UART2;
tcp_client <-> UART3;
route_dispatch();
if (reset_requested) {
NVIC_SystemReset();
}
if (hiwdg.Instance == IWDG) {
HAL_IWDG_Refresh(&hiwdg);
}
}
```
## 八、当前构建状态
下一阶段实现要求:
### 8.1 MDK 构建命令
1. 统一由 `LINK[idx]` 驱动实例状态
2. 统一由 `MUX` 决定数据口承载模式
3. 统一由 `route_dispatch()``SRCID / DSTMASK` 分发
```bat
"C:\Keil_v5\UV4\UV4.exe" -b "D:\code\STM32Project\TCP2UART\MDK-ARM\TCP2UART.uvprojx" -j0
```
## 八、实现边界
### 8.2 当前结果
1. 保持单网卡静态网络模型
2. 不实现 DHCP
3. 不实现旧 `S1... / C1...` 外部协议字段
4. 不在文档中保留兼容层描述
5. 所有 AT 文本控制统一要求 `\r\n` 结束
当前构建结果:
## 九、文档一致性要求
1. `0 Error(s)`
2. `0 Warning(s)`
3. 代码体积仍满足 `STM32F103R8T6` 资源约束
4. `MDK-ARM` 工程可直接编译并下载验证
后续实现、联调、测试与代码注释必须遵守以下统一口径:
说明当前版本已经满足:
1. `STM32F103R8T6 64KB Flash` 约束
2. `20KB SRAM` 约束
3. `MDK-ARM` 可直接编译
## 九、当前已知限制与待验证项
### 9.1 功能限制
1. 当前使用静态 IP,不支持 DHCP
2. 当前已验证 CH390 基础寄存器读写、PHY 管理寄存器访问与 lwIP `netif` 链路置位路径;RX/TX 实际业务流量仍需继续做板上验证
3. 目前未提供完整的上板网络吞吐、丢包率与长时间稳定性报告
4. `config` 模块仍保留较重的字符串解析逻辑,但当前体积已可接受
### 9.2 上板验证重点
1. 验证 CH390 `RST/CS/SCK/MOSI/MISO/INT` 在芯片脚侧的实际波形与当前软件假设一致
2. 验证 `VID/PID/REV`、MAC 写回、`RCR/IMR/INTCR`、PHY 寄存器与 `LINK`/`netif` 链路状态在多次上电下稳定一致
3. 验证 `TIM4` 1ms 中断稳定性与 `PC13` 1秒翻转节拍
4. 验证 `UART2/UART3 DMA + IDLE` 在长连续流量下的行为
5. 验证 TCP Server 与 TCP Client 双链路同时工作时的稳定性
6. 验证配置保存、复位、MAC 生效路径
7. 验证 CH390 收发路径、链路变化中断与 RX/TX 数据通路
## 十、后续建议
下一阶段建议按以下顺序推进:
1. 在当前可读写基线下,优先验证 `default_config`、MAC、PHY 协商/链路、IRQ、RX/TX 是否完整生效
2. 同步用芯片脚侧波形与电源域量测验证 `RST/CS/SCK/MOSI/MISO/INT``VDDK/AVDD33/VDDIO/AVDD33`
3. 若链路与寄存器状态可信,再推进 TCP Server / TCP Client 与 UART2 / UART3 的双向联调
4. 完成后补充吞吐、丢包、长稳与异常恢复测试
## 十一、当前结论
截至本轮调试:
1. 系统主循环、RTT、定时器心跳、UART 配置路径均可正常工作
2. 已修复并验证多个真实软件问题,且相关中间里程碑已提交版本库
3. CH390D 当前已恢复基础寄存器读写,且已在实机上验证 `VID=0x1C00``PID=0x9151``REV=0x2B`、PHY ID 可读
4. 运行时 `lwIP netif` 已观察到 `LINK_UP` 置位,说明当前阶段已不再是“完全无响应”或“链路始终未起”
5. 当前硬件修复后,ARP/Ping 基础链路已验证通过,后续重点转为业务流量与长稳验证
6. 板级供电完整性应作为 CH390D 调试前置检查项,而不是放到软件排查后期才介入
1. 对外协议只使用 `MUX / NET / LINK`
2. 控制帧只使用 `DSTMASK=0x00`
3. MUX 帧格式固定为 `SYNC | LEN_H | LEN_L | SRCID | DSTMASK | PAYLOAD | TAIL`
4. AT 手册、需求说明、技术实现三份文档不得再出现历史展开式字段