refactor(NET): netMsgQueueHandle 收进 net_socket 私有,改为创建后绑定

结构债 S-2 的最后一步——**该族的 24 处手写跨模块裸 extern 就此全部清零**。

队列对象仍由 CubeMX 在 `MX_FREERTOS_Init()` 创建(**创建点不可外移**:
`osKernelInitialize()` 之前的任何创建类 API 会杀死启动,见
`docs/架构设计/项目启动顺序管理.md`);改为创建后立刻在 `Src/freertos.c` 的
`USER CODE BEGIN RTOS_QUEUES` 区调用 `net_msg_queue_adopt(netMsgQueueHandle)`,
把句柄交给唯一使用者。`net_socket.c` 内改用 `static osMessageQueueId_t
s_net_msg_queue`(21 处引用改名),BSP 对该全局变量的裸 `extern` 消失——现在
`netMsgQueueHandle` 只出现在生成文件自己的两处(定义 + 创建)。

两个刻意的设计决定:
① **不新建第二个队列**。自建队列 + 删 `.ioc` 里的 netMsgQueue 也能收口,但要
   CubeMX 重生成(Ask-first),过渡期还会同时存在两个队列,白占 CCM 堆里
   8 × `net_msg_t` 的空间——CCM 正是当下 87.9% 的红线。故选"创建后绑定"。
② `adopt()` **拒绝重复绑定、保留首次句柄**。真出现两处绑定时,静默换句柄会让
   已入队的请求留在旧队列里永不处理;拒掉第二个反而更容易暴露。绑定前的判空
   是真实防线:丢了那一行,后果是"所有 net_* 请求被丢弃、网络全线静默不通",
   不是崩溃。

**防回退**:`check_cubemx_survival.py` 新增存活项 `net-msgq-adopt`(region
`RTOS_QUEUES`、`must_contain=["net_msg_queue_adopt"]`),易失清单 29 → 30 项全部
到位;基线已重建(有意的 USER CODE 区改动,按脚本文档流程 `--write`)。

**体量**:`Code` 213,204 → **213,236 B(+32)**、`ER_IROM1` **231,816 B(22.1%)**;
`RW +4 / ZI −4` → `RW_IRAM1` 恒 **75,264 B(57.4%)**、`RW_CCM` 恒 **57,376 B
(87.9%)**、`RW+ZI` 总量 132,688 B 不变(没有多占一个字节 RAM)。

**验证**:`@build` 0 错 0 警告;`@test` PASS——624 ms 到 `net init: OK`、`i104:
listening on 2404`、无 `[ERR]`/Fault、`heap free=15800 min_ever=8464` 逐项不变。
另在真机跑了一次 FTP 控制通道往返:220 → `USER admin` 331 → `PASS admin` 230
→ `PWD` 257 → `TYPE I` 200 → `QUIT` 221。每条命令都是一次过队列的
net_recv/net_send,证明绑定路径真在跑;`.map` 里 `freertos.o(MX_FREERTOS_Init)
refers to net_socket.o(i.net_msg_queue_adopt)` 证明镜像含该行。

⚠ **顺带揪出一条测试工具漂移(本次未修,等定夺)**:
`test/host/ftp_up_dl_test.py:123/126` 仍写死 `USER anonymous` /
`PASS test@test.com`,而设备自 N-19(2026-10-11)起按 `/config.ini [ftp]` 校验
admin/admin(SHA-256 `pwd_hash`)→ 该脚本必然登录失败。它是手工工具、不在任何
pre-commit 钩子里,所以 11 天没人发现,而 `docs/测试说明/FTP_Test_Guide.md` 把它
列为"推荐入口"。建议加 `--user/--password`(默认 admin/admin),并连
`ftp_speed_test.py` 一起核。

数字联动:两份 `data/` 快照重跑、`ram_baseline --update/--write`、
`check_mem_numbers --write`、FLASH 与任务栈两张配图常量重算并重新生成(逐文本按
字号与锚点复查越界 = 0)、报告 §1.3/§5.1/§5.4 与部署文档 §3.3 同步。报告 §0.4 的
S-2 行按「完成即销项」改写为已闭环,§9 拆出独立 S-2 行标 ✅。

门禁:`@build` 0/0、`@test` PASS、`layer-deps` / `cubemx-survival` / `mem-numbers`
(本次改到台账受管区,scan 已过)/ `mem-budget`(57.4% / 87.9%)/ `task-table` /
`doc-links --all`(146 文档 0 问题)/ `id-check --strict`(增量拦截通过、可判定
82.84%、存量债 640)全绿;14 个文件字节卫生 BOM 无 / CR 0 / U+FFFD 0 / 无尾空格。
未推送。
This commit is contained in:
2026-10-22 20:01:40 +08:00
parent 6ede1443e9
commit e7f28502bc
14 changed files with 211 additions and 123 deletions
+45 -23
View File
@@ -69,12 +69,34 @@ static uint16_t s_dynamic_port = 49152; /* 动态端口分配起始
static volatile uint32_t s_net_generation = 0; /* 网络代次号:网络重建完成时递增(服务据此重建监听) */
/*
* 消息队列(线程安全核心)
* 消息队列(线程安全核心,句柄由本模块私有持有)
* 外部任务经 net_send/net_recv/net_close 等公开 API 投递请求
* netTask 调 net_process_messages() 串行处理所有 CH395F 操作
* 由 CubeMX 在 MX_FREERTOS_Init()(osKernelInitialize 之后)中创建
* 队列对象由 CubeMX 在 MX_FREERTOS_Init()(osKernelInitialize 之后)创建,创建后
* 立刻经 net_msg_queue_adopt() 绑定到这里;绑定之前恒为 NULL,各处投递前的判空
* 因此是真实防线而不是形式(绑定失败的后果是"请求被丢弃",不是崩溃)。
*/
extern osMessageQueueId_t netMsgQueueHandle; /* CubeMX 生成的消息队列句柄 */
static osMessageQueueId_t s_net_msg_queue;
/*
* 函数功能:绑定消息队列句柄(本模块是该句柄的唯一使用者)
* 入口参数:queue_id - 已创建的消息队列句柄
* 返回值:0 = 绑定成功;-1 = 句柄为空或重复绑定(保留首次绑定,不覆盖)
* 限定条件:osKernelInitialize() 之后、netTask 启动之前,由 MX_FREERTOS_Init() 调用一次
* 函数说明:见 net_socket.h 同名声明处的完整说明。重复绑定**不覆盖**是刻意的——
* 真出现两处绑定时,说明有人新加了调用点,此时保留先绑的那个并把后来者
* 拒掉,比静默换句柄(已入队的请求会留在旧队列里永不处理)更容易暴露。
*/
int net_msg_queue_adopt(osMessageQueueId_t queue_id) {
if (queue_id == NULL) {
return -1;
}
if (s_net_msg_queue != NULL) {
return -1;
}
s_net_msg_queue = queue_id;
return 0;
}
/* ================= 错误码存储(E-03 修复:按任务隔离,消除跨任务覆写竞态) =================
*
@@ -582,7 +604,7 @@ void net_process_messages(void) {
net_msg_t msg;
/* 队列句柄未就绪(net_init 未完成):直接返回 */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
return;
}
@@ -599,7 +621,7 @@ void net_process_messages(void) {
net_reconcile_tick();
/* 队列排空:超时 0 非阻塞取,每条处理一轮,直到本轮队列为空 */
while (osMessageQueueGet(netMsgQueueHandle, &msg, NULL, 0) == osOK) {
while (osMessageQueueGet(s_net_msg_queue, &msg, NULL, 0) == osOK) {
/* 默认处理完即发即时回执;RECV 挂起登记时置 0(回执推迟到
* net_pending_tick 完成检查,避免"登记成功"被误报为处理结果) */
int do_notify = 1;
@@ -1120,7 +1142,7 @@ int net_listen(int sockfd) {
}
/* 消息队列未创建(网络层未初始化)→ 通用错误 */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -1136,7 +1158,7 @@ int net_listen(int sockfd) {
msg.result = -1;
/* 入队:队列满时阻塞调用方直至有空位 */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败 → BUSY */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -1284,7 +1306,7 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
}
/* 消息队列未创建(网络层未初始化)→ 通用错误 */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -1304,7 +1326,7 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
msg.result = -1;
/* 入队:队列满时阻塞调用方直至有空位 */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败 → BUSY */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -1445,7 +1467,7 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
}
/* 消息队列未创建(网络层未初始化)→ 通用错误 */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -1474,7 +1496,7 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
msg.result = -1;
/* 入队:队列满时阻塞调用方直至有空位 */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败 → BUSY */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -2011,9 +2033,9 @@ static int net_drop_conn_locked(net_sock_t *p_sock) {
* 限定条件:1. 必须在【非 netTask】上下文中调用(应用/测试任务);若在 netTask 内调用会自己等自己 → 死锁
* (netTask 阻塞在 xTaskNotifyWait 而无人处理消息);netTask 内请直接用 net_send_locked()
* 2. Socket 须处于 ESTABLISHED 状态
* 3. net_init() + MX_FREERTOS_Init() 已执行,netMsgQueueHandle 已由 net_init 创建
* 3. net_init() + MX_FREERTOS_Init() 已执行,消息队列已创建并绑定到本模块
* 函数说明:1. 所有 CH395F SPI 访问只允许在 netTask 内串行执行(见 TRAP-NET-14)
* 2. 本函数不直接触碰 SPI,而是把发送请求打包成 net_msg_t 投递到 netMsgQueueHandle
* 2. 本函数不直接触碰 SPI,而是把发送请求打包成 net_msg_t 投递到本模块的消息队列
* 3. netTask 的 net_process_messages() 取出并在 netTask 上下文调用 net_send_locked() 真正写 CH395F
* 4. 调用方经 FreeRTOS TaskNotify 阻塞等待处理结果,对外呈现"同步发送"语义
* 5. 函数返回 = 本次发送已被 netTask 处理完毕(成功或失败)
@@ -2031,7 +2053,7 @@ int net_send(int sockfd, const void *buf, int len, int flags) {
}
/* ---- 2. 运行环境检查:消息队列须已创建(网络层已初始化) ---- */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
/* 网络层未初始化 */
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -2055,7 +2077,7 @@ int net_send(int sockfd, const void *buf, int len, int flags) {
msg.result = -1;
/* ---- 4. 入队:将消息投递给 netTask,osWaitForever 表示队列满时阻塞调用方 ---- */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败(队列异常等极端情况) */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -2107,7 +2129,7 @@ int net_recv(int sockfd, void *buf, int len, int flags) {
}
/* 消息队列未创建(网络层未初始化)→ 通用错误 */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -2129,7 +2151,7 @@ int net_recv(int sockfd, void *buf, int len, int flags) {
msg.result = -1;
/* 入队:队列满时阻塞调用方直至有空位 */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败 → BUSY */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -2193,7 +2215,7 @@ int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms) {
}
/* ---- 2. 运行环境检查:消息队列须已创建(网络层已初始化) ---- */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
/* 网络层未初始化 */
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -2225,7 +2247,7 @@ int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms) {
msg.result = -1;
/* ---- 5. 入队:将消息投递给 netTask,osWaitForever 表示队列满时阻塞调用方 ---- */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败(队列异常等极端情况) */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -2278,7 +2300,7 @@ int net_close(int sockfd) {
}
/* 消息队列未创建(网络层未初始化)→ 通用错误 */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -2294,7 +2316,7 @@ int net_close(int sockfd) {
msg.result = -1;
/* 入队:队列满时阻塞调用方直至有空位 */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败 → BUSY */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -2336,7 +2358,7 @@ int net_drop_conn(int sockfd) {
}
/* 消息队列未创建(网络层未初始化)→ 通用错误 */
if (netMsgQueueHandle == NULL) {
if (s_net_msg_queue == NULL) {
return NET_ERR_RETURN_1(NET_ERR);
}
@@ -2352,7 +2374,7 @@ int net_drop_conn(int sockfd) {
msg.result = -1;
/* 入队:队列满时阻塞调用方直至有空位 */
if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
if (osMessageQueuePut(s_net_msg_queue, &msg, 0, osWaitForever) != osOK) {
/* 入队失败 → BUSY */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
+18
View File
@@ -24,6 +24,7 @@ extern "C" {
#ifndef NET_NO_OS
#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os2.h" /* osMessageQueueId_t:net_msg_queue_adopt() 的参数类型 */
#endif /* NET_NO_OS */
#ifndef NET_NO_OS
@@ -60,6 +61,23 @@ typedef struct {
} net_msg_t;
#endif /* NET_NO_OS */
#ifndef NET_NO_OS
/*
* 函数功能:把消息队列句柄交给本模块持有(**句柄的唯一使用者是 net_socket.c**)
* 入口参数:queue_id - 已创建的消息队列句柄
* 返回值:0 = 绑定成功;-1 = 句柄为空、或已绑定过(重复绑定保留首次句柄,不覆盖)
* 限定条件:必须在 osKernelInitialize() 之后、netTask 启动之前调用一次
* 函数说明:队列对象本身仍由 CubeMX 在 MX_FREERTOS_Init() 里创建——创建点不能外移,
* 因为 osKernelInitialize() 之前任何创建类 API 都会杀死启动
* (docs/架构设计/项目启动顺序管理.md)。外移创建点还会让重新生成把它抹掉。
* 所以这里用"创建后立刻绑定":调用点见 Src/freertos.c 的
* USER CODE BEGIN RTOS_QUEUES 区。此前本模块靠对本文件外全局变量的
* 裸 extern 取用,谁改名或删掉创建语句都不会有提示。
*/
int net_msg_queue_adopt(osMessageQueueId_t queue_id);
#endif /* NET_NO_OS */
/*
* 网络初始化接口
*/
+5
View File
@@ -329,6 +329,11 @@ void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* 队列对象由上面生成的语句创建(创建点不可外移:osKernelInitialize() 之前的
创建类 API 会杀死启动)。这里立刻把句柄交给唯一使用者 net_socket,之后本模块
不再对外暴露这个全局变量;少了这一行,net_socket 的句柄恒为 NULL,所有 net_*
请求会被判空丢弃(表现为网络全线静默不通)。 */
(void)net_msg_queue_adopt(netMsgQueueHandle);
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
+3 -3
View File
@@ -21,7 +21,7 @@
<text x="186" y="152" text-anchor="end" dominant-baseline="central" class="label" fill="#333">ftpTask</text>
<rect class="bar-seg" x="190" y="144" width="162.5" height="16" fill="#BBDEFB" rx="3"/>
<rect x="190" y="144" width="57.8" height="16" fill="#2196F3" rx="3"/>
<text x="190" y="171" dominant-baseline="central" class="legend-text" fill="#333">配置 4096B | 实测峰值 764B | 最坏 1456B | 余量 2640B (64%) <tspan fill="#2E7D32" font-weight="bold">PASS</tspan></text>
<text x="190" y="171" dominant-baseline="central" class="legend-text" fill="#333">配置 4096B | 实测峰值 1404B | 最坏 1456B | 余量 2640B (64%) <tspan fill="#2E7D32" font-weight="bold">PASS</tspan></text>
<text x="186" y="192" text-anchor="end" dominant-baseline="central" class="label" fill="#333">uiTask</text>
<rect class="bar-seg" x="190" y="184" width="650.0" height="16" fill="#FFE0B2" rx="3"/>
<rect x="190" y="184" width="160.8" height="16" fill="#FF9800" rx="3"/>
@@ -33,7 +33,7 @@
<text x="186" y="272" text-anchor="end" dominant-baseline="central" class="label" fill="#333">timeSyncTask</text>
<rect class="bar-seg" x="190" y="264" width="101.6" height="16" fill="#BBDEFB" rx="3"/>
<rect x="190" y="264" width="50.1" height="16" fill="#2196F3" rx="3"/>
<text x="190" y="291" dominant-baseline="central" class="legend-text" fill="#333">配置 2560B | 实测峰值 616B | 最坏 1264B | 余量 1296B (50%) <tspan fill="#2E7D32" font-weight="bold">PASS</tspan></text>
<text x="190" y="291" dominant-baseline="central" class="legend-text" fill="#333">配置 2560B | 实测峰值 648B | 最坏 1264B | 余量 1296B (50%) <tspan fill="#2E7D32" font-weight="bold">PASS</tspan></text>
<text x="186" y="312" text-anchor="end" dominant-baseline="central" class="label" fill="#333">adcTask</text>
<rect class="bar-seg" x="190" y="304" width="101.6" height="16" fill="#C8E6C9" rx="3"/>
<rect x="190" y="304" width="52.4" height="16" fill="#4CAF50" rx="3"/>
@@ -45,7 +45,7 @@
<text x="186" y="392" text-anchor="end" dominant-baseline="central" class="label" fill="#333">protectTask</text>
<rect class="bar-seg" x="190" y="384" width="81.2" height="16" fill="#BBDEFB" rx="3"/>
<rect x="190" y="384" width="34.6" height="16" fill="#2196F3" rx="3"/>
<text x="190" y="411" dominant-baseline="central" class="legend-text" fill="#333">配置 2048B | 实测峰值 624B | 最坏 872B | 余量 1176B (57%) <tspan fill="#2E7D32" font-weight="bold">PASS</tspan></text>
<text x="190" y="411" dominant-baseline="central" class="legend-text" fill="#333">配置 2048B | 实测峰值 828B | 最坏 872B | 余量 1176B (57%) <tspan fill="#2E7D32" font-weight="bold">PASS</tspan></text>
<text x="186" y="434" text-anchor="end" dominant-baseline="central" class="label" fill="#333">idle</text>
<rect class="bar-seg" x="190" y="428" width="20.3" height="12" fill="#90A4AE" rx="2"/>
<text x="214.3125" y="434" dominant-baseline="central" class="legend-text" fill="#333">512B(未实测)</text>

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

+12 -12
View File
@@ -10,26 +10,26 @@
<text x="410.0" y="24" text-anchor="middle" class="title">Flash (1MB) 使用布局 — 2026-10-22 @build</text>
<rect class="bar-seg" x="60" y="50" width="150.5" height="40" fill="#2196F3" rx="2"/>
<text x="135.2" y="70.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">代码段 (Code) 208.2KB</text>
<rect class="bar-seg" x="210.4621124267578" y="50" width="13.1" height="40" fill="#4CAF50" rx="2"/>
<rect class="bar-seg" x="210.4846954345703" y="50" width="13.1" height="40" fill="#4CAF50" rx="2"/>
<text x="227.6" y="70.0" text-anchor="start" dominant-baseline="central" class="legend-text" fill="#333">只读数据 (RO) 18.1KB</text>
<rect class="bar-seg" x="223.57437133789062" y="50" width="575.6" height="40" fill="#E0E0E0" rx="2"/>
<rect class="bar-seg" x="223.59695434570312" y="50" width="575.6" height="40" fill="#E0E0E0" rx="2"/>
<text x="511.4" y="70.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">Flash 空闲 796.5KB</text>
<text x="60" y="108" class="label" fill="#333">已用: 227.5KB (22.2%) 空闲: 796.5KB (77.8%) ER_IROM1(Code+RO): 226.4KB (22.1%) 总量: 1MB (= ROM 合计口径)</text>
<text x="60" y="124" class="label" fill="#555">Code + RO 分布(ER_IROM1 226.4KB,按 .map 对象归类)</text>
<rect class="bar-seg" x="60" y="130" width="280.0" height="24" fill="#4CAF50" rx="2"/>
<text x="200.0" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">85.7KB</text>
<rect class="bar-seg" x="340.0125979360094" y="130" width="182.0" height="24" fill="#2196F3" rx="2"/>
<rect class="bar-seg" x="339.9739448528143" y="130" width="182.0" height="24" fill="#2196F3" rx="2"/>
<text x="431.0" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">55.7KB</text>
<rect class="bar-seg" x="522.027491112415" y="130" width="81.9" height="24" fill="#F44336" rx="2"/>
<text x="563.0" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">25.0KB</text>
<rect class="bar-seg" x="603.8992337693714" y="130" width="57.1" height="24" fill="#607D8B" rx="2"/>
<rect class="bar-seg" x="521.963712599648" y="130" width="81.9" height="24" fill="#F44336" rx="2"/>
<text x="562.9" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">25.0KB</text>
<rect class="bar-seg" x="603.8241536390931" y="130" width="57.1" height="24" fill="#607D8B" rx="2"/>
<text x="632.4" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">17.5KB</text>
<rect class="bar-seg" x="660.9706450833535" y="130" width="34.9" height="24" fill="#FF9800" rx="2"/>
<rect class="bar-seg" x="695.8692575846478" y="130" width="34.4" height="24" fill="#00BCD4" rx="2"/>
<rect class="bar-seg" x="730.228316018362" y="130" width="27.0" height="24" fill="#9C27B0" rx="2"/>
<rect class="bar-seg" x="757.2634866945087" y="130" width="17.5" height="24" fill="#795548" rx="2"/>
<rect class="bar-seg" x="774.7782418113417" y="130" width="1.5" height="24" fill="#B0BEC5" rx="2"/>
<rect class="bar-seg" x="776.2723915369482" y="130" width="23.7" height="24" fill="#E0E0E0" rx="2"/>
<rect class="bar-seg" x="660.8876867860718" y="130" width="34.9" height="24" fill="#FF9800" rx="2"/>
<rect class="bar-seg" x="695.7814818649274" y="130" width="34.4" height="24" fill="#00BCD4" rx="2"/>
<rect class="bar-seg" x="730.1357973565242" y="130" width="27.0" height="24" fill="#9C27B0" rx="2"/>
<rect class="bar-seg" x="757.1672360837907" y="130" width="17.5" height="24" fill="#795548" rx="2"/>
<rect class="bar-seg" x="774.6795734548091" y="130" width="1.5" height="24" fill="#B0BEC5" rx="2"/>
<rect class="bar-seg" x="776.1735169272182" y="130" width="23.8" height="24" fill="#E0E0E0" rx="2"/>
<rect x="60" y="167" width="10" height="10" fill="#4CAF50" rx="2"/>
<text x="74" y="176" class="legend-text" fill="#333">LVGL 库 85.7KB</text>
<rect x="255" y="167" width="10" height="10" fill="#2196F3" rx="2"/>

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -38,10 +38,10 @@
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ER_IROM1 | 231,784 B (226.35 KB) | 1,048,576 B (1024 KB) | 22.1% |
| ER_IROM1 | 231,816 B (226.38 KB) | 1,048,576 B (1024 KB) | 22.1% |
| RW_IRAM1 | 75,264 B (73.50 KB) | 131,072 B (128 KB) | 57.4% |
| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
| **Flash (ROM 合计)** | **232,968 B (227.5 KB)** | 1,048,576 B (1024 KB) | **22.2%** |
| **Flash (ROM 合计)** | **233,004 B (227.5 KB)** | 1,048,576 B (1024 KB) | **22.2%** |
<!-- MEM_SNAPSHOT:END -->
各区的容量与常量来源:
+2 -2
View File
@@ -15,14 +15,14 @@
<!-- MEM_BUDGET:BEGIN generated by scripts/ram_baseline.py -->
| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |
|---|---|---|---|---|
| ER_IROM1 (Flash) | 231,784 B | 1,048,576 B | 22.1% | 参考 |
| ER_IROM1 (Flash) | 231,816 B | 1,048,576 B | 22.1% | 参考 |
| RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS |
| UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 |
| RW_IRAM1 | 75,264 B | 131,072 B | 57.4% | PASS |
| 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 |
|---|---|---|---|
| 网络 | 13,690 B | 12 KB | ⚠ 超 1.4 KB |
| 网络 | 13,694 B | 12 KB | ⚠ 超 1.4 KB |
| 存储 | 7,056 B | 12 KB | OK |
| UI | 30,422 B | 16 KB | ⚠ 超 13.7 KB |
| RTOS 堆 | 57,376 B | 56 KB | 堆=配额 |
+61 -61
View File
@@ -1,24 +1,24 @@
# STM32F4-Base RAM/Flash Usage Report
> Generated: 2026-10-22 19:14 Map: `STM32F407-Demo.map`
> Generated: 2026-10-22 19:56 Map: `STM32F407-Demo.map`
## 1. Grand Totals (全局总量)
| Metric | Value |
|---|---|
| Code (inc. data) | 213,204 B (208.2 KB) |
| Code (inc. data) | 213,236 B (208.2 KB) |
| RO Data | 18,580 B (18.1 KB) |
| RW Data (initialized) | 1,184 B (1.16 KB) |
| ZI Data (zero-init) | 131,504 B (128.4 KB) |
| **Total RO (Code + RO)** | **231,784 B (226.4 KB)** |
| RW Data (initialized) | 1,188 B (1.16 KB) |
| ZI Data (zero-init) | 131,500 B (128.4 KB) |
| **Total RO (Code + RO)** | **231,816 B (226.4 KB)** |
| **Total RW (RW + ZI) = SRAM used** | **132,688 B (129.58 KB)** |
| **Total ROM (Code + RO + RW init)** | **232,968 B (227.5 KB)** |
| **Total ROM (Code + RO + RW init)** | **233,004 B (227.5 KB)** |
## 2. 执行区水位 (Execution Regions)
| Region | Base | Size | Max | Util% |
|---|---|---|---|---|
| ER_IROM1 | 0x08000000 | 231,784 B (226.35 KB) | 1,048,576 B (1024 KB) | 22.1% |
| ER_IROM1 | 0x08000000 | 231,816 B (226.38 KB) | 1,048,576 B (1024 KB) | 22.1% |
| RW_CCM | 0x10000000 | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
| UNINIT_CCM | 0x1000FF00 | 48 B (0.05 KB) | 256 B (0 KB) | 18.8% |
| RW_IRAM1 | 0x20000000 | 75,264 B (73.50 KB) | 131,072 B (128 KB) | 57.4% |
@@ -33,54 +33,54 @@
| 4 | 0x2000EDC8 | 6,408 | 6.26 | Zero | .bss | ui_port.o |
| 5 | 0x2000667C | 6,200 | 6.05 | Zero | .bss | nand_ftl.o |
| 6 | 0x20004E18 | 4,152 | 4.05 | Zero | .bss | ch395f.o |
| 7 | 0x20002054 | 4,096 | 4.00 | Zero | .bss | console_log.o |
| 8 | 0x20001274 | 3,552 | 3.47 | Zero | .bss | sys_log_mcu.o |
| 9 | 0x20003640 | 2,724 | 2.66 | Zero | .bss | default_task.o |
| 7 | 0x20002058 | 4,096 | 4.00 | Zero | .bss | console_log.o |
| 8 | 0x20001278 | 3,552 | 3.47 | Zero | .bss | sys_log_mcu.o |
| 9 | 0x20003644 | 2,724 | 2.66 | Zero | .bss | default_task.o |
| 10 | 0x2000A524 | 1,720 | 1.68 | Zero | .bss | cmsis_os2.o |
| 11 | 0x2000444C | 1,440 | 1.41 | Zero | .bss | sample_ring.o |
| 12 | 0x20009F48 | 1,220 | 1.19 | Zero | .bss | tasks.o |
| 13 | 0x20000D74 | 1,104 | 1.08 | Zero | .bss | cfg_file_store_mcu.o |
| 14 | 0x20003054 | 1,064 | 1.04 | Zero | .bss | soe_store.o |
| 13 | 0x20000D78 | 1,104 | 1.08 | Zero | .bss | cfg_file_store_mcu.o |
| 14 | 0x20003058 | 1,064 | 1.04 | Zero | .bss | soe_store.o |
| 15 | 0x20012200 | 1,024 | 1.00 | Zero | | startup_stm32f407xx.o |
| 16 | 0x20005E50 | 800 | 0.78 | Zero | .bss | gd5f2gq5ue.o |
| 17 | 0x200040E8 | 712 | 0.70 | Zero | .bss | iec104_serv.o |
| 18 | 0x20000AB4 | 704 | 0.69 | Zero | .bss | cfg_file.o |
| 19 | 0x200005CC | 560 | 0.55 | Zero | .bss | spi.o |
| 20 | 0x20000844 | 552 | 0.54 | Zero | .bss | usart.o |
| 18 | 0x20000AB8 | 704 | 0.69 | Zero | .bss | cfg_file.o |
| 19 | 0x200005D0 | 560 | 0.55 | Zero | .bss | spi.o |
| 20 | 0x20000848 | 552 | 0.54 | Zero | .bss | usart.o |
| 21 | 0x20009CE0 | 552 | 0.54 | Zero | .bss | lftpd_io.o |
| 22 | 0x2000ABDC | 492 | 0.48 | Zero | .bss | lv_init.o |
| 23 | 0x20004C38 | 480 | 0.47 | Zero | .bss | freq.o |
| 24 | 0x2000629C | 416 | 0.41 | Zero | .bss | net_socket.o |
| 25 | 0x200064DC | 416 | 0.41 | Zero | .bss | net_pending.o |
| 26 | 0x200034C0 | 384 | 0.38 | Zero | .bss | task_prof.o |
| 26 | 0x200034C4 | 384 | 0.38 | Zero | .bss | task_prof.o |
| 27 | 0x20004A8C | 320 | 0.31 | Zero | .bss | prot_set.o |
| 28 | 0x2000A40C | 280 | 0.27 | Zero | .bss | timers.o |
| 29 | 0x20006190 | 268 | 0.26 | Zero | .bss | rs485.o |
| 30 | 0x200011C4 | 176 | 0.17 | Zero | .bss | prot_set_store.o |
| 31 | 0x200004C4 | 168 | 0.16 | Zero | .bss | adc.o |
| 32 | 0x200002B0 | 160 | 0.16 | Data | .data | lftpd.o |
| 30 | 0x200011C8 | 176 | 0.17 | Zero | .bss | prot_set_store.o |
| 31 | 0x200004C8 | 168 | 0.16 | Zero | .bss | adc.o |
| 32 | 0x200002B4 | 160 | 0.16 | Data | .data | lftpd.o |
| 33 | 0x200049EC | 160 | 0.16 | Zero | .bss | phasor.o |
| 34 | 0x200106D0 | 152 | 0.15 | Zero | .bss | ui_menu_view.o |
| 35 | 0x2000643C | 128 | 0.12 | Zero | .bss | net_listener.o |
| 36 | 0x20004BCC | 108 | 0.11 | Zero | .bss | prot_elm.o |
| 37 | 0x2000056C | 84 | 0.08 | Zero | .bss | i2c.o |
| 37 | 0x20000570 | 84 | 0.08 | Zero | .bss | i2c.o |
| 38 | 0x200043F8 | 84 | 0.08 | Zero | .bss | adc_input.o |
| 39 | 0x2000024C | 83 | 0.08 | Data | .data | ftp_cfg.o |
| 40 | 0x200007FC | 72 | 0.07 | Zero | .bss | tim.o |
| 41 | 0x20000A6C | 72 | 0.07 | Zero | .bss | stm32f4xx_hal_timebase_tim.o |
| 42 | 0x2000347C | 68 | 0.07 | Zero | .bss | task_watchdog.o |
| 43 | 0x20000480 | 65 | 0.06 | Zero | .bss | freertos.o |
| 39 | 0x20000250 | 83 | 0.08 | Data | .data | ftp_cfg.o |
| 40 | 0x20000800 | 72 | 0.07 | Zero | .bss | tim.o |
| 41 | 0x20000A70 | 72 | 0.07 | Zero | .bss | stm32f4xx_hal_timebase_tim.o |
| 42 | 0x20003480 | 68 | 0.07 | Zero | .bss | task_watchdog.o |
| 43 | 0x20000484 | 65 | 0.06 | Zero | .bss | freertos.o |
| 44 | 0x20009F08 | 64 | 0.06 | Zero | .bss | queue.o |
| 45 | 0x20000354 | 60 | 0.06 | Data | .data | tasks.o |
| 46 | 0x2000040C | 60 | 0.06 | Data | .data | ui_page_selftest.o |
| 45 | 0x20000358 | 60 | 0.06 | Data | .data | tasks.o |
| 46 | 0x20000410 | 60 | 0.06 | Data | .data | ui_page_selftest.o |
| 47 | 0x20010768 | 60 | 0.06 | Zero | .bss | ui_page_runlog.o |
| 48 | 0x20000150 | 48 | 0.05 | Data | .data | adc_health.o |
| 49 | 0x200043C8 | 48 | 0.05 | Zero | .bss | iec104_pts.o |
| 50 | 0x20000000 | 44 | 0.04 | Data | .data | freertos.o |
| 51 | 0x2000009C | 44 | 0.04 | Data | .data | task_watchdog.o |
| 52 | 0x20000044 | 36 | 0.04 | Data | .data | sys_log_mcu.o |
| 53 | 0x20000228 | 36 | 0.04 | Data | .data | net_cfg.o |
| 54 | 0x20000448 | 32 | 0.03 | Data | .data | ui_standby.o |
| 53 | 0x2000022C | 36 | 0.04 | Data | .data | net_cfg.o |
| 54 | 0x2000044C | 32 | 0.03 | Data | .data | ui_standby.o |
| 55 | 0x20006170 | 32 | 0.03 | Zero | .bss | tpafe5160.o |
| 56 | 0x200064BC | 32 | 0.03 | Zero | .bss | net_events.o |
| 57 | 0x20000128 | 28 | 0.03 | Data | .data | adc_input.o |
@@ -88,47 +88,47 @@
| 59 | 0x200000E4 | 24 | 0.02 | Data | .data | adc_task.o |
| 60 | 0x20000180 | 24 | 0.02 | Data | .data | prot_set.o |
| 61 | 0x2000019C | 24 | 0.02 | Data | .data | freq.o |
| 62 | 0x200001FC | 24 | 0.02 | Data | .data | net_listener.o |
| 62 | 0x20000200 | 24 | 0.02 | Data | .data | net_listener.o |
| 63 | 0x200043B0 | 24 | 0.02 | Zero | .bss | protect_task.o |
| 64 | 0x20000030 | 20 | 0.02 | Data | .data | cfg_file.o |
| 65 | 0x20000080 | 20 | 0.02 | Data | .data | soe_store.o |
| 66 | 0x200001D0 | 20 | 0.02 | Data | .data | gd5f2gq5ue.o |
| 67 | 0x20000390 | 20 | 0.02 | Data | .data | timers.o |
| 68 | 0x20000468 | 20 | 0.02 | Data | .data | ui_net_sink.o |
| 69 | 0x200003D0 | 18 | 0.02 | Data | .data | ui_menu.o |
| 67 | 0x20000394 | 20 | 0.02 | Data | .data | timers.o |
| 68 | 0x2000046C | 20 | 0.02 | Data | .data | ui_net_sink.o |
| 69 | 0x200003D4 | 18 | 0.02 | Data | .data | ui_menu.o |
| 70 | 0x200000FC | 16 | 0.02 | Data | .data | iec104_serv.o |
| 71 | 0x20000118 | 16 | 0.02 | Data | .data | iec104_pts.o |
| 72 | 0x20000214 | 16 | 0.02 | Data | .data | net_events.o |
| 73 | 0x200002A0 | 16 | 0.02 | Data | .data | nand_ftl.o |
| 74 | 0x200003EC | 16 | 0.02 | Data | .data | ui_content_page.o |
| 75 | 0x200000D4 | 12 | 0.01 | Data | .data | default_task.o |
| 76 | 0x200001B4 | 12 | 0.01 | Data | .data | stm32f4xx_hal.o |
| 77 | 0x200001E4 | 12 | 0.01 | Data | .data | tpafe5160.o |
| 78 | 0x200001F0 | 12 | 0.01 | Data | .data | net_socket.o |
| 79 | 0x200003A8 | 12 | 0.01 | Data | .data | port.o |
| 80 | 0x200003C4 | 12 | 0.01 | Data | .data | ui_port.o |
| 81 | 0x200003FC | 12 | 0.01 | Data | .data | ui_page_password.o |
| 82 | 0x200005C0 | 12 | 0.01 | Zero | .bss | iwdg.o |
| 72 | 0x200001F0 | 16 | 0.02 | Data | .data | net_socket.o |
| 73 | 0x20000218 | 16 | 0.02 | Data | .data | net_events.o |
| 74 | 0x200002A4 | 16 | 0.02 | Data | .data | nand_ftl.o |
| 75 | 0x200003F0 | 16 | 0.02 | Data | .data | ui_content_page.o |
| 76 | 0x200000D4 | 12 | 0.01 | Data | .data | default_task.o |
| 77 | 0x200001B4 | 12 | 0.01 | Data | .data | stm32f4xx_hal.o |
| 78 | 0x200001E4 | 12 | 0.01 | Data | .data | tpafe5160.o |
| 79 | 0x200003AC | 12 | 0.01 | Data | .data | port.o |
| 80 | 0x200003C8 | 12 | 0.01 | Data | .data | ui_port.o |
| 81 | 0x20000400 | 12 | 0.01 | Data | .data | ui_page_password.o |
| 82 | 0x200005C4 | 12 | 0.01 | Zero | .bss | iwdg.o |
| 83 | 0x200001C4 | 10 | 0.01 | Data | .data | ch395f.o |
| 84 | 0x20000094 | 8 | 0.01 | Data | .data | sys_clock.o |
| 85 | 0x200000C8 | 8 | 0.01 | Data | .data | task_prof.o |
| 86 | 0x2000010C | 8 | 0.01 | Data | .data | protect_task.o |
| 87 | 0x20000144 | 8 | 0.01 | Data | .data | sample_ring.o |
| 88 | 0x200003B4 | 8 | 0.01 | Data | .data | ff.o |
| 89 | 0x200003BC | 8 | 0.01 | Data | .data | ffsystem.o |
| 90 | 0x200003E4 | 8 | 0.01 | Data | .data | ui_menu_view.o |
| 88 | 0x200003B8 | 8 | 0.01 | Data | .data | ff.o |
| 89 | 0x200003C0 | 8 | 0.01 | Data | .data | ffsystem.o |
| 90 | 0x200003E8 | 8 | 0.01 | Data | .data | ui_menu_view.o |
| 91 | 0x2000002C | 4 | 0.00 | Data | .data | app_main.o |
| 92 | 0x200000D0 | 4 | 0.00 | Data | .data | vol_lock.o |
| 93 | 0x200000E0 | 4 | 0.00 | Data | .data | net_task.o |
| 94 | 0x200001C0 | 4 | 0.00 | Data | .data | system_stm32f4xx.o |
| 95 | 0x20000224 | 4 | 0.00 | Data | .data | net_pending.o |
| 96 | 0x20000350 | 4 | 0.00 | Data | .data | lftpd_io.o |
| 97 | 0x200003A4 | 4 | 0.00 | Data | .data | cmsis_os2.o |
| 98 | 0x2000047C | 4 | 0.00 | Data | .data | mc_w.l(errno.o) |
| 95 | 0x20000228 | 4 | 0.00 | Data | .data | net_pending.o |
| 96 | 0x20000354 | 4 | 0.00 | Data | .data | lftpd_io.o |
| 97 | 0x200003A8 | 4 | 0.00 | Data | .data | cmsis_os2.o |
| 98 | 0x20000480 | 4 | 0.00 | Data | .data | mc_w.l(errno.o) |
| 99 | 0x2000014C | 2 | 0.00 | Data | .data | phasor.o |
| 100 | 0x20000408 | 2 | 0.00 | Data | .data | ui_page_net_cfg.o |
| 100 | 0x2000040C | 2 | 0.00 | Data | .data | ui_page_net_cfg.o |
| 101 | 0x20000198 | 1 | 0.00 | Data | .data | prot_elm.o |
| | | **75,239** | **73.48** | | | **Total** |
| | | **75,243** | **73.48** | | | **Total** |
## 4. Image Component Sizes(RW + ZI > 0,按大小降序)
@@ -158,7 +158,7 @@
| 22 | usart.o | 884 | 0 | 0 | 552 | 552 |
| 23 | freq.o | 764 | 8 | 24 | 480 | 504 |
| 24 | lv_init.o | 156 | 0 | 0 | 492 | 492 |
| 25 | net_socket.o | 4,916 | 443 | 12 | 416 | 428 |
| 25 | net_socket.o | 4,944 | 443 | 16 | 416 | 432 |
| 26 | net_pending.o | 1,400 | 0 | 4 | 416 | 420 |
| 27 | task_prof.o | 638 | 185 | 8 | 384 | 392 |
| 28 | prot_set.o | 844 | 640 | 24 | 320 | 344 |
@@ -171,7 +171,7 @@
| 35 | ui_menu_view.o | 2,034 | 16 | 8 | 152 | 160 |
| 36 | net_listener.o | 948 | 207 | 24 | 128 | 152 |
| 37 | adc_input.o | 592 | 27 | 28 | 84 | 112 |
| 38 | freertos.o | 712 | 592 | 44 | 65 | 109 |
| 38 | freertos.o | 716 | 592 | 44 | 65 | 109 |
| 39 | prot_elm.o | 708 | 227 | 1 | 108 | 109 |
| 40 | i2c.o | 168 | 0 | 0 | 84 | 84 |
| 41 | ftp_cfg.o | 152 | 225 | 83 | 0 | 83 |
@@ -187,8 +187,8 @@
| 51 | net_cfg.o | 832 | 103 | 36 | 0 | 36 |
| 52 | protect_task.o | 840 | 68 | 8 | 24 | 32 |
| 53 | ui_standby.o | 1,208 | 67 | 32 | 0 | 32 |
| 54 | (incl. Padding) | 284 | 96 | 16 | 9 | 25 |
| 55 | adc_task.o | 1,520 | 234 | 24 | 0 | 24 |
| 54 | adc_task.o | 1,520 | 234 | 24 | 0 | 24 |
| 55 | (incl. Padding) | 284 | 96 | 16 | 5 | 21 |
| 56 | ui_menu.o | 760 | 137 | 18 | 0 | 18 |
| 57 | ui_content_page.o | 1,664 | 81 | 16 | 0 | 16 |
| 58 | iwdg.o | 28 | 0 | 0 | 12 | 12 |
@@ -204,7 +204,7 @@
| 68 | vol_lock.o | 92 | 0 | 4 | 0 | 4 |
| 69 | errno.o | 20 | 0 | 4 | 0 | 4 |
| 70 | ui_page_net_cfg.o | 1,004 | 105 | 2 | 0 | 2 |
| | **All .o files** | **213,204** | **18,580** | **1,184** | **131,504** | **132,688** |
| | **All .o files** | **213,236** | **18,580** | **1,188** | **131,500** | **132,688** |
## 5. Flash (Code + RO Data) Top-30(按大小降序)
@@ -213,7 +213,7 @@
| 1 | ff.o | 7,962 | 282 | 8,244 |
| 2 | cfg_file.o | 5,970 | 810 | 6,780 |
| 3 | lftpd.o | 6,108 | 509 | 6,617 |
| 4 | net_socket.o | 4,916 | 443 | 5,359 |
| 4 | net_socket.o | 4,944 | 443 | 5,387 |
| 5 | lv_indev.o | 4,928 | 0 | 4,928 |
| 6 | ch395f.o | 3,978 | 603 | 4,581 |
| 7 | ui_font_cn_12.o | 0 | 4,545 | 4,545 |
@@ -240,6 +240,6 @@
| 28 | printfa.o | 2,312 | 0 | 2,312 |
| 29 | stm32f4xx_hal_i2c.o | 2,294 | 0 | 2,294 |
| 30 | lv_display.o | 2,284 | 0 | 2,284 |
| | **All .o files** | **213,204** | **18,580** | **231,784** |
| | **All .o files** | **213,236** | **18,580** | **231,816** |
> 自洽校验:per-file 213,204/18,580/1,184/131,504 vs Grand Totals 213,204/18,580/1,184/131,504(CodeΔ=+0 / ROΔ=+0 / RWΔ=+0 / ZIΔ=+0;精确一致(含 '('incl. Generated)'-'(incl. Padding)' 台账行))→ **PASS**
> 自洽校验:per-file 213,236/18,580/1,188/131,500 vs Grand Totals 213,236/18,580/1,188/131,500(CodeΔ=+0 / ROΔ=+0 / RWΔ=+0 / ZIΔ=+0;精确一致(含 '('incl. Generated)'-'(incl. Padding)' 台账行))→ **PASS**
@@ -1,7 +1,7 @@
# Stack budget report
- Source: `MDK-ARM\STM32F407-Demo\STM32F407-Demo.htm` (Keil static call graph)
- Linker run: Thu Oct 22 19:12:02 2026
- Linker run: Thu Oct 22 19:53:08 2026
- Global maximum stack usage: **3024 B** (any call tree)
- Runtime watermark: 8 task(s) from 串口采集日志 `.dsh\skills\serial-assistant\scripts\state\serial.log`
@@ -11,13 +11,13 @@ Rule: `margin = cfg - max(static_max_depth, runtime_peak)` must be >= max(1024 B
|---|---|---|---|---|---|---|---|---|
| defaultTask | `StartDefaultTask` | 5120 | 3024 | 2152 | 3024 | 2096 | 40% | PASS |
| netTask | `StartNetTask` | 3840 | 1912 | 1116 | 1912 | 1928 | 50% | PASS |
| ftpTask | `StartFtpTask` | 4096 | 1456 | 764 | 1456 | 2640 | 64% | PASS |
| ftpTask | `StartFtpTask` | 4096 | 1456 | 1404 | 1456 | 2640 | 64% | PASS |
| uiTask | `StartUiTask` | 16384 | 1336 | 4052 | 4052 | 12332 | 75% | PASS |
| testTask | `start_test_task` | 8192 | 736 | - | 736 | 7456 | 91% | PASS |
| timeSyncTask | `time_sync_task` | 2560 | 1264 | 616 | 1264 | 1296 | 50% | PASS |
| timeSyncTask | `time_sync_task` | 2560 | 1264 | 648 | 1264 | 1296 | 50% | PASS |
| adcTask | `adc_task_func` | 2560 | 1320 | 952 | 1320 | 1240 | 48% | PASS |
| iec104Task | `iec104_serv_task` | 2560 | 1456 | 540 | 1456 | 1104 | 43% | PASS |
| protectTask | `protect_task` | 2048 | 872 | 624 | 872 | 1176 | 57% | PASS |
| protectTask | `protect_task` | 2048 | 872 | 828 | 872 | 1176 | 57% | PASS |
`Static max` = armlink worst-case call-tree depth; `Runtime peak` = measured high-water mark (boot + whatever workload ran before the sample); `Worst` = max of the two, which is what the verdict is computed from.
@@ -504,7 +504,7 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级
| 资源 | 已用 | 总量 | 利用率 | 余量 | 红线说明 |
|---|---|---|---|---|---|
| Flash(`ER_IROM1` = Code + RO) | 231,784 B(226.4 KB) | 1 MB | 22.1% | ≈804 KB | **充裕**:产品需求无 OTA / 双镜像预算,Flash 不是卡点;死代码裁剪簇已收口 → `docs/问题记录/项目审查与优化建议报告.md` §5.4 |
| Flash(`ER_IROM1` = Code + RO) | 231,816 B(226.4 KB) | 1 MB | 22.1% | ≈804 KB | **充裕**:产品需求无 OTA / 双镜像预算,Flash 不是卡点;死代码裁剪簇已收口 → `docs/问题记录/项目审查与优化建议报告.md` §5.4 |
| 主 SRAM1(静态区;FreeRTOS 堆已迁 CCM) | 75,264 B(73.5 KB) | 128 KB | 57.4% | 55,808 B | 已不紧张——2026-10-11 堆迁 CCM 与 2026-10-15 `LV_MEM_SIZE` 40→16 KB 两步的结果 |
| CCM(`RW_CCM` 段) | 57,376 B(56.0 KB) | 65,280 B | **87.9%** | **7,904 B** | **当前真正的红线**:加任务 / 抬栈 / 加堆会先在这里撞墙;`mem-budget` 钩子在 92% 拦提交 |
@@ -49,7 +49,12 @@
| 内存 RAM | N-14 🟡(N-22) | FTL 单页写回缓存无空闲/掉电强制 flush(整页写与换页已 flush,`f_close` 经 `CTRL_SYNC` 已落盘) | 用户裁定 2026-10-22 暂不做;残余窗口只是"单条记录" |
| Flash | **F-5 🟡 观察项**(N-28) | uvprojx 201 个 LVGL `.c` 里 **127 个空 TU**;增量构建 4~5 s、CI 不跑 `@build` | 有实测全量耗时痛点再做,用 `<IncludeInBuild>` |
| 结构 | **S-1 已止住恶化**(2026-10-22 上门禁) | 不是"命名错位",是真实的 **BSP→App 反向 include**,精确口径 **8 个文件 9 处**(上一版写"7 文件 15 处"也不准,已按 `check_layer_deps.py` 判定重算):`cfg_file.h`×2(NETCFG)、`vol_lock.h`×1(lftpd_io)、`sys_log.h`×3(UI 两处 + `ui_w_records.h`);`console_log.h` / `sys_clock.h` / `sha256.h` 三个横切叶子头已**显式豁免**。**运行时的属主纪律本来就没破**(UI 只投递 `net_cfg_save_request()`,写盘在 defaultTask),要修的只是静态方向 | **门禁已落地**(`layer-deps` + `scripts/check_layer_deps.py`:存量 6 条基线只减不增、新增当场 FAIL,落地时做过故意违规自证)。剩下的才是反转:把 `cfg_file_*` 直接调用换成注入的 ops(NETCFG 已有 `net_cfg_set_save_req_cb` 先例);**目录搬迁仍暂缓**(远程 CI 不跑 `@build`,兜底未成立) |
| 结构 | **S-2 只剩 1 处**(24 处手写已消 23) | 今天已消 23 处:2 处与 `Inc/spi.h`/`Inc/i2c.h` 重复(GD5F/SD2506)+ 19 处任务句柄与属性(新建 `App/task/task_handles.h`)+ 1 处 `main.c` 函数内 `g_rcc_csr_latched`(改由 `App/app/app_main.h` 声明)+ 1 处 `ch395f.c:177`(**改为契约转调**:GD5F 的完成标志收为文件内 `static`,导出 `gd5f_spi1_notify_done()` / `gd5f_spi1_notify_error()`,CH395F 那个"HAL 全局唯一回调"的 SPI1 分支只转调、不再直接写它的变量;`HAL_SPI_AbortCpltCallback` 仍无人实现 → 另列观察)。**只剩 `net_socket.c:77` 的 `netMsgQueueHandle`**。**两类不算债**:`stm32f4xx_it.c:241-256` 是 CubeMX「External variables」生成块(删了会被写回来);`:183/195/207/220` 是 `__asm` Handler 里的汇编标签引用(ARMCC `__asm` 取不到 C 数据符号,**合法例外**) | 剩下一步:`netMsgQueueHandle` 收进 net_socket 内部 + 提供投递 API |
| ~~结构 S-2~~ ✅ **已闭环销项 2026-10-22** | 该修的 24 处手写跨模块裸 `extern` **全部消完**:2 处与 `Inc/spi.h`/`Inc/i2c.h` 重复 → 改 include;19 处任务句柄与属性 → `App/task/task_handles.h`;1 处 `main.c` 函数内 `g_rcc_csr_latched` → `App/app/app_main.h`;
`ch395f.c:177` 的 `g_spi1_dma_done` → 标志收回 GD5F 内部 `static`,改由 `gd5f_spi1_notify_done()` / `notify_error()` 契约转调;最后一处 `net_socket.c:77` 的
`netMsgQueueHandle` → 句柄改为 net_socket 私有 `static s_net_msg_queue`,由 `Src/freertos.c` 的 `USER CODE BEGIN RTOS_QUEUES` 区在队列创建后立刻
`net_msg_queue_adopt()` 绑定(创建点不能外移——`osKernelInitialize()` 之前的创建类 API 会杀死启动;**故意不新建第二个队列**:那会白占 CCM 里 8×`net_msg_t`
的堆空间,而 CCM 正是当前红线)。**两类从来不算债**:`stm32f4xx_it.c:241-256` 是 CubeMX「External variables」生成块;`:183/195/207/220` 是 `__asm` Handler
里的汇编标签引用(ARMCC `__asm` 取不到 C 数据符号)。 | 无(后续由 `layer-deps` 与 `cubemx-survival` 两条门禁守着不回退:新增 `net-msgq-adopt` 存活项) |
| 驱动规范 | S-5 ❌ | `bsp_err_t` 至今只出现在本报告里(无统一错误码/超时/重试约定) | 定义后进 `docs/代码规范/` |
| 网络 | N-09 / PHY ❌(N-25) | `NET_MAX_SOCKETS` 仍为 8(与单连接复用语义不符);PHY 强制 100M 无自协商回退;PASV 每次新建监听 | 见 §4.2;随 N-25 一并处置 |
| 存储 | N-15 🟡(N-25) | `nand_ftl.o` 静态 6,216 B——三块 2 KB 级页缓冲并存未合并 | 与 R-3 同批评估 |
@@ -88,7 +93,7 @@ git ls-files -z | xargs -0 stat -c '%s'
| 名词 | 口径 |
|---|---|
| Flash 占用 | `Code + RO-data` = `ER_IROM1` = **231,784 B(22.1%)**;`ROM 合计` 再加 `RW` 初始化表 = 232,968 B(22.2%) |
| Flash 占用 | `Code + RO-data` = `ER_IROM1` = **231,816 B(22.1%)**;`ROM 合计` 再加 `RW` 初始化表 = 233,004 B(22.2%) |
| SRAM 占用 | `RW_IRAM1`(DMA 可达区)与 `RW_CCM`(仅 CPU)分开计,二者不可互换(规则 R2/R3) |
| 最坏栈 | `max(armlink 静态调用图深度, 真机 [STACK] 高水位)`;判定线 `余量 ≥ max(1024 B ISR, 配置×30%)` |
| 编译单元 | uvprojx 的 `<FilePath>` 计数(今日 **326 个 `.c`**,其中 LVGL 201);"自研 `.c`" 另按目录口径 114 个 |
@@ -225,8 +230,8 @@ defaultTask 单属主;原子写经卷锁;旧档迁移已删除。**仍列为
| 指标 | 2026-10-22 | 2026-10-15 | 说明 |
|---|---|---|---|
| `Code` | 213,204 B | 213,520 B | F-6 收口 −332 B;同日 SPI 回调归属纠正 +16 B |
| `ER_IROM1`(Code+RO) | **231,784 B / 22.1%** | 232,280 B / 22.2% | 余 ≈804 KB |
| `Code` | 213,236 B | 213,520 B | 当日累计:F-6 −332 B、SPI 回调归属 +16 B、消息队列收口 +32 B |
| `ER_IROM1`(Code+RO) | **231,816 B / 22.1%** | 232,280 B / 22.2% | 余 ≈804 KB |
| `RW_IRAM1` | **75,264 B / 57.4%**(余 55,808) | 73,568 B / 56.1% | 增量来自 B5/B8 功能码 |
| `RW_CCM` | **57,376 B / 87.9%**(余 7,904) | 57,376 B / 87.9% | **当前唯一红线** |
| FreeRTOS 堆 | 56 KB(57,344 B)@CCM;实测 `free=15,800` / `min_ever=8,464` | 同 | 2026-10-22 真机 |
@@ -266,7 +271,7 @@ defaultTask 单属主;原子写经卷锁;旧档迁移已删除。**仍列为
| **F-6** 双精度软浮点 | ≈1 KB | **归因错**:全库 0 处 `%f`;剩余 `dadd/dmul/ddiv/depilogue/dfixul` 1,018 B 锁在 MicroLIB `printfa.o` 的 `_printf_core → _fp_digits`,只要用 `snprintf` 就删不掉。但**根因侧确有可修点**:`App/algo/prot_set.h` 两个 Q10 宏写成 `double` | ✅ **已落地 2026-10-22**:改单精度 → `@build` −332 B、5 个 helper(300 B)消失;数值逐位等价(穷举 42 个字面量 + int32 全域 ÷1024 往返 4.49×10⁶ 例零差异);真机 `@test` PASS |
**当前可回收 Flash = 0 B**(F-4/F-6 已定论,图片链同理不打补丁)。LVGL 仍占镜像 **37.8%**
(87,706 / 231,784 B)——这是"用 LVGL 画单色菜单"的结构性代价,F-1/F-2/F-3 已省掉 64,576 B。
(87,706 / 231,816 B)——这是"用 LVGL 画单色菜单"的结构性代价,F-1/F-2/F-3 已省掉 64,576 B。
### 5.5 内存治理长效机制(常开,不受暂缓影响)
@@ -374,7 +379,8 @@ W6 簇按 U4 → U1 → U3 → U2 的顺序执行完毕(U2 停在"够用即止
| **D-1** | 外部资料与工程文档同仓同树 | ❌ 暂不处理 | 本文 §3.3、登记簿 N-29 |
| D-2 ~ D-7 | 文档治理条目(链接/同源/编号/BOM 等) | ✅ 多数已制度化为钩子 | 本文 §3.2、`../文档规范.md` |
| D-9 | 文档面残余观察 | 🟡 观察 | 本节即定义位 |
| **S-1 / S-2** | 分层反向依赖 / 跨模块裸 `extern` | 🟡 半办(2026-10-22:24 处手写裸 extern 已消 23 处,只剩 `net_socket.c:77`;反向 include 8 文件 9 处已上门禁、6 条基线待还) | 本文 §0.4、登记簿 C5 |
| **S-1** | 分层反向依赖(BSP include App 的头) | 🟡 已止住恶化(存量 6 条基线待还,新增被 `layer-deps` 拦) | 本文 §0.4、登记簿 C5 |
| **S-2** | 跨模块裸 `extern` | ✅ **已闭环 2026-10-22**(24 处手写全消;两类本就不算债见 §0.4) | 本文变更记录 2026-10-22 三行;契约见 `App/task/task_handles.h`、`gd5f_spi1_notify_*`、`net_msg_queue_adopt` |
| **S-4** | `app_cfg.h` 未接线占位开关 | ✅ **已闭环 2026-10-22**(4 个零消费点宏删除) | `App/app/app_cfg.h` 修改记录 v1.2;口径同步见 `../环境与部署/项目部署环境要求.md` §3.2/§3.5、`../产品需求/产品需求设计文档.md`、`../任务规划/排期详述.md` C5 |
| **S-3** | `.ioc` 侧 USART1 配置 | ❌ 在策 | 登记簿 S-3 |
| **S-5** | 统一 `bsp_err_t` 错误码约定 | ❌ 未做 | 本文 §0.4、`docs/代码规范/`(待建) |
@@ -409,6 +415,33 @@ W6 簇按 U4 → U1 → U3 → U2 的顺序执行完毕(U2 停在"够用即止
**改判的三条旧结论**:① §6 的 U1/U3/U4 原写「❌ 未建」,实际已落地(`ui_tokens.h` 69 行、`ui_page_registry.c` 描述符注册表、`ui-golden`+`font-charset` 两枚钩子);U2 只有 `ui_w_records` 一个组件;"27 页未落地"实为 7 页。② "新增一页 ≤30 行"目标**未达**(最省 40 行),如实记为未达项。③ §0.4 与登记簿已漂开 → 本版把待办清单降级为**快照 + 指向登记簿**,权威只留一处。
**刻意保留的三层**(删了会出事):§9 **编号族登记处**——本文是 `id_registry.json` 里 `N-RPT`/`D-RPT`/`S-RPT`/`R-RPT`(游标 R-9)/`F-RPT`/`U-RPT`(游标 U5) 六族的属主登记处,且外部存在「报告 N-14」「报告 F-4/F-5/F-6」「报告 D-1」「报告 R-2/R-3」式紧邻引用与 `check_dangling`,删定义位即触发编号门禁;§1.2/§1.3 方法与口径(数字可重跑);文末**变更记录 + 已销项去处表**原样冻结保留(52 行)。被外部点名的锚点(`§0.3`/`§3.1`/`§4.1`/`§4.2`/`§4.3`/`§5.3`×9/`§5.4`/`§5.5`×4/`§6.2`/`§6.3`/`§6.5`)逐个保留,**68 处入站引用零改动**。
**门禁**:`check_doc_links.py --all --sections-strict` → 146 文档 0 问题(章节引用 2,499、可判定 1,483);`check_ids.py --strict` 增量拦截通过、**存量债 650 → 641(−9)**、可判定比例 82.98% → **82.79%**(仍高于基线 82.6%,但缓冲从 0.38pp 缩到 0.19pp——删掉的那批引用 99% 是可判定的,属预期副作用);`mem-numbers` / `ram_baseline --gate` / `task-table` / `cubemx-survival` 全 0。字节卫生:BOM 无 / CR 0 / U+FFFD 0 / 无行尾空格 / LF 结尾。 |
| **2026-10-22** | **S-2 收尾:`netMsgQueueHandle` 收进 net_socket 内部——该族 24 处手写裸 extern 全部清零** | 最后一步。队列对象仍由 CubeMX 在
`MX_FREERTOS_Init()` 创建(**创建点不可外移**:`osKernelInitialize()` 之前的任何创建类 API 会杀死启动,
docs/架构设计/项目启动顺序管理.md),改为创建后立刻在 `Src/freertos.c` 的 `USER CODE BEGIN RTOS_QUEUES` 区
调用 `net_msg_queue_adopt(netMsgQueueHandle)` 把句柄交给本模块;net_socket 内改为 `static s_net_msg_queue`
(21 处引用改名),BSP 对该全局变量的裸 `extern` 消失,`netMsgQueueHandle` 现在只出现在生成文件自己的两处。 |
| | **两个刻意的设计决定**:① **不新建第二个队列**——那会白占 CCM 堆里 8 × `net_msg_t` 的空间,而 CCM 是当下
87.9% 的红线;所以选"创建后绑定"而不是"自建队列 + 删 .ioc 里的队列"(后者还要 CubeMX 重生成,属 Ask-first)。
② `adopt()` **拒绝重复绑定并保留首次句柄**——真出现两处绑定时,静默换句柄会让已入队的请求留在旧队列里永不处理,
拒掉第二个反而更容易暴露。绑定前的判空是真实防线:丢这一行的后果是"所有 net_* 请求被丢弃、网络全线静默不通",
不是崩溃。 |
| | **防回退**:`check_cubemx_survival.py` 新增存活项 `net-msgq-adopt`(region `RTOS_QUEUES`,must_contain
`net_msg_queue_adopt`),易失清单 **29 → 30 项全部到位**;基线已重建。 |
| | **体量**:`Code` 213,204 → **213,236 B(+32)**、`ER_IROM1` **231,816 B(22.1%)**;`RW +4 / ZI −4` →
`RW_IRAM1` 恒 **75,264 B(57.4%)**、`RW_CCM` 恒 **57,376 B(87.9%)**、`RW+ZI` 总量 132,688 B **不变**。 |
| | **验证**:`@build` 0 错 0 警告;`@test` PASS(624 ms 到 `net init: OK`、i104 已监听、无 `[ERR]`/Fault、
`heap free=15800 min_ever=8464` 逐项不变——证明没有多占一个队列);**另做真机 FTP 控制通道往返**:220 →
`USER admin` 331 → `PASS admin` **230** → `PWD` 257 → `TYPE I` 200 → `QUIT` 221,每条命令都是一次过队列的
net_recv/net_send → 绑定路径在真机走通;`.map` 里 `freertos.o(MX_FREERTOS_Init) refers to
net_socket.o(i.net_msg_queue_adopt)` 证明镜像确实含该行。 |
| | **顺带揪出一条测试工具漂移(未修,等定夺)**:`test/host/ftp_up_dl_test.py:123/126` 仍写死
`USER anonymous` / `PASS test@test.com`,而设备自 N-19(2026-10-11)起按 `/config.ini [ftp]` 校验
admin/admin(SHA-256 `pwd_hash`)→ 该脚本**必然登录失败**;它是手工工具、不在任何 pre-commit 钩子里,所以
一直没人发现,而 `../测试说明/FTP_Test_Guide.md` 把它列为推荐入口。建议:加 `--user/--password`
(默认 admin/admin),并顺手把 `ftp_speed_test.py` 一起核。 |
| | 数字联动照做:两份 `data/` 快照重跑、`ram_baseline --update/--write`、`check_mem_numbers --write`、FLASH 与
任务栈两张配图重算重生成(逐文本复查越界 = 0)、本文 §1.3/§5.1/§5.4 与部署文档 §3.3 同步;§0.4 的 S-2 行按
「完成即销项」改写、§9 拆出 S-2 行标 ✅。 |
| **2026-10-22** | **S-1 只做「防扩大」那一半:新增 `layer-deps` 分层方向门禁**(推荐清单第 5 步拆分执行,钩子 37 → **38**) | 上一轮的结论是「反转暂缓、门禁现在就该上」,这次照做。
为什么门禁比搬迁值钱:AGENTS 与分层图早就写着「六层单向依赖」,可从来没有机械检查——于是同一件事的记载从 2026-09 的
「NETCFG 一处」漂到今天的「8 文件 9 处」,全靠人读代码才发现。边界的静默腐蚀只能靠门禁止住。 |
+10
View File
@@ -245,6 +245,16 @@ CHECKS = [
no_baseline=True, # 见下方说明:本文件每次 @build 后被 Keil 改写
hint="task_watchdog.c 须挂在 MDK 工程 App 组;CubeMX 重生成可能重建 .uvprojx。",
),
dict(
id="net-msgq-adopt",
kind="protected",
path="Src/freertos.c",
region="RTOS_QUEUES",
must_contain=["net_msg_queue_adopt"],
hint="消息队列句柄的唯一使用者是 net_socket,创建后必须在 USER CODE BEGIN RTOS_QUEUES 区"
"绑定给它(替代此前 BSP 对该全局变量的裸 extern)。丢了这一行,net_socket 的句柄"
"恒为 NULL → 所有 net_* 请求被判空丢弃,网络全线静默不通(无崩溃、无报错日志)。",
),
dict(
id="reset-cause-latch",
kind="protected",
+1 -1
View File
@@ -4,4 +4,4 @@ date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi
2026-10-14 212296 18740 1112 154456 231036 22.0 98144 74.9 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=40960;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;default_task.o=2736;sys_log_mcu.o=1924
2026-10-15 213540 18740 1136 131520 232280 22.2 75232 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
2026-10-20 213356 18580 1184 131480 231936 22.1 75240 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
2026-10-22 213204 18580 1184 131504 231784 22.1 75264 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
2026-10-22 213236 18580 1188 131500 231816 22.1 75264 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
1 date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi
4 2026-10-14 212296 18740 1112 154456 231036 22.0 98144 74.9 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=40960;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;default_task.o=2736;sys_log_mcu.o=1924
5 2026-10-15 213540 18740 1136 131520 232280 22.2 75232 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
6 2026-10-20 213356 18580 1184 131480 231936 22.1 75240 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
7 2026-10-22 213204 213236 18580 1184 1188 131504 131500 231784 231816 22.1 75264 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
+8 -8
View File
@@ -47,11 +47,11 @@ RAM2_CATEGORIES = [
# ── Flash breakdown (1MB = 1,048,576 B; 2026-10-22 @build) ──────────────────
FLASH_TOTAL = 1048576
FLASH_CODE = 213204
FLASH_CODE = 213236
FLASH_RO = 18580
FLASH_RW = 1184
FLASH_RW = 1188
FLASH_USED = FLASH_CODE + FLASH_RO + FLASH_RW # ROM 合计(含 RW 初始化表)
FLASH_IROM = FLASH_CODE + FLASH_RO # ER_IROM1 区用量 = 231,784 B(22.1%)
FLASH_IROM = FLASH_CODE + FLASH_RO # ER_IROM1 区用量 = 231,816 B(22.1%)
FLASH_FREE = FLASH_TOTAL - FLASH_USED
FLASH_CATEGORIES = [
@@ -61,7 +61,7 @@ FLASH_CATEGORIES = [
("Flash 空闲", FLASH_FREE, "#E0E0E0"),
]
# Flash Code+RO 分布(= ER_IROM1 231,784 B;2026-10-22 按 .map 对象表逐对象归类,
# Flash Code+RO 分布(= ER_IROM1 231,816 B;2026-10-22 按 .map 对象表逐对象归类,
# 口径同 data/ram_report_20261022.md;"其他"含链接器填充)
FLASH_CODE_SUB = [
("LVGL 库", 87706, "#4CAF50"),
@@ -73,7 +73,7 @@ FLASH_CODE_SUB = [
("FatFS", 8468, "#9C27B0"),
("C 库 (microlib)", 5486, "#795548"),
("startup", 468, "#B0BEC5"),
("其他 (长尾)", 7432, "#E0E0E0"), # remainder
("其他 (长尾)", 7464, "#E0E0E0"), # remainder
]
# ── Task stack budgets (2026-10-22 @build + 同日真机 [STACK] 实测; data/stack_report_20261022.md) ──
@@ -83,13 +83,13 @@ FLASH_CODE_SUB = [
TASK_STACKS = [
("defaultTask", 5120, "Normal", 3024, 2152, 2096, 40, "PASS", "FatFS 挂载/探针 + 配置引擎 + syslog + LED"),
("netTask", 3840, "Normal", 1912, 1116, 1928, 50, "PASS", "CH395F 轮询、消息处理"),
("ftpTask", 4096, "Normal", 1456, 764, 2640, 64, "PASS", "lftpd FTP 服务(大缓冲已静态化)"),
("ftpTask", 4096, "Normal", 1456, 1404, 2640, 64, "PASS", "lftpd FTP 服务(大缓冲已静态化)"),
("uiTask", 16384, "BelowNormal", 4052, 4052, 12332, 75, "PASS", "LVGL UI 主循环 + 远程显示推流"),
("testTask", 8192, "BelowNormal", 736, 736, 7456, 91, "PASS", "测试套件(产品构建不创建,取静态最坏链)"),
("timeSyncTask", 2560, "Normal", 1264, 616, 1296, 50, "PASS", "TCP 时间同步(8888)"),
("timeSyncTask", 2560, "Normal", 1264, 648, 1296, 50, "PASS", "TCP 时间同步(8888)"),
("adcTask", 2560, "AboveNormal", 1320, 952, 1240, 48, "PASS", "1 kHz 节拍消费者(L1 采集,纯取数)"),
("iec104Task", 2560, "Normal", 1456, 540, 1104, 43, "PASS", "IEC 60870-5-104 上行(2404)"),
("protectTask", 2048, "Normal", 872, 624, 1176, 57, "PASS", "20 ms 保护判据 + 闭锁 + 定值校验和巡检"),
("protectTask", 2048, "Normal", 872, 828, 1176, 57, "PASS", "20 ms 保护判据 + 闭锁 + 定值校验和巡检"),
]
KERNEL_STACKS = [("idle", 512), ("timer", 1024)] # 128/256 words(未实测)