refactor: 适配STM32F103RCT6 + FreeRTOS工程框架,同步baremetal-r8协议手册

- 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专项)
This commit is contained in:
2026-04-09 20:22:48 +08:00
parent 68c64959c7
commit c21d85a9da
10 changed files with 1322 additions and 430 deletions
+419 -341
View File
@@ -1,42 +1,425 @@
# TCP2UART 项目技术实现(裸机迁移基线)
# TCP2UART 项目技术实现
## 一、目标
## 一、文档目的
当前分支 `baremetal-r8` 的目标不是一次性完成全部业务逻辑重写,而是先把工程基线切换到适合 `STM32F103R8T6` 的裸机方向,为后续继续开发提供统一入口
本文档描述 `TCP2UART` 项目基于 `STM32F103RCT6 + FreeRTOS` 的最终内部实现口径
阶段已经完成或约束如下
文档只围绕最终协议模型展开
1. MCU 目标统一为 `STM32F103R8T6 / STM32F103xB`
2. `CubeMX IOC` 中已移除 `FreeRTOS` 中间件声明
3. 工程规划转为裸机轮询 + 中断驱动模型
4. 暂不在本阶段重写 TCP/串口业务逻辑
5. 保留现有源码作为迁移参考,后续由其他 Agent/开发者继续接力实现
- `MUX`:串口承载层
- `NET`:全局网络配置层
- `LINK[idx]`:实例配置与连接管理层
## 二、硬件与资源约束
不再保留历史 `S1... / C1...` 外部字段模型。
### 2.1 MCU
## 二、当前工程基础
- 型号:`STM32F103R8T6`
- Flash`64 KB`
- SRAM`20 KB`
当前工程基础约束如下:
1. MCU`STM32F103RCT6`256KB Flash / 48KB SRAM
2. 网络芯片:`CH390D`
3. 软件架构:`FreeRTOS + lwIP NO_SYS=0`
4. 协议栈:`lwIP socket/netconn API`
5. 调试输出:`SEGGER RTT`
6. 使用 `FreeRTOS` 任务调度
7. 不实现 DHCP
## 三、总体架构
```text
+--------------------------------------------------+
| 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 任务间通信机制
```text
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 实现方向
```c
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 实现方向
```c
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 实现方向
```c
void ConfigTask(void *argument)
{
for (;;) {
/* 从配置队列接收 AT 命令文本 */
xQueueReceive(xConfigQueue, &cmd, portMAX_DELAY);
/* 解析并执行 AT 命令 */
config_process_at_cmd(cmd);
/* 通过 UART1 发送响应 */
}
}
```
### 4.6 RouteTask 实现方向
```c
void RouteTask(void *argument)
{
for (;;) {
/* 从 UART 队列和 TCP 队列读取数据帧 */
/* 根据 SRCID/DSTMASK 决定路由目标 */
/* 控制帧 (DSTMASK=0x00) -> ConfigTask */
/* 数据帧 -> TCP 实例或 UART TX */
}
}
```
## 五、最终协议实现模型
### 5.1 MUX 帧承载层
数据口启用 MUX 后,统一处理如下帧:
```text
SYNC | LEN_H | LEN_L | SRCID | DSTMASK | PAYLOAD | TAIL
```
实现职责:
1. 识别帧边界
2. 解析长度字段
3. 提取 `SRCID`
4. 解析 `DSTMASK`
5. 按控制帧或数据帧分流
### 5.2 控制帧与数据帧分离
控制规则固定如下:
- `DSTMASK = 0x00`:系统控制帧
- `DSTMASK != 0x00`:业务数据帧
系统控制帧处理要求:
1. `PAYLOAD` 解释为 AT 文本
2. AT 文本必须以 `\r\n` 结束
3. 控制帧投递到 `ConfigTask`
业务数据帧处理要求:
1. `SRCID` 表示单一源端点
2. `DSTMASK` 表示目标端点集合
3. `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` 为全局静态网络记录:
```text
IP,MASK,GW,MAC
```
说明:
- 设备只有一张网卡,因此不为每个实例单独配置本地 IP
- 当前实现目标中不包含 DHCP
### 6.3 LINK 记录
`LINK[idx]` 为统一实例记录:
```text
EN,LPORT,RIP,RPORT,UART
```
固定索引映射:
- `0 = S1`
- `1 = S2`
- `2 = C1`
- `3 = C2`
字段职责:
- `EN`:实例启用状态
- `LPORT`:本地端口
- `RIP / RPORT`:对端地址与端口
- `UART`:对应业务数据口
说明:
- `Server``Client` 共享同一记录结构
- `Server``RIP / RPORT` 可作为对端约束或预设
- `Client``RIP / RPORT` 表示远端目标
## 七、模块职责
### 7.1 配置模块 `config.c/.h`
最终职责:
1. 解析 `AT+MUX`
2. 解析 `AT+NET`
3. 解析 `AT+LINK`
4. 加载与保存配置
5. 处理 `SAVE / RESET / DEFAULT`
### 7.2 UART 透传模块 `uart_trans.c/.h`
最终职责:
1. 保持 `USART2 / USART3``DMA + IDLE` 接收发送基线
2.`MUX=0` 时执行普通透传
3.`MUX=1` 时执行 MUX 帧收发
4. 将控制帧与业务数据帧分流
### 7.3 TCP Server / Client 模块
最终职责:
1. 不再从外部协议角度区分不同字段模型
2. 统一受 `LINK[idx]` 配置驱动
3. 由调度层决定实例与 UART 的数据交换路径
### 7.4 FreeRTOS 初始化 `freertos.c`
CubeMX 生成的 FreeRTOS 初始化文件,职责:
1. 定义默认任务 `StartDefaultTask`
2. 用户在 `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 将运行以下线程:
1. `tcpip_thread`:lwIP 核心线程,处理所有协议栈内部事件
2. 应用任务通过 `netconn` / `socket` API 与 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 的适配:
1. `sys_thread_new`:创建 lwIP 线程
2. `sys_mbox_*`:消息邮箱(基于 FreeRTOS Queue
3. `sys_sem_*`:信号量(基于 FreeRTOS Semaphore
4. `sys_mutex_*`:互斥锁(基于 FreeRTOS Mutex
5. `sys_arch_protect / unprotect`:临界区保护
## 九、中断与 HAL 时间基准
### 9.1 HAL 时间基准
FreeRTOS 下 `SysTick` 被 FreeRTOS 占用,HAL 时间基准改用 `TIM4`
- `TIM4` 配置为 1ms 中断(72MHz / (71+1) / (999+1) = 1kHz
- `HAL_InitTick` 使用 `TIM4` 而非 `SysTick`
- `uwTick``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`
### 2.2 主要外设
### 11.2 主要外设
- `SPI1`:连接 `CH390D`
- `USART1`:配置串口
- `USART2`Server 透传串口
- `USART3`Client 透传串口
- `USART2`数据透传串口
- `USART3`数据透传串口
- `DMA1`3 路 UART 收发 DMA
- `EXTI0`CH390 中断输入
- `IWDG`:独立看门狗
- `TIM4`HAL 时间基准(替代 SysTick
### 2.3 当前引脚分配
### 11.3 引脚分配
| 引脚 | 功能 | 用途 |
|------|------|------|
| PA2 | USART2_TX | Server 透传串口 |
| PA3 | USART2_RX | Server 透传串口 |
| PA2 | USART2_TX | 数据透传串口 |
| PA3 | USART2_RX | 数据透传串口 |
| PA4 | SPI1_NSS | CH390D 片选 |
| PA5 | SPI1_SCK | CH390D SPI 时钟 |
| PA6 | SPI1_MISO | CH390D SPI 数据输入 |
@@ -45,331 +428,26 @@
| PA10 | USART1_RX | 配置串口 |
| PB0 | EXTI0 | CH390D INT |
| PB1 | GPIO_Output | CH390D RESET |
| PB10 | USART3_TX | Client 透传串口 |
| PB11 | USART3_RX | Client 透传串口 |
| PB10 | USART3_TX | 数据透传串口 |
| PB11 | USART3_RX | 数据透传串口 |
| PC13 | GPIO_Output | 状态 LED |
| PD0/PD1 | HSE | 8MHz 外部晶振 |
## 三、为何从 FreeRTOS 迁移到裸机
## 十二、实现边界
`STM32F103R8T6` 的 RAM 只有 `20KB`。当前工程在引入如下组件后,链接空间明显不足:
1. 保持单网卡静态网络模型
2. 不实现 DHCP
3. 不实现旧 `S1... / C1...` 外部协议字段
4. 不在文档中保留兼容层描述
5. 所有 AT 文本控制统一要求 `\r\n` 结束
6. FreeRTOS 堆管理使用 `heap_4.c`
7. HAL 时间基准使用 `TIM4` 而非 `SysTick`
1. `FreeRTOS` 内核
2. `CMSIS-RTOS V2` 包装层
3. 多任务栈
4. `lwIP + socket/netconn` OS 抽象层
5. 多路 `StreamBuffer / Semaphore / Mutex`
## 十三、文档一致性要求
此前编译已经证明
后续实现、联调、测试与代码注释必须遵守以下统一口径
1. 源码层报错可修复
2. 统一 `R8` 型号后仍然在链接阶段失败
3. 主要瓶颈是 `RAM + Flash` 同时偏紧
因此本项目后续建议的主方向为:
1. 去掉 `FreeRTOS`
2. 去掉 `CMSIS-RTOS V2`
3. 避免依赖 `lwIP socket/netconn`
4. 采用裸机主循环 + DMA/IDLE/EXTI 中断驱动
5. 网络侧改为更贴近资源受限场景的实现模型
## 四、裸机架构目标
### 4.1 总体分层
```text
+--------------------------------------------------+
| Application State Machine |
| config / server link / client link / watchdog |
+--------------------------------------------------+
| Transport Scheduler |
| main loop polling + event flags + timeout scan |
+--------------------------------------------------+
| Network Interface |
| CH390 event polling / packet rx-tx dispatch |
+--------------------------------------------------+
| Peripheral Drivers |
| UART DMA+IDLE / SPI / GPIO / EXTI / Flash |
+--------------------------------------------------+
| STM32 HAL / CMSIS |
+--------------------------------------------------+
```
### 4.2 执行模型
不再使用任务调度器,改为以下模型:
1. `ISR` 只做最小事件置位与 DMA 状态更新
2. 主循环统一处理事件、超时、状态机推进
3. UART RX 继续依赖 `DMA + IDLE`
4. UART TX 可保留 `DMA`
5. CH390 中断只置位 `netif_pending`
6. 网络协议处理在主循环中推进
### 4.3 事件源
建议保留以下裸机事件位:
```c
typedef enum {
EVENT_NONE = 0x00000000u,
EVENT_CH390_INT = 0x00000001u,
EVENT_UART1_RX_IDLE = 0x00000002u,
EVENT_UART2_RX_IDLE = 0x00000004u,
EVENT_UART3_RX_IDLE = 0x00000008u,
EVENT_UART2_TX_DONE = 0x00000010u,
EVENT_UART3_TX_DONE = 0x00000020u,
EVENT_NET_TIMER_1MS = 0x00000040u,
EVENT_LINK_RETRY = 0x00000080u,
EVENT_CONFIG_PENDING = 0x00000100u,
} app_event_t;
```
这些事件位建议通过 `volatile uint32_t g_app_events` 或一个轻量原子位图维护。
## 五、建议的软件模块拆分
### 5.1 保留模块
以下模块可继续保留,但需要去除 RTOS 依赖:
1. `App/config.c`
2. `App/flash_param.c`
3. `App/tcp_server.*`
4. `App/tcp_client.*`
5. `App/uart_trans.*`
6. `Drivers/CH390/*`
7. `Drivers/LwIP/*` 或后续替代网络栈
### 5.2 需要改造的核心模块
1. `Core/Src/main.c`
2. `Core/Src/stm32f1xx_it.c`
3. `Core/Src/usart.c`
4. `Core/Src/dma.c`
5. `Core/Src/freertos.c`:后续应移除出构建或清空为兼容壳
6. `Core/Inc/FreeRTOSConfig.h`:后续可移除出工程
7. `Drivers/LwIP/port/sys_arch.c`:若完全去 OS,应停止使用该移植层
8. `Drivers/LwIP/src/include/arch/sys_arch.h`
### 5.3 建议新增的裸机模块
建议后续新增:
1. `App/app_scheduler.c/.h`
- 统一处理事件位
- 驱动周期任务
- 执行状态机推进
2. `App/app_net.c/.h`
- 网络初始化
- CH390 事件分发
- 链路保活/重连
3. `App/app_uart.c/.h`
- UART DMA/IDLE 收发整合
- 与网络方向的缓冲协调
4. `App/app_time.c/.h`
- 基于 `SysTick` 的毫秒计时
- 软件超时管理
## 六、裸机下的关键技术决策
### 6.1 延时与时间基准
建议统一使用:
1. `SysTick 1ms` 全局时基
2. 禁止在主业务路径使用长阻塞 `HAL_Delay`
3. 超时逻辑统一基于 `tick_now - tick_start`
示例:
```c
uint32_t app_now_ms(void);
bool app_is_timeout(uint32_t start, uint32_t timeout_ms);
```
### 6.2 UART 接收模型
保持 `DMA + IDLE` 是合理的,原因:
1. 可降低 CPU 占用
2. 适合串口透传场景
3. 便于在裸机下维持较高吞吐
建议 UART RX 流程:
1. DMA 持续接收至环形或双缓冲
2. IDLE 中断触发“本帧结束”
3. ISR 只记录长度与事件位
4. 主循环消费数据并决定转发方向
### 6.3 UART 发送模型
建议继续使用 `DMA TX`
1. 发送启动在主循环中执行
2. DMA 完成中断只清 busy 标志并置 `TX_DONE` 事件
3. 发送缓冲统一由应用层管理
### 6.4 CH390 访问模型
裸机下不再需要 `mutex`,但仍需保证上下文一致性:
1. ISR 内不要执行复杂 SPI 事务
2. EXTI 仅置位 `EVENT_CH390_INT`
3. 所有 CH390 SPI 读写都在主循环中完成
4. 若必须与 DMA 回调共享状态,使用短临界区保护
### 6.5 网络栈路线
这里需要后续 Agent 决定最终实现路线,建议二选一:
1. `lwIP RAW API + NO_SYS=1`
- 优点:仍保留成熟 TCP/IP 栈
- 缺点:迁移复杂度较高,需要重写当前 `socket/netconn` 依赖
2. 基于现有 CH390 资料,评估是否存在更轻的直接 socket/简化协议接口
- 优点:可能进一步减小资源占用
- 缺点:功能边界和维护成本需重新评估
当前更推荐的长期路线是:
`lwIP RAW API + NO_SYS=1`
因为这条路线与现有 CH390 + 以太网驱动结构更连续。
## 七、主循环设计建议
建议采用固定骨架:
```c
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_IWDG_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
MX_SPI1_Init();
app_time_init();
app_uart_init();
app_net_init();
app_config_init();
while (1)
{
app_poll_events();
app_process_config();
app_process_uart_links();
app_process_network();
app_process_timeouts();
app_feed_watchdog();
}
}
```
设计原则:
1. 所有步骤可重入或幂等
2. 每轮主循环不可长时间阻塞
3. 网络与串口处理都要支持“分段推进”
## 八、建议的状态机拆分
### 8.1 TCP Server 链路
```text
IDLE -> LISTEN -> CONNECTED -> CLOSING -> LISTEN
```
### 8.2 TCP Client 链路
```text
IDLE -> RESOLVE/CONFIG -> CONNECTING -> CONNECTED -> RETRY_WAIT -> CONNECTING
```
### 8.3 配置口
```text
IDLE -> RX_FRAME_READY -> PARSE -> EXECUTE -> RESPOND -> IDLE
```
### 8.4 CH390 网口
```text
RESET -> INIT -> LINK_CHECK -> RUNNING -> ERROR_RECOVER -> INIT
```
## 九、内存预算建议
`STM32F103R8T6` 为目标,后续实现应尽量遵循:
### 9.1 推荐 RAM 预算
| 项目 | 建议值 | 说明 |
|------|--------|------|
| 启动栈 | 1 KB | `startup` 保留 |
| C Heap | 0 | 默认关闭 |
| UART1 RX/TX | 384 B | 配置口 |
| UART2 RX/TX | 1 KB | 透传链路 |
| UART3 RX/TX | 1 KB | 透传链路 |
| 网络收发缓存 | 2-4 KB | 视协议栈路线而定 |
| 参数/状态结构 | < 2 KB | 控制状态 |
### 9.2 原则
1. 避免动态分配
2. 优先静态缓冲 + 明确大小
3. 单向链路缓冲优先复用
4. 所有大缓冲区要在文档中登记
## 十、当前已完成的工程侧修改
本分支当前已经完成:
1. `R8/xB` 型号统一
2. MDK 启动文件切换到 `startup_stm32f103xb.s`
3. `IOC` 中移除 `FREERTOS` 中间件声明
4. `PendSV/SVCall` 不再作为 RTOS 中断入口保留
5. `Heap/Stack` 的工程默认值收缩到更适合 `R8`
## 十一、后续 Agent 接手时应优先处理的事项
### 11.1 工程配置层
1.`MDK-ARM/TCP2UART.uvprojx` 中移除 `FreeRTOS` 源文件组
2. 从包含路径中移除 `CMSIS_RTOS_V2``FreeRTOS` 路径
3. 视需要移除 `Core/Src/freertos.c`
4. 视需要移除 `Core/Inc/FreeRTOSConfig.h`
### 11.2 代码层
1. 将所有 `osThreadNew``vTaskDelay``xStreamBuffer*``xSemaphore*``xMutex*` 调用替换为裸机实现
2.`lwIP``NO_SYS=0` 路线迁移到裸机可用路线
3. 重写 `CH390` 事件处理为主循环驱动
4. 重写 UART 透传调度逻辑为状态机
### 11.3 风险点
1. 当前 `socket/netconn` 方案不能直接脱离 OS 使用
2. `sys_arch` 相关移植层最终应被清退
3. 原来依赖任务切换“自然解耦”的路径,迁移到裸机后必须明确状态和时序边界
## 十二、交接说明
当前分支适合作为“裸机迁移起点”,但不是最终可编译成品。它的价值在于:
1. 目标器件与工程元数据已经统一
2. `CubeMX` 方向已经从 `FreeRTOS` 转向裸机
3. 技术实现文档已明确后续重构路线
接下来的工作重点应由后续 Agent 在此基线上继续完成逻辑代码迁移。
1. 对外协议只使用 `MUX / NET / LINK`
2. 控制帧只使用 `DSTMASK=0x00`
3. MUX 帧格式固定为 `SYNC | LEN_H | LEN_L | SRCID | DSTMASK | PAYLOAD | TAIL`
4. AT 手册、需求说明、技术实现三份文档不得再出现历史展开式字段