266 lines
6.5 KiB
Markdown
266 lines
6.5 KiB
Markdown
# TCP2UART 项目技术实现
|
||
|
||
## 一、当前实现结论
|
||
|
||
当前工程已经从原先的 `FreeRTOS + lwIP socket/netconn` 方向,重构为适配 `STM32F103R8T6` 的裸机实现。
|
||
|
||
当前基线特征如下:
|
||
|
||
1. MCU 目标固定为 `STM32F103R8T6 / STM32F103xB`
|
||
2. 软件架构改为 `bare-metal main loop + DMA/IDLE + EXTI`
|
||
3. 网络栈采用 `lwIP RAW API + NO_SYS=1`
|
||
4. 调试输出采用 `SEGGER RTT`
|
||
5. 构建目标已通过 `MDK-ARM` 编译,适配 `64KB Flash / 20KB SRAM`
|
||
|
||
## 二、硬件与资源约束
|
||
|
||
### 2.1 MCU
|
||
|
||
- 型号:`STM32F103R8T6`
|
||
- Flash:`64 KB`
|
||
- SRAM:`20 KB`
|
||
- 主频:`72 MHz`
|
||
|
||
### 2.2 主要外设
|
||
|
||
- `SPI1`:连接 `CH390D`
|
||
- `USART1`:配置串口
|
||
- `USART2`:Server 透传串口
|
||
- `USART3`:Client 透传串口
|
||
- `DMA1`:UART 收发 DMA
|
||
- `EXTI0`:CH390 中断输入
|
||
- `IWDG`:独立看门狗
|
||
|
||
### 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 |
|
||
+--------------------------------------------------+
|
||
| Main Poll Loop |
|
||
| ethernetif_poll / sys_check_timeouts / watchdog |
|
||
+--------------------------------------------------+
|
||
| Peripheral/Event Layer |
|
||
| UART DMA+IDLE / DMA IRQ / EXTI / SysTick |
|
||
+--------------------------------------------------+
|
||
| Drivers |
|
||
| CH390 / lwIP netif / HAL |
|
||
+--------------------------------------------------+
|
||
```
|
||
|
||
### 4.2 执行模型
|
||
|
||
当前执行模型为:
|
||
|
||
1. `SysTick` 提供全局毫秒时基
|
||
2. `EXTI0` 只置位 CH390 待处理标志
|
||
3. `DMA IRQ` 和 `UART IRQ` 只完成回调分发与 IDLE 采样
|
||
4. 主循环统一执行网络轮询、超时推进、串口桥接和看门狗喂狗
|
||
|
||
## 五、当前模块实现状态
|
||
|
||
### 5.1 配置模块
|
||
|
||
文件:`App/config.c/.h`
|
||
|
||
已实现:
|
||
|
||
1. 从 Flash 加载配置
|
||
2. UART1 命令口接收
|
||
3. 常用网络与串口参数解析
|
||
4. 参数保存与软复位请求
|
||
|
||
当前约束:
|
||
|
||
1. 构建已关闭 `DHCP`,因此 `AT+DHCP=1` 会明确返回错误
|
||
2. 配置损坏时会回退默认值,但默认值不会自动写回 Flash,仍需手动 `AT+SAVE`
|
||
|
||
### 5.2 UART 透传模块
|
||
|
||
文件:`App/uart_trans.c/.h`
|
||
|
||
已实现:
|
||
|
||
1. `USART2/USART3` 使用 `DMA + IDLE`
|
||
2. RX 使用 DMA 缓冲转环形缓冲
|
||
3. TX 使用 DMA 发送
|
||
4. TX/RX 完成由 `HAL_UART_*Callback` 驱动
|
||
|
||
### 5.3 TCP Server 模块
|
||
|
||
文件:`App/tcp_server.c/.h`
|
||
|
||
已实现:
|
||
|
||
1. `lwIP RAW API` 监听指定端口
|
||
2. 单连接接入
|
||
3. 网络数据写入本地环形缓冲
|
||
4. 主循环中与 UART2 做双向桥接
|
||
|
||
### 5.4 TCP Client 模块
|
||
|
||
文件:`App/tcp_client.c/.h`
|
||
|
||
已实现:
|
||
|
||
1. `lwIP RAW API` 主动连接远端地址
|
||
2. 断链后按周期重连
|
||
3. 网络数据写入本地环形缓冲
|
||
4. 主循环中与 UART3 做双向桥接
|
||
|
||
### 5.5 CH390 与 netif 模块
|
||
|
||
文件:`Drivers/CH390/*`、`Drivers/LwIP/src/netif/*`
|
||
|
||
已实现:
|
||
|
||
1. `SPI1 + GPIO CS + EXTI0` 驱动 CH390
|
||
2. `ethernetif.c` 采用 `NO_SYS=1` 路线
|
||
3. CH390 中断在主循环中轮询处理
|
||
4. 配置中的 MAC 地址会在初始化时写入 CH390
|
||
|
||
### 5.6 RTT 调试输出
|
||
|
||
文件:`Middlewares/Third_Party/SEGGER_RTT/*`
|
||
|
||
已实现:
|
||
|
||
1. 工程内置最小 `SEGGER RTT` 源文件
|
||
2. `main.c` 中 `printf/fputc` 已重定向到 RTT
|
||
|
||
## 六、lwIP 配置策略
|
||
|
||
当前 `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`
|
||
|
||
同时从 `MDK` 工程中移除了:
|
||
|
||
1. `FreeRTOS` 相关源码
|
||
2. `lwIP api/socket/netconn/tcpip` 路线源码
|
||
3. `altcp / autoip / acd / dhcp / dns / igmp` 等当前不需要模块
|
||
|
||
## 七、主循环实际骨架
|
||
|
||
当前主循环逻辑可概括为:
|
||
|
||
```c
|
||
while (1)
|
||
{
|
||
ethernetif_poll();
|
||
ethernetif_check_link();
|
||
sys_check_timeouts();
|
||
tcp_client_poll();
|
||
uart_trans_poll();
|
||
config_poll();
|
||
|
||
tcp_server <-> UART2;
|
||
tcp_client <-> UART3;
|
||
|
||
if (reset_requested) {
|
||
NVIC_SystemReset();
|
||
}
|
||
|
||
HAL_IWDG_Refresh(&hiwdg);
|
||
}
|
||
```
|
||
|
||
## 八、当前构建状态
|
||
|
||
### 8.1 MDK 构建命令
|
||
|
||
```bat
|
||
"C:\Keil_v5\UV4\UV4.exe" -b "D:\code\STM32Project\TCP2UART\MDK-ARM\TCP2UART.uvprojx" -j0
|
||
```
|
||
|
||
### 8.2 当前结果
|
||
|
||
当前构建结果:
|
||
|
||
1. `0 Error(s)`
|
||
2. `0 Warning(s)`
|
||
3. `Code=38664`
|
||
4. `RO-data=1272`
|
||
5. `RW-data=168`
|
||
6. `ZI-data=19120`
|
||
|
||
说明当前版本已经满足:
|
||
|
||
1. `STM32F103R8T6 64KB Flash` 约束
|
||
2. `20KB SRAM` 约束
|
||
3. `MDK-ARM` 可直接编译
|
||
|
||
## 九、当前已知限制与待验证项
|
||
|
||
### 9.1 功能限制
|
||
|
||
1. 当前使用静态 IP,不支持 DHCP
|
||
2. 目前未提供上板网络与串口吞吐测试结论
|
||
3. `config` 模块仍保留较重的字符串解析逻辑,但当前体积已可接受
|
||
|
||
### 9.2 上板验证重点
|
||
|
||
1. 验证 CH390 INT 极性与 EXTI 触发行为
|
||
2. 验证 `SPI1` 与 CH390 的稳定性
|
||
3. 验证 `UART2/UART3 DMA + IDLE` 在长连续流量下的行为
|
||
4. 验证 TCP Server 与 TCP Client 双链路同时工作时的稳定性
|
||
5. 验证配置保存、复位、MAC 生效路径
|
||
|
||
## 十、后续建议
|
||
|
||
下一阶段建议按以下顺序推进:
|
||
|
||
1. 上板联调 CH390 链路与 RTT 输出
|
||
2. 验证 UART2/3 透传功能
|
||
3. 补充双向透传稳定性与丢包测试
|
||
4. 视需要继续优化 `config.c` 的体积与命令集
|
||
5. 若后续必须支持 DHCP,再单独评估资源预算
|