refactor: 确定路径A架构(NO_SYS=0+netconn+多TCP任务),精确化任务设计与内存预算
- FreeRTOSConfig.h: 堆8->10KB, 优先级56->7, 添加lwIP sys_arch宏和任务优先级/栈大小定义 - lwipopts.h: LWIP_SOCKET=0节省RAM, LWIP_TCPIP_CORE_LOCKING=1, MEM_SIZE 8KB, PBUF_POOL 10, MEMP_NUM_NETCONN 8, TCP_SND_BUF/WND 8xMSS, 关闭DHCP/UDP, TCPIP_THREAD_STACKSIZE/PRIO明确指定 - 项目技术实现: 9+1任务架构, netconn阻塞模式每连接独立任务, 零拷贝route_msg_t, 内存精确估算49KB(RCT6超1KB需优化或换RDT6), 模块重写/复用清单 - 项目需求说明: 明确netconn API路线, 添加RDT6备选, 更新任务列表9个任务
This commit is contained in:
@@ -48,105 +48,183 @@
|
||||
+--------------------------------------------------+
|
||||
```
|
||||
|
||||
## 四、FreeRTOS 任务设计
|
||||
## 四、FreeRTOS 任务设计(路径 A:netconn + 多 TCP 任务)
|
||||
|
||||
### 4.1 任务列表
|
||||
### 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 喂狗 |
|
||||
本项目采用 **路径 A**:`NO_SYS=0 + netconn API + 每个 TCP 连接独立任务`。
|
||||
|
||||
### 4.2 任务间通信机制
|
||||
核心决策:
|
||||
1. lwIP 以 `NO_SYS=0` 模式运行,`tcpip_thread` 由 lwIP 自动创建
|
||||
2. TCP 连接使用 `netconn` 阻塞 API(`netconn_accept` / `netconn_recv` / `netconn_write`)
|
||||
3. 每个 TCP Server 和 Client 实例各占一个独立任务
|
||||
4. 任务间通过 Queue 传递指针 + 元数据描述符,实现零拷贝
|
||||
|
||||
```text
|
||||
UART ISR --[Semaphore]--> UartTask --[Queue]--> RouteTask --[Queue]--> NetworkTask
|
||||
|
|
||||
ConfigTask <--[Queue]-- RouteTask <--[Queue]-- NetworkTask <--------+
|
||||
|
|
||||
+--> UART TX (Direct DMA send)
|
||||
### 4.2 任务列表(共 9 个任务 + 1 个 lwIP 自建)
|
||||
|
||||
| 任务名 | 优先级 | 栈(words) | 模式 | 职责 |
|
||||
|--------|--------|-----------|------|------|
|
||||
| `tcpip_thread` | 6 (最高) | 512 | 阻塞 | lwIP 内核线程(自动创建) |
|
||||
| `NetPollTask` | 5 | 384 | 事件驱动 | `ethernetif_poll` + 链路检测 |
|
||||
| `TcpSrvTask_S1` | 4 | 384 | 阻塞 | `netconn_accept` + S1 收发 |
|
||||
| `TcpSrvTask_S2` | 4 | 384 | 阻塞 | `netconn_accept` + S2 收发 |
|
||||
| `TcpCliTask_C1` | 4 | 256 | 阻塞 | `netconn_connect` + C1 收发 |
|
||||
| `TcpCliTask_C2` | 4 | 256 | 阻塞 | `netconn_connect` + C2 收发 |
|
||||
| `UartRxTask` | 4 | 384 | 事件驱动 | UART DMA/IDLE 接收 + MUX 帧提取 |
|
||||
| `ConfigTask` | 2 | 256 | 阻塞 | AT 命令解析与响应 |
|
||||
| `DefaultTask` | 1 | 128 | 周期 | LED 心跳 + IWDG 喂狗 |
|
||||
|
||||
说明:
|
||||
- `tcpip_thread` 是 lwIP 自建的内核线程,处理所有协议栈内部事件
|
||||
- 所有 `netconn_*` API 通过 `tcpip_thread` 消息机制实现线程安全
|
||||
- `LWIP_TCPIP_CORE_LOCKING=1` 允许应用任务直接调用 `netconn_write` 而不经邮箱中转
|
||||
- `tcpip_thread` 优先级最高(6),确保 TCP ACK 和超时处理不被延迟
|
||||
|
||||
### 4.3 零拷贝路由消息设计
|
||||
|
||||
```c
|
||||
/* 路由消息描述符 - Queue 传递的是此结构的指针,不拷贝负载数据 */
|
||||
typedef struct {
|
||||
uint8_t src_id; /* 源端点 ID */
|
||||
uint8_t dst_mask; /* 目标端点位图 */
|
||||
uint16_t len; /* 数据长度 */
|
||||
uint8_t conn_type; /* 连接标识:LINK_S1/S2/C1/C2 */
|
||||
uint8_t *data; /* 指向预分配静态缓冲区 */
|
||||
} route_msg_t;
|
||||
```
|
||||
|
||||
具体通信对象:
|
||||
静态缓冲池(预分配,避免动态分配):
|
||||
|
||||
```c
|
||||
#define ROUTE_BUF_COUNT 4
|
||||
#define ROUTE_BUF_SIZE 512
|
||||
|
||||
static uint8_t g_route_buf_pool[ROUTE_BUF_COUNT][ROUTE_BUF_SIZE];
|
||||
static volatile uint8_t g_route_buf_used[ROUTE_BUF_COUNT];
|
||||
```
|
||||
|
||||
- 发送方:从池中获取空闲缓冲区,拷贝数据,填充 `route_msg_t`,Queue 发送指针
|
||||
- 接收方:从 Queue 取 `route_msg_t*`,处理数据后标记缓冲区为可用
|
||||
- 无动态分配,无堆碎片
|
||||
|
||||
### 4.4 任务间通信机制
|
||||
|
||||
```text
|
||||
UART ISR ──[TaskNotify]──> UartRxTask ──[Queue*]──> TcpSrvTask / TcpCliTask
|
||||
│ ▲
|
||||
├──[Queue*]──────────────>─┘
|
||||
│
|
||||
DSTMASK=0 └──[Queue]──> ConfigTask
|
||||
|
||||
TcpSrvTask / TcpCliTask ──[Queue*]──> UartRxTask (UART TX 方向)
|
||||
|
||||
EXTI0 ISR ──[BinarySem]──> NetPollTask ──> ethernetif_poll ──> tcpip_thread
|
||||
```
|
||||
|
||||
通信对象:
|
||||
|
||||
| 对象 | 类型 | 生产者 | 消费者 | 用途 |
|
||||
|------|------|--------|--------|------|
|
||||
| `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 发送数据 |
|
||||
| `xNetSemaphore` | Binary Semaphore | EXTI0 ISR | NetPollTask | CH390 中断通知 |
|
||||
| `xUartRxNotify` | TaskNotification | UART IDLE ISR | UartRxTask | UART 接收通知 |
|
||||
| `xTcpRxQueue` | Queue (16, route_msg_t*) | TCP 任务 | UartRxTask | TCP→UART 数据 |
|
||||
| `xUartTxQueue` | Queue (8, route_msg_t*) | UartRxTask | TCP 任务 | UART→TCP 数据 |
|
||||
| `xConfigQueue` | Queue (8, char*) | UartRxTask | ConfigTask | AT 文本 |
|
||||
|
||||
### 4.3 NetworkTask 实现方向
|
||||
说明:
|
||||
- TCP→UART 方向:TCP 任务调用 `netconn_recv` 获取数据,构造 `route_msg_t` 指针投递到 `xTcpRxQueue`,UartRxTask 取出后写入 UART DMA
|
||||
- UART→TCP 方向:UartRxTask 从 UART DMA 读取数据,构造 `route_msg_t` 指针投递到 `xUartTxQueue`,对应 TCP 任务取出后调用 `netconn_write` 发送
|
||||
- 路由逻辑内联在 UartRxTask 和各 TCP 任务中,不设独立 RouteTask
|
||||
|
||||
### 4.5 NetPollTask 实现
|
||||
|
||||
```c
|
||||
void NetworkTask(void *argument)
|
||||
void NetPollTask(void *argument)
|
||||
{
|
||||
/* 初始化 CH390 + lwIP netif */
|
||||
/* 创建 TCP Server/Client 实例 */
|
||||
ethernetif_init(&ch390_netif);
|
||||
/* 等待链路就绪后启动 TCP 任务 */
|
||||
/* ... */
|
||||
|
||||
for (;;) {
|
||||
/* 等待 CH390 中断信号量 */
|
||||
xSemaphoreTake(xCh390Semaphore, pdMS_TO_TICKS(10));
|
||||
/* 处理 CH390 事件 */
|
||||
ethernetif_poll();
|
||||
ethernetif_check_link();
|
||||
/* lwIP 超时处理由 tcpip_thread 自动完成 */
|
||||
/* TCP 数据收发 */
|
||||
tcp_link_process();
|
||||
xSemaphoreTake(xNetSemaphore, pdMS_TO_TICKS(2));
|
||||
ethernetif_poll(&ch390_netif);
|
||||
ethernetif_check_link(&ch390_netif);
|
||||
/* sys_check_timeouts() 由 tcpip_thread 自动执行,此处不需要调用 */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 UartTask 实现方向
|
||||
### 4.6 TcpSrvTask 实现模板
|
||||
|
||||
```c
|
||||
void UartTask(void *argument)
|
||||
void TcpSrvTask_S1(void *argument)
|
||||
{
|
||||
struct netconn *conn = netconn_new(NETCONN_TCP);
|
||||
netconn_bind(conn, IP_ADDR_ANY, cfg->links[0].lport);
|
||||
netconn_listen(conn);
|
||||
|
||||
for (;;) {
|
||||
/* 等待 UART IDLE 中断通知 */
|
||||
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(10));
|
||||
/* 处理 UART2/UART3 DMA 接收数据 */
|
||||
/* MUX=0: 直接投递到路由队列 */
|
||||
/* MUX=1: 提取 MUX 帧,分流控制帧与数据帧 */
|
||||
/* 检查 StreamBuffer,发送 UART TX 数据 */
|
||||
struct netconn *newconn;
|
||||
if (netconn_accept(conn, &newconn) == ERR_OK) {
|
||||
/* 在本任务内处理唯一客户端 */
|
||||
tcp_server_worker(newconn, LINK_S1);
|
||||
netconn_close(newconn);
|
||||
netconn_delete(newconn);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.5 ConfigTask 实现方向
|
||||
### 4.7 TcpCliTask 实现模板
|
||||
|
||||
```c
|
||||
void TcpCliTask_C1(void *argument)
|
||||
{
|
||||
for (;;) {
|
||||
struct netconn *conn = netconn_new(NETCONN_TCP);
|
||||
ip_addr_t remote_ip;
|
||||
IP_ADDR4(&remote_ip, cfg->links[2].rip[0], ...);
|
||||
|
||||
if (netconn_connect(conn, &remote_ip, cfg->links[2].rport) == ERR_OK) {
|
||||
tcp_client_worker(conn, LINK_C1);
|
||||
}
|
||||
netconn_close(conn);
|
||||
netconn_delete(conn);
|
||||
vTaskDelay(pdMS_TO_TICKS(cfg->links[2].reconnect_interval));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.8 UartRxTask 实现
|
||||
|
||||
```c
|
||||
void UartRxTask(void *argument)
|
||||
{
|
||||
for (;;) {
|
||||
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(10));
|
||||
/* 处理 UART2/UART3 DMA 接收数据 */
|
||||
/* MUX=0: 构造 route_msg_t 指针投递到 xUartTxQueue */
|
||||
/* MUX=1: 提取 MUX 帧,DSTMASK=0 投 xConfigQueue,否则投 xUartTxQueue */
|
||||
/* 从 xTcpRxQueue 取数据,写入 UART DMA 发送 */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.9 ConfigTask 实现
|
||||
|
||||
```c
|
||||
void ConfigTask(void *argument)
|
||||
{
|
||||
for (;;) {
|
||||
/* 从配置队列接收 AT 命令文本 */
|
||||
char *cmd;
|
||||
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 帧承载层
|
||||
@@ -276,13 +354,16 @@ EN,LPORT,RIP,RPORT,UART
|
||||
3. 在 `MUX=1` 时执行 MUX 帧收发
|
||||
4. 将控制帧与业务数据帧分流
|
||||
|
||||
### 7.3 TCP Server / Client 模块
|
||||
### 7.3 TCP Server / Client 模块(需重写)
|
||||
|
||||
最终职责:
|
||||
原 `tcp_server.c` / `tcp_client.c` 基于 lwIP RAW API 回调模式,需重写为 netconn 阻塞模式:
|
||||
|
||||
1. 不再从外部协议角度区分不同字段模型
|
||||
2. 统一受 `LINK[idx]` 配置驱动
|
||||
3. 由调度层决定实例与 UART 的数据交换路径
|
||||
1. 删除所有 `tcp_pcb` / `tcp_recv` / `tcp_accept` 回调代码
|
||||
2. 改用 `netconn_new` / `netconn_bind` / `netconn_listen` / `netconn_accept`(Server)
|
||||
3. 改用 `netconn_new` / `netconn_connect`(Client)
|
||||
4. 收发改为 `netconn_recv` / `netconn_write` 阻塞调用
|
||||
5. 内部 ring buffer 可取消(netconn 内部已有 pbuf 缓冲)
|
||||
6. 每个 TCP 任务内直接处理路由,通过 Queue 指针传递数据
|
||||
|
||||
### 7.4 FreeRTOS 初始化 `freertos.c`
|
||||
|
||||
@@ -309,36 +390,67 @@ CubeMX 生成的 FreeRTOS 初始化文件,职责:
|
||||
| `configUSE_MALLOC_FAILED_HOOK` | 1 | 内存分配失败钩子 |
|
||||
| `configSUPPORT_DYNAMIC_ALLOCATION` | 1 | 动态内存分配 |
|
||||
|
||||
## 八、lwIP 配置方向
|
||||
## 八、lwIP 配置(NO_SYS=0 + netconn)
|
||||
|
||||
### 8.1 lwIP 线程模型
|
||||
|
||||
由于采用 `NO_SYS=0`,lwIP 将运行以下线程:
|
||||
|
||||
1. `tcpip_thread`:lwIP 核心线程,处理所有协议栈内部事件
|
||||
2. 应用任务通过 `netconn` / `socket` API 与 lwIP 交互
|
||||
1. `tcpip_thread`(优先级 6,栈 512 words):lwIP 核心线程,处理所有协议栈内部事件
|
||||
2. 应用任务通过 `netconn` API 与 lwIP 交互,由 `tcpip_thread` 消息机制保证线程安全
|
||||
3. `LWIP_TCPIP_CORE_LOCKING=1`:允许应用任务在持有核心锁时直接调用 `netconn_write`,无需通过邮箱中转
|
||||
|
||||
### 8.2 lwIP 内存配置建议
|
||||
### 8.2 lwIP 关键配置项(lwipopts.h)
|
||||
|
||||
| 配置项 | 建议值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| 配置项 | 值 | 说明 |
|
||||
|--------|-----|------|
|
||||
| `NO_SYS` | 0 | 启用 OS 抽象 |
|
||||
| `LWIP_NETCONN` | 1 | 启用 netconn API |
|
||||
| `LWIP_SOCKET` | 0 | 不使用 socket API,节省 RAM |
|
||||
| `LWIP_TCPIP_CORE_LOCKING` | 1 | 允许直接发送,减少延时 |
|
||||
| `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 最大段大小 |
|
||||
| `PBUF_POOL_SIZE` | 10 | pbuf 池数量 |
|
||||
| `MEMP_NUM_NETCONN` | 8 | 2监听 + 4连接 + 2余量 |
|
||||
| `MEMP_NUM_NETBUF` | 8 | netconn 缓冲 |
|
||||
| `MEMP_NUM_TCP_PCB` | 4 | TCP 控制块 |
|
||||
| `MEMP_NUM_TCP_PCB_LISTEN` | 2 | TCP 监听 |
|
||||
| `MEMP_NUM_TCP_SEG` | 24 | TCP 段 |
|
||||
| `MEMP_NUM_TCPIP_MSG_API` | 8 | API 消息池 |
|
||||
| `MEMP_NUM_TCPIP_MSG_INPKT` | 8 | 入包消息池 |
|
||||
| `TCP_MSS` | 536 | 保守 MSS |
|
||||
| `TCP_SND_BUF` | 8×MSS=4288 | 发送缓冲 |
|
||||
| `TCP_WND` | 8×MSS=4288 | 接收窗口 |
|
||||
| `TCPIP_THREAD_STACKSIZE` | 512 | tcpip_thread 栈 |
|
||||
| `TCPIP_THREAD_PRIO` | 6 (最高) | tcpip_thread 优先级 |
|
||||
| `LWIP_DHCP` | 0 | 不使用 DHCP |
|
||||
| `LWIP_UDP` | 0 | 不使用 UDP |
|
||||
|
||||
### 8.3 sys_arch 移植层
|
||||
|
||||
`Drivers/LwIP/port/sys_arch.c` 提供 lwIP 到 FreeRTOS 的适配:
|
||||
`Drivers/LwIP/port/sys_arch.c` 需实现 lwIP 到 FreeRTOS 的适配:
|
||||
|
||||
1. `sys_thread_new`:创建 lwIP 线程
|
||||
2. `sys_mbox_*`:消息邮箱(基于 FreeRTOS Queue)
|
||||
1. `sys_thread_new`:创建 lwIP 线程(即 `tcpip_thread`)
|
||||
2. `sys_mbox_*`:消息邮箱(基于 FreeRTOS Queue,容量 `TCPIP_MBOX_SIZE=8`)
|
||||
3. `sys_sem_*`:信号量(基于 FreeRTOS Semaphore)
|
||||
4. `sys_mutex_*`:互斥锁(基于 FreeRTOS Mutex)
|
||||
5. `sys_arch_protect / unprotect`:临界区保护
|
||||
5. `sys_arch_protect / unprotect`:临界区保护(基于 `vPortEnterCritical / vPortExitCritical`)
|
||||
|
||||
### 8.4 lwIP 初始化流程
|
||||
|
||||
```c
|
||||
/* 在 MX_FREERTOS_Init 或 NetPollTask 中调用 */
|
||||
void lwip_init_task(void)
|
||||
{
|
||||
/* tcpip_thread 在 lwip_init() 或第一个 sys_thread_new 时自动启动 */
|
||||
tcpip_init(NULL, NULL);
|
||||
|
||||
/* 等待 tcpip_thread 就绪 */
|
||||
/* 添加网络接口 */
|
||||
netif_add(&ch390_netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
|
||||
netif_set_default(&ch390_netif);
|
||||
netif_set_up(&ch390_netif);
|
||||
}
|
||||
```
|
||||
|
||||
## 九、中断与 HAL 时间基准
|
||||
|
||||
@@ -365,34 +477,65 @@ FreeRTOS 下 `SysTick` 被 FreeRTOS 占用,HAL 时间基准改用 `TIM4`:
|
||||
|
||||
FreeRTOS 可管理的中断优先级必须 >= `configMAX_SYSCALL_INTERRUPT_PRIORITY`(本工程为 5)。
|
||||
|
||||
## 十、内存预算
|
||||
## 十、内存预算(路径 A 精确估算)
|
||||
|
||||
以 `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 余量 |
|
||||
| 项目 | 大小 | 说明 |
|
||||
|------|------|------|
|
||||
| 启动栈 (MSP) | 2,048 B | `startup_stm32f103xe.s` 定义 0x800 |
|
||||
| FreeRTOS 堆 (heap_4) | 10,240 B | `configTOTAL_HEAP_SIZE` |
|
||||
| 任务栈 (9 任务) | 13,312 B | 3,328 words × 4 (见上表) |
|
||||
| lwIP 堆 (MEM_SIZE) | 8,192 B | |
|
||||
| PBUF 池 (10 个) | ~6,000 B | 10 × ~600B |
|
||||
| MEMP 池 | ~4,000 B | netconn/netbuf/tcpip_msg/pcb/seg |
|
||||
| UART DMA+Ring 缓冲 | 2,304 B | 2 通道 × (256+256+512+384)/2 |
|
||||
| 路由缓冲池 (4×512B) | 2,048 B | 零拷贝指针传递 |
|
||||
| 配置结构 | 1,024 B | |
|
||||
| **合计** | **~49,168 B** | |
|
||||
| **余量 (RCT6 48KB)** | **~-928 B** | ⚠️ 超出,需优化或换 RDT6 |
|
||||
| **余量 (RDT6 64KB)** | **~15,264 B** | ✅ 充裕 |
|
||||
|
||||
### 10.2 Flash 预算
|
||||
### 10.2 优化空间(RCT6 下)
|
||||
|
||||
若坚持使用 RCT6,可通过以下措施压缩到 48KB 以内:
|
||||
|
||||
| 优化项 | 节省 |
|
||||
|--------|------|
|
||||
| 取消 TCP 任务的 ring buffer(netconn 内部有 pbuf 缓冲) | -2,048 B |
|
||||
| `configTOTAL_HEAP_SIZE` 降至 8KB | -2,048 B |
|
||||
| `MEM_SIZE` 降至 6KB | -2,048 B |
|
||||
| TcpCliTask 栈降至 192 words × 2 | -512 B |
|
||||
| **优化后合计** | **~42,504 B** |
|
||||
| **RCT6 余量** | **~5,464 B** |
|
||||
|
||||
### 10.3 备选 MCU
|
||||
|
||||
当 RAM 最终不够用时,切换为 `STM32F103RDT6`(pin-to-pin 替代):
|
||||
|
||||
| 项目 | RCT6 | RDT6 |
|
||||
|------|------|------|
|
||||
| Flash | 256 KB | 384 KB |
|
||||
| SRAM | 48 KB | 64 KB |
|
||||
| 引脚 | LQFP64 | LQFP64(完全兼容) |
|
||||
| 启动文件 | `startup_stm32f103xe.s` | `startup_stm32f103xd.s` |
|
||||
| 宏定义 | `STM32F103xE` | `STM32F103xD` |
|
||||
| Flash 算法 | `STM32F10x_HD` | `STM32F10x_HD`(相同) |
|
||||
| SRAM 大小 | `0xC000` | `0x10000` |
|
||||
| Flash 大小 | `0x40000` | `0x60000` |
|
||||
|
||||
### 10.4 Flash 预算
|
||||
|
||||
| 项目 | 估计值 | 说明 |
|
||||
|------|--------|------|
|
||||
| FreeRTOS 内核 | ~8 KB | 含 CMSIS-RTOS V2 |
|
||||
| HAL 驱动 | ~20 KB | GPIO/UART/SPI/DMA/IWDG/TIM |
|
||||
| lwIP 协议栈 | ~40 KB | core + api + ipv4 + netif |
|
||||
| lwIP 协议栈 | ~50 KB | core + api + ipv4 + netif + sys_arch |
|
||||
| CH390 驱动 | ~4 KB | |
|
||||
| 应用代码 | ~20 KB | config/uart_trans/tcp/route |
|
||||
| **合计** | ~92 KB | 预留约 164 KB 余量 |
|
||||
| 应用代码 | ~20 KB | config/uart_trans/tcp_server/tcp_client |
|
||||
| **合计** | ~102 KB | RCT6 预留 154 KB,RDT6 预留 282 KB |
|
||||
|
||||
## 十一、硬件资源
|
||||
|
||||
@@ -451,3 +594,45 @@ FreeRTOS 可管理的中断优先级必须 >= `configMAX_SYSCALL_INTERRUPT_PRIOR
|
||||
2. 控制帧只使用 `DSTMASK=0x00`
|
||||
3. MUX 帧格式固定为 `SYNC | LEN_H | LEN_L | SRCID | DSTMASK | PAYLOAD | TAIL`
|
||||
4. AT 手册、需求说明、技术实现三份文档不得再出现历史展开式字段
|
||||
|
||||
## 十四、路径 A 实现清单
|
||||
|
||||
### 14.1 必须重写的模块
|
||||
|
||||
| 模块 | 原实现 | 目标实现 | 说明 |
|
||||
|------|--------|----------|------|
|
||||
| `tcp_server.c/.h` | lwIP RAW API 回调 | netconn 阻塞任务 | `tcp_new` → `netconn_new`,回调 → 阻塞循环 |
|
||||
| `tcp_client.c/.h` | lwIP RAW API 回调 | netconn 阻塞任务 | 同上 |
|
||||
| `sys_arch.c/.h` | NO_SYS=1 空壳 | FreeRTOS 移植层 | `sys_mbox`、`sys_sem`、`sys_mutex`、`sys_thread` |
|
||||
| `lwipopts.h` | NO_SYS=1 | NO_SYS=0 + netconn | 已更新 |
|
||||
| `main.c` | while(1) 轮询 | FreeRTOS 任务创建 | `App_Poll()` → 各任务函数 |
|
||||
| `stm32f1xx_it.c` | 裸机 ISR | FreeRTOS ISR | `xxFromISR` API |
|
||||
|
||||
### 14.2 可复用(需适配)的模块
|
||||
|
||||
| 模块 | 适配内容 |
|
||||
|------|----------|
|
||||
| `uart_trans.c/.h` | 添加 `xTaskNotifyFromISR` 替代 poll 模式 |
|
||||
| `config.c/.h` | 添加 `xQueueReceive` 替代 `config_poll()` |
|
||||
| `flash_param.c/.h` | 无需修改 |
|
||||
| `CH390` 驱动 | `ethernetif_poll` 改为 NetPollTask 调用,SPI 加 Mutex 保护 |
|
||||
| `ethernetif.c` | 添加 `netif_add` 的 `tcpip_input` 回调 |
|
||||
|
||||
### 14.3 无需修改的模块
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| `FreeRTOSConfig.h` | 已更新(任务优先级宏、堆大小) |
|
||||
| `startup_stm32f103xe.s` | 已适配 RCT6 |
|
||||
| `TCP2UART.ioc` | 已适配 RCT6 + FreeRTOS + TIM4 |
|
||||
| `MDK-ARM/TCP2UART.uvprojx` | 已适配 RCT6 + xE 宏 |
|
||||
| MUX 帧编解码 | 协议逻辑与 RTOS 无关 |
|
||||
|
||||
### 14.4 新增模块
|
||||
|
||||
| 模块 | 职责 |
|
||||
|------|------|
|
||||
| `route_msg.c/.h` | 零拷贝路由消息池管理 |
|
||||
| `task_tcp_server.c/.h` | netconn Server 任务模板 |
|
||||
| `task_tcp_client.c/.h` | netconn Client 任务模板 |
|
||||
| `task_net_poll.c/.h` | CH390 poll + link check 任务 |
|
||||
|
||||
Reference in New Issue
Block a user