c21d85a9da
- IOC: MCU切换为STM32F103RCTx,添加FREERTOS+TIM4中间件,HAL时间基准改为TIM4 - Keil uvprojx: 目标器件RC,Flash 256KB/48KB SRAM,宏xE,HD Flash算法,启动文件xe.s - EWARM ewp: 宏xE,ICF/启动文件切换为xe版本 - 启动文件: Stack_Size 0x400→0x800适配FreeRTOS - 重写项目需求说明/技术实现文档,描述FreeRTOS 5任务架构+lwIP NO_SYS=0 - 新增AT固件使用手册(MUX/NET/LINK协议)和工程调试指南(FreeRTOS专项)
13 KiB
13 KiB
TCP2UART 项目技术实现
一、文档目的
本文档描述 TCP2UART 项目基于 STM32F103RCT6 + FreeRTOS 的最终内部实现口径。
本文档只围绕最终协议模型展开:
MUX:串口承载层NET:全局网络配置层LINK[idx]:实例配置与连接管理层
不再保留历史 S1... / C1... 外部字段模型。
二、当前工程基础
当前工程基础约束如下:
- MCU:
STM32F103RCT6(256KB Flash / 48KB SRAM) - 网络芯片:
CH390D - 软件架构:
FreeRTOS + lwIP NO_SYS=0 - 协议栈:
lwIP socket/netconn API - 调试输出:
SEGGER RTT - 使用
FreeRTOS任务调度 - 不实现 DHCP
三、总体架构
+--------------------------------------------------+
| AT / Control Plane |
| USART1 AT parser + MUX control frame parser |
+--------------------------------------------------+
| Configuration Model |
| MUX / NET / LINK[idx] |
+--------------------------------------------------+
| FreeRTOS Tasks |
| NetworkTask / UartTask / ConfigTask / RouteTask |
+--------------------------------------------------+
| Inter-Task Communication |
| Queue / Semaphore / Mutex / StreamBuffer |
+--------------------------------------------------+
| lwIP TCP/IP Stack (NO_SYS=0) |
| tcpip_thread + socket/netconn + sys_arch |
+--------------------------------------------------+
| Driver Layer |
| CH390 / lwIP netif / UART DMA+IDLE / HAL |
+--------------------------------------------------+
四、FreeRTOS 任务设计
4.1 任务列表
| 任务名 | 优先级 | 栈大小 | 周期 | 职责 |
|---|---|---|---|---|
NetworkTask |
osPriorityHigh (4) | 512 words | 事件驱动 | CH390 事件消费 + lwIP 超时处理 |
UartTask |
osPriorityHigh (4) | 512 words | 事件驱动 | UART DMA/IDLE 接收 + MUX 帧提取 |
ConfigTask |
osPriorityNormal (3) | 256 words | 事件驱动 | AT 命令解析与响应 |
RouteTask |
osPriorityNormal (3) | 512 words | 事件驱动 | SRCID/DSTMASK 数据路由分发 |
DefaultTask |
osPriorityLow (1) | 128 words | 1000ms 周期 | LED 心跳 + IWDG 喂狗 |
4.2 任务间通信机制
UART ISR --[Semaphore]--> UartTask --[Queue]--> RouteTask --[Queue]--> NetworkTask
|
ConfigTask <--[Queue]-- RouteTask <--[Queue]-- NetworkTask <--------+
|
+--> UART TX (Direct DMA send)
具体通信对象:
| 对象 | 类型 | 生产者 | 消费者 | 用途 |
|---|---|---|---|---|
xUartRxQueue |
Queue (64 items) | UartTask | RouteTask | UART 接收帧传递 |
xTcpRxQueue |
Queue (32 items) | NetworkTask | RouteTask | TCP 接收数据传递 |
xConfigQueue |
Queue (16 items) | RouteTask | ConfigTask | AT 命令文本传递 |
xCh390Semaphore |
Binary Semaphore | EXTI0 ISR | NetworkTask | CH390 中断通知 |
xSpiMutex |
Mutex | NetworkTask | 多任务 | SPI/CH390 访问保护 |
xUart2TxStream |
StreamBuffer (1024) | RouteTask | UartTask | UART2 发送数据 |
xUart3TxStream |
StreamBuffer (1024) | RouteTask | UartTask | UART3 发送数据 |
4.3 NetworkTask 实现方向
void NetworkTask(void *argument)
{
/* 初始化 CH390 + lwIP netif */
/* 创建 TCP Server/Client 实例 */
for (;;) {
/* 等待 CH390 中断信号量 */
xSemaphoreTake(xCh390Semaphore, pdMS_TO_TICKS(10));
/* 处理 CH390 事件 */
ethernetif_poll();
ethernetif_check_link();
/* lwIP 超时处理由 tcpip_thread 自动完成 */
/* TCP 数据收发 */
tcp_link_process();
}
}
4.4 UartTask 实现方向
void UartTask(void *argument)
{
for (;;) {
/* 等待 UART IDLE 中断通知 */
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(10));
/* 处理 UART2/UART3 DMA 接收数据 */
/* MUX=0: 直接投递到路由队列 */
/* MUX=1: 提取 MUX 帧,分流控制帧与数据帧 */
/* 检查 StreamBuffer,发送 UART TX 数据 */
}
}
4.5 ConfigTask 实现方向
void ConfigTask(void *argument)
{
for (;;) {
/* 从配置队列接收 AT 命令文本 */
xQueueReceive(xConfigQueue, &cmd, portMAX_DELAY);
/* 解析并执行 AT 命令 */
config_process_at_cmd(cmd);
/* 通过 UART1 发送响应 */
}
}
4.6 RouteTask 实现方向
void RouteTask(void *argument)
{
for (;;) {
/* 从 UART 队列和 TCP 队列读取数据帧 */
/* 根据 SRCID/DSTMASK 决定路由目标 */
/* 控制帧 (DSTMASK=0x00) -> ConfigTask */
/* 数据帧 -> TCP 实例或 UART TX */
}
}
五、最终协议实现模型
5.1 MUX 帧承载层
数据口启用 MUX 后,统一处理如下帧:
SYNC | LEN_H | LEN_L | SRCID | DSTMASK | PAYLOAD | TAIL
实现职责:
- 识别帧边界
- 解析长度字段
- 提取
SRCID - 解析
DSTMASK - 按控制帧或数据帧分流
5.2 控制帧与数据帧分离
控制规则固定如下:
DSTMASK = 0x00:系统控制帧DSTMASK != 0x00:业务数据帧
系统控制帧处理要求:
PAYLOAD解释为 AT 文本- AT 文本必须以
\r\n结束 - 控制帧投递到
ConfigTask
业务数据帧处理要求:
SRCID表示单一源端点DSTMASK表示目标端点集合RouteTask根据DSTMASK做多目标分发
5.3 统一端点编码
内部与外部文档统一使用以下端点编码:
| 端点 | 编码 |
|---|---|
C1 |
0x01 |
C2 |
0x02 |
UART2 |
0x04 |
UART3 |
0x08 |
S1 |
0x10 |
S2 |
0x20 |
实现要求:
SRCID为单值DSTMASK为位图DSTMASK=0x00仅保留为控制帧
六、配置层设计
6.1 MUX 记录
MUX 为全局记录,仅控制设备数据口是否进入 MUX 承载模式。
取值:
0:普通透传1:MUX 透传
6.2 NET 记录
NET 为全局静态网络记录:
IP,MASK,GW,MAC
说明:
- 设备只有一张网卡,因此不为每个实例单独配置本地 IP
- 当前实现目标中不包含 DHCP
6.3 LINK 记录
LINK[idx] 为统一实例记录:
EN,LPORT,RIP,RPORT,UART
固定索引映射:
0 = S11 = S22 = C13 = C2
字段职责:
EN:实例启用状态LPORT:本地端口RIP / RPORT:对端地址与端口UART:对应业务数据口
说明:
Server与Client共享同一记录结构Server的RIP / RPORT可作为对端约束或预设Client的RIP / RPORT表示远端目标
七、模块职责
7.1 配置模块 config.c/.h
最终职责:
- 解析
AT+MUX - 解析
AT+NET - 解析
AT+LINK - 加载与保存配置
- 处理
SAVE / RESET / DEFAULT
7.2 UART 透传模块 uart_trans.c/.h
最终职责:
- 保持
USART2 / USART3的DMA + IDLE接收发送基线 - 在
MUX=0时执行普通透传 - 在
MUX=1时执行 MUX 帧收发 - 将控制帧与业务数据帧分流
7.3 TCP Server / Client 模块
最终职责:
- 不再从外部协议角度区分不同字段模型
- 统一受
LINK[idx]配置驱动 - 由调度层决定实例与 UART 的数据交换路径
7.4 FreeRTOS 初始化 freertos.c
CubeMX 生成的 FreeRTOS 初始化文件,职责:
- 定义默认任务
StartDefaultTask - 用户在
MX_FREERTOS_Init中创建自定义任务
7.5 FreeRTOS 配置 FreeRTOSConfig.h
关键配置项:
| 配置项 | 值 | 说明 |
|---|---|---|
configUSE_PREEMPTION |
1 | 抢占式调度 |
configTICK_RATE_HZ |
1000 | 1ms tick |
configMINIMAL_STACK_SIZE |
128 | 最小栈(words) |
configTOTAL_HEAP_SIZE |
10240 | FreeRTOS 堆大小 |
configMAX_PRIORITIES |
7 | 最大优先级数 |
configUSE_MUTEXES |
1 | 启用互斥锁 |
configUSE_COUNTING_SEMAPHORES |
1 | 启用计数信号量 |
configUSE_RECURSIVE_MUTEXES |
1 | 启用递归互斥锁 |
configCHECK_FOR_STACK_OVERFLOW |
2 | 栈溢出检测方式 2 |
configUSE_MALLOC_FAILED_HOOK |
1 | 内存分配失败钩子 |
configSUPPORT_DYNAMIC_ALLOCATION |
1 | 动态内存分配 |
八、lwIP 配置方向
8.1 lwIP 线程模型
由于采用 NO_SYS=0,lwIP 将运行以下线程:
tcpip_thread:lwIP 核心线程,处理所有协议栈内部事件- 应用任务通过
netconn/socketAPI 与 lwIP 交互
8.2 lwIP 内存配置建议
| 配置项 | 建议值 | 说明 |
|---|---|---|
MEM_SIZE |
8192 | lwIP 堆大小 |
MEMP_NUM_NETCONN |
6 | netconn 连接数 |
MEMP_NUM_TCP_PCB |
6 | TCP 控制块数 |
PBUF_POOL_SIZE |
8 | pbuf 池大小 |
PBUF_POOL_BUFSIZE |
1524 | pbuf 缓冲大小 |
TCP_WND |
2048 | TCP 窗口大小 |
TCP_MSS |
1460 | TCP 最大段大小 |
8.3 sys_arch 移植层
Drivers/LwIP/port/sys_arch.c 提供 lwIP 到 FreeRTOS 的适配:
sys_thread_new:创建 lwIP 线程sys_mbox_*:消息邮箱(基于 FreeRTOS Queue)sys_sem_*:信号量(基于 FreeRTOS Semaphore)sys_mutex_*:互斥锁(基于 FreeRTOS Mutex)sys_arch_protect / unprotect:临界区保护
九、中断与 HAL 时间基准
9.1 HAL 时间基准
FreeRTOS 下 SysTick 被 FreeRTOS 占用,HAL 时间基准改用 TIM4:
TIM4配置为 1ms 中断(72MHz / (71+1) / (999+1) = 1kHz)HAL_InitTick使用TIM4而非SysTickuwTick在TIM4_IRQHandler中递增
9.2 中断优先级规划
| 中断 | 优先级 | 说明 |
|---|---|---|
SysTick |
15(最低) | FreeRTOS tick |
PendSV |
15(最低) | FreeRTOS 上下文切换 |
SVCall |
0 | FreeRTOS 服务调用 |
TIM4 |
0 | HAL 时间基准 |
EXTI0 |
5 | CH390 中断 |
DMA1_Ch2~7 |
5 | UART DMA |
USART1/2/3 |
5 | UART 中断 |
SPI1 |
5 | SPI 中断 |
FreeRTOS 可管理的中断优先级必须 >= configMAX_SYSCALL_INTERRUPT_PRIORITY(本工程为 5)。
十、内存预算
以 STM32F103RCT6 为目标(48KB SRAM):
10.1 RAM 预算
| 项目 | 建议值 | 说明 |
|---|---|---|
| 启动栈 (MSP) | 2 KB | startup_stm32f103xe.s 中定义 |
| FreeRTOS 堆 | 10 KB | heap_4.c 管理 |
| 任务栈合计 | ~6 KB | 5 个任务 |
| lwIP 堆 | 8 KB | MEM_SIZE |
| UART 缓冲 | 4 KB | RX/TX DMA 缓冲 |
| Queue/StreamBuffer | 4 KB | 任务间通信 |
| 参数/状态 | 2 KB | 配置结构 |
| 空闲栈 | 1 KB | 系统预留 |
| 合计 | ~37 KB | 预留约 11 KB 余量 |
10.2 Flash 预算
| 项目 | 估计值 | 说明 |
|---|---|---|
| FreeRTOS 内核 | ~8 KB | 含 CMSIS-RTOS V2 |
| HAL 驱动 | ~20 KB | GPIO/UART/SPI/DMA/IWDG/TIM |
| lwIP 协议栈 | ~40 KB | core + api + ipv4 + netif |
| CH390 驱动 | ~4 KB | |
| 应用代码 | ~20 KB | config/uart_trans/tcp/route |
| 合计 | ~92 KB | 预留约 164 KB 余量 |
十一、硬件资源
11.1 MCU
- 型号:
STM32F103RCT6 - Flash:
256 KB - SRAM:
48 KB - 主频:
72 MHz
11.2 主要外设
SPI1:连接CH390DUSART1:配置串口USART2:数据透传串口USART3:数据透传串口DMA1:3 路 UART 收发 DMAEXTI0:CH390 中断输入IWDG:独立看门狗TIM4:HAL 时间基准(替代 SysTick)
11.3 引脚分配
| 引脚 | 功能 | 用途 |
|---|---|---|
| PA2 | USART2_TX | 数据透传串口 |
| PA3 | USART2_RX | 数据透传串口 |
| PA4 | SPI1_NSS | 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 | 数据透传串口 |
| PB11 | USART3_RX | 数据透传串口 |
| PC13 | GPIO_Output | 状态 LED |
| PD0/PD1 | HSE | 8MHz 外部晶振 |
十二、实现边界
- 保持单网卡静态网络模型
- 不实现 DHCP
- 不实现旧
S1... / C1...外部协议字段 - 不在文档中保留兼容层描述
- 所有 AT 文本控制统一要求
\r\n结束 - FreeRTOS 堆管理使用
heap_4.c - HAL 时间基准使用
TIM4而非SysTick
十三、文档一致性要求
后续实现、联调、测试与代码注释必须遵守以下统一口径:
- 对外协议只使用
MUX / NET / LINK - 控制帧只使用
DSTMASK=0x00 - MUX 帧格式固定为
SYNC | LEN_H | LEN_L | SRCID | DSTMASK | PAYLOAD | TAIL - AT 手册、需求说明、技术实现三份文档不得再出现历史展开式字段