栈整改不抬栈:删旧档迁移、FIL静态化、日志行缓冲按模块收紧、钩子脱离HAL,defaultTask链5312→2776B

This commit is contained in:
2026-10-10 10:17:00 +08:00
parent 5c978465c9
commit 0779d3a075
54 changed files with 3203 additions and 2770 deletions
+28 -11
View File
@@ -94,15 +94,24 @@ static int hook_ptr_ok(const void *p)
* defaultTask 1024 words:扛 mount+mkfs+FAT 探针+cfg 加载+syslog 写+配置引擎
* (全深层 FatFS I/O)。原 512,2KB 实测峰值溢出——开启
* configCHECK_FOR_STACK_OVERFLOW=2 后被钩子抓到(2026-09-21)。
* netTask 960 words:静态最坏链 2664 B(发送停滞→断连→重监听→SPI 故障→日志尾,
* 真实直调链,日志主导:链上 5 帧各含 192 B __con_line + 尾部 ~696 B);3840 B
* 配置余量 1176 B(30.6%),过 stack_report 规则。运行时水位仅 ~1.1 KB(错误尾未
* 2026-10-10 栈整改(**未抬栈**,靠削链达标):静态最坏链 5312 → 2776 B、
* 实测峰值 3392 → 2152 B(余 1944 B / 47%)。四个杠杆:① 删旧档 NCFG 迁移
* (net_cfg_legacy,−600 B 链);② 6 处局部 `FIL` 改函数级 static(FF_FS_TINY=0
* → 单个 FIL = 528 B 栈);③ 日志行缓冲按模块收紧 `DBG_LINE_BUF_MAX 128`
* + 时间戳缓冲并入行缓冲(每个日志调用点原内联 192+32 B);④ 断言/故障钩子
* 脱离 HAL 发送回退 + 缓冲静态化(configASSERT 在 FreeRTOS 内部可达 →
* 钩子在**每个**任务的最坏链尾)。详见 docs/内存管理/RAM使用分析与优化方案.md
* netTask 960 words:静态最坏链 1872 B(2026-10-10 整改后;整改前 2664 B:
* 发送停滞→断连→重监听→SPI 故障→日志尾,日志主导);3840 B 配置余量 1968 B
* (51%),过 stack_report 规则。运行时水位仅 ~0.9 KB(错误尾未
* 触发,不可作依据)。曾试 net_drain_chip_rx scratch 静态化,实测仅省 16 B 栈
* (ARMCC 已叠放不重叠局部量)反增 256 B BSS,已回退——见 net_socket.c 注释。
* testTask 2048 words:存储套件 deep call chain + 局部缓冲,原 1024(4 KB)实测溢出
* (2026-09-20)。仅启用测试套件时创建。
* timeSyncTask 512 words:本区下方手工定义(不在 `.ioc` 的 Tasks01 里 → 重生成会丢,
* 靠审计 WARN 提示),只做读 RTC + 置就绪事件位,无深调用链。
* 靠审计 WARN 提示),建监听 → net_bind → CH395F → 日志尾。2026-10-10 整改后
* 静态最坏链 1024 B(整改前 1736 B)、实测峰值 616 B;⚠ 余量 1024 B **正好**
* 等于 ISR 底线 → 本任务链上再加任何调用(或新日志行)都必须先抬栈。
*/
/* 存储测试变量(g_storage_stats / s_perf_buf)已迁至 test/board/storage_test_task.c */
osThreadId_t timeSyncTaskHandle;
@@ -435,7 +444,10 @@ void vApplicationAssertFailed(const char *file, long line)
{
static const char msg_head[] = "\r\n[ERR] ASSERT FAILED ";
const char *p = file;
char num[16];
/* 缓冲一律 static(不放栈上):本钩子是"内核状态已不可信"的终点路径,打印完即
* 复位,不存在并发/重入;放栈上会让 armlink 把这 81 B 挂进每个任务的最坏链
* (configASSERT 在 FreeRTOS 内部可达 → 每条链尾都有本钩子) */
static char num[16];
int i;
/* 文件名只取末段(全路径太长且无信息量) */
@@ -449,8 +461,8 @@ void vApplicationAssertFailed(const char *file, long line)
}
/* 有界拷贝:上限 48 字符 */
{
static char name[49]; /* static 存储(见上),作用域收到本块 */
uint16_t len = 0u;
char name[49];
while ((len < 48u) && (p[len] != '\0')) {
name[len] = p[len];
len++;
@@ -471,21 +483,26 @@ void vApplicationAssertFailed(const char *file, long line)
if (line <= 0) {
num[i++] = '0';
} else {
char rev[16];
int n = 0;
int j;
while ((line > 0) && (n < 15)) {
rev[n++] = (char)('0' + (line % 10));
num[n++] = (char)('0' + (line % 10)); /* 先逆序填入 */
line /= 10;
}
while (n > 0) {
num[i++] = rev[--n];
for (j = 0; j < n / 2; j++) { /* 原地反转:省一个 16 B 缓冲 */
char t = num[j];
num[j] = num[n - 1 - j];
num[n - 1 - j] = t;
}
i = n;
}
dbg_console_write_raw(num, (unsigned)i);
dbg_console_write_raw(" (resetting)\r\n", 15u);
HAL_Delay(200); /* 等 UART 移位寄存器排空 */
/* 无需 HAL_Delay:dbg_console_write_raw → con_tx_bounded 已等到 TC(移位寄存器
* 排空)才返回;去掉 HAL_Delay 亦少一条 HAL 依赖(断言现场 tick 未必可信) */
NVIC_SystemReset();
}
/* USER CODE END Application */