fix(stack): N-33 抬栈收口 defaultTask/timeSyncTask 栈余量(2 FAIL -> 0 FAIL)

既有债收口(非新引入):B7 定值持久化把 defaultTask 静态最坏链推到
3016 B、timeSyncTask 推到 1264 B,两者跌破 stack_report 判据
(余量 >= max(1024 B ISR, 配置 x 30%))。本轮只抬栈,不动调用链。

前基线(stack_report,9 任务):
- defaultTask  cfg 4096 B / 静态 3016 B / 余 1080 B (26%)  FAIL
- timeSyncTask cfg 2048 B / 静态 1264 B / 余  784 B (38%)  FAIL
- 其余 7 任务 PASS(net 2112/1728、ftp 1456/2640、ui 1336/15048、
  test 736/7456、adc 1320/1240、iec104 1456/1104、protect 872/1176)

改动:
- defaultTask 1024 -> 1280 words(4096 -> 5120 B):余 2104 B / 41%
- timeSyncTask 512 -> 640 words(2048 -> 2560 B):余 1296 B / 50%
- 后基线:9 任务 0 FAIL(stack_report 退出码 0)

堆开销(任务栈来自 FreeRTOS 堆,.map 静态数字不变):
- defaultTask +1024 B、timeSyncTask +512 B,合计 +1536 B
- 台架背书基线 heap free=17936 / min_ever=10000 B(B6),抬后
  min_ever 预计 ~8464 B,仍远高于 3072 B 告警线

防丢失(CubeMX 存活 L1 纪律):
- STM32F407-Demo.ioc 的 FREERTOS.Tasks01 同步改 1024 -> 1280
  (.ioc 是 CubeMX 生成任务栈值的事实源,未跑重生成)
- Src/freertos.c 生成区 .stack_size 与 .ioc 保持一致
- USER CODE BEGIN Variables 核算注释块补 N-33 依据(栈值理由唯一落点)
- .cubemx_survival_baseline.json 经 --write 重建(仅 ioc-task-stacks 一行)

task-table 生成区随栈变更再生成(README.md + AGENTS.md 的
TASK_TABLE 锚点区各 2 行,锚点区外无任何改动)。

验证:@build 0 错误 0 警告(Program Size 与改前逐字节一致);
ci_local 全绿(L0 + L0.5,826/826 断言);stack_report 前后各跑一次。
台架 @test 与串口 [STACK] 水位复测在提交后单独跑。
This commit is contained in:
2026-10-12 17:47:15 +08:00
parent 4262bf6146
commit 51bc325b57
5 changed files with 18 additions and 10 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
"hal-iwdg-enabled": "1a8ed6cff34f7ba6", "hal-iwdg-enabled": "1a8ed6cff34f7ba6",
"ioc-keepusercode": "b5bea41b6c623f7c", "ioc-keepusercode": "b5bea41b6c623f7c",
"ioc-iwdg-present": "d3a6e667048c95db", "ioc-iwdg-present": "d3a6e667048c95db",
"ioc-task-stacks": "3262f737d92dcbee", "ioc-task-stacks": "58ee94dd2a093177",
"adc1-hal-enabled": "1a8ed6cff34f7ba6", "adc1-hal-enabled": "1a8ed6cff34f7ba6",
"adc1-calibration-call": "8d5f4b40fb218913", "adc1-calibration-call": "8d5f4b40fb218913",
"adc1-calibration-impl": "d33bc4323e243248", "adc1-calibration-impl": "d33bc4323e243248",
+2 -2
View File
@@ -52,12 +52,12 @@
<!-- TASK_TABLE:BEGIN generated by scripts/gen_task_table.py --> <!-- TASK_TABLE:BEGIN generated by scripts/gen_task_table.py -->
| Task | 栈 (words) | 优先级 | | Task | 栈 (words) | 优先级 |
|---|---|---| |---|---|---|
| defaultTask | 1024 | Normal | | defaultTask | 1280 | Normal |
| netTask | 960 | Normal | | netTask | 960 | Normal |
| ftpTask | 1024 | Normal | | ftpTask | 1024 | Normal |
| testTask | 2048 | BelowNormal | | testTask | 2048 | BelowNormal |
| uiTask | 4096 | BelowNormal | | uiTask | 4096 | BelowNormal |
| timeSyncTask | 512 | Normal | | timeSyncTask | 640 | Normal |
| adcTask | 640 | AboveNormal | | adcTask | 640 | AboveNormal |
| iec104Task | 640 | Normal | | iec104Task | 640 | Normal |
| protectTask | 512 | Normal | | protectTask | 512 | Normal |
+2 -2
View File
@@ -69,12 +69,12 @@ main.c
<!-- TASK_TABLE:BEGIN generated by scripts/gen_task_table.py --> <!-- TASK_TABLE:BEGIN generated by scripts/gen_task_table.py -->
| 任务 | 栈大小 | 优先级 | 职责 | | 任务 | 栈大小 | 优先级 | 职责 |
|------|--------|--------|------| |------|--------|--------|------|
| defaultTask | 1024 words | Normal | FTL + FatFS 挂载、配置引擎属主、syslog 唯一写者 | | defaultTask | 1280 words | Normal | FTL + FatFS 挂载、配置引擎属主、syslog 唯一写者 |
| netTask | 960 words | Normal | 网络初始化 + CH395F 轮询 | | netTask | 960 words | Normal | 网络初始化 + CH395F 轮询 |
| ftpTask | 1024 words | Normal | FTP 服务(等待网络+存储就绪) | | ftpTask | 1024 words | Normal | FTP 服务(等待网络+存储就绪) |
| testTask | 2048 words | BelowNormal | 硬件测试入口 | | testTask | 2048 words | BelowNormal | 硬件测试入口 |
| uiTask | 4096 words | BelowNormal | LVGL UI 界面 | | uiTask | 4096 words | BelowNormal | LVGL UI 界面 |
| timeSyncTask | 512 words | Normal | 墙钟时间同步 | | timeSyncTask | 640 words | Normal | 墙钟时间同步 |
| adcTask | 640 words | AboveNormal | TPAFE5160 采样(TIM3 1kHz 事件驱动 + 原子快照 + STM32 ADC DMA) | | adcTask | 640 words | AboveNormal | TPAFE5160 采样(TIM3 1kHz 事件驱动 + 原子快照 + STM32 ADC DMA) |
| iec104Task | 640 words | Normal | | | iec104Task | 640 words | Normal | |
| protectTask | 512 words | Normal | | | protectTask | 512 words | Normal | |
+1 -1
View File
@@ -119,7 +119,7 @@ FREERTOS.Events01=sys_evt,Dynamic,NULL
FREERTOS.FootprintOK=true FREERTOS.FootprintOK=true
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,FootprintOK,configTOTAL_HEAP_SIZE,Queues01,Events01,configCHECK_FOR_STACK_OVERFLOW,configUSE_MALLOC_FAILED_HOOK FREERTOS.IPParameters=Tasks01,configENABLE_FPU,FootprintOK,configTOTAL_HEAP_SIZE,Queues01,Events01,configCHECK_FOR_STACK_OVERFLOW,configUSE_MALLOC_FAILED_HOOK
FREERTOS.Queues01=netMsgQueue,8,net_msg_t,0,Dynamic,NULL,NULL FREERTOS.Queues01=netMsgQueue,8,net_msg_t,0,Dynamic,NULL,NULL
FREERTOS.Tasks01=defaultTask,24,1024,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;netTask,24,960,StartNetTask,Default,NULL,Dynamic,NULL,NULL;ftpTask,24,1024,StartFtpTask,As weak,NULL,Dynamic,NULL,NULL;testTask,16,2048,start_test_task,As weak,NULL,Dynamic,NULL,NULL;uiTask,16,4096,StartUiTask,Default,NULL,Dynamic,NULL,NULL FREERTOS.Tasks01=defaultTask,24,1280,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;netTask,24,960,StartNetTask,Default,NULL,Dynamic,NULL,NULL;ftpTask,24,1024,StartFtpTask,As weak,NULL,Dynamic,NULL,NULL;testTask,16,2048,start_test_task,As weak,NULL,Dynamic,NULL,NULL;uiTask,16,4096,StartUiTask,Default,NULL,Dynamic,NULL,NULL
FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2 FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2
FREERTOS.configENABLE_FPU=1 FREERTOS.configENABLE_FPU=1
FREERTOS.configTOTAL_HEAP_SIZE=57344 FREERTOS.configTOTAL_HEAP_SIZE=57344
+12 -4
View File
@@ -94,7 +94,7 @@ static int hook_ptr_ok(const void *p)
* 底线规则:余量 ≥ max(1024 B ISR, 30%)。完整核算见 docs/内存管理/RAM使用分析与优化方案.md, * 底线规则:余量 ≥ max(1024 B ISR, 30%)。完整核算见 docs/内存管理/RAM使用分析与优化方案.md,
* 全表(含 ftpTask 1024 / uiTask 4096 的现值)见 AGENTS.md 任务表。 * 全表(含 ftpTask 1024 / uiTask 4096 的现值)见 AGENTS.md 任务表。
* *
* defaultTask 1024 words:扛 mount+mkfs+FAT 探针+cfg 加载+syslog 写+配置引擎 * defaultTask 1280 words:扛 mount+mkfs+FAT 探针+cfg 加载+syslog 写+配置引擎
* (全深层 FatFS I/O)。原 512,2KB 实测峰值溢出——开启 * (全深层 FatFS I/O)。原 512,2KB 实测峰值溢出——开启
* configCHECK_FOR_STACK_OVERFLOW=2 后被钩子抓到(2026-09-21)。 * configCHECK_FOR_STACK_OVERFLOW=2 后被钩子抓到(2026-09-21)。
* 2026-10-10 栈整改(**未抬栈**,靠削链达标):静态最坏链 5312 → 2776 B、 * 2026-10-10 栈整改(**未抬栈**,靠削链达标):静态最坏链 5312 → 2776 B、
@@ -104,6 +104,10 @@ static int hook_ptr_ok(const void *p)
* + 时间戳缓冲并入行缓冲(每个日志调用点原内联 192+32 B);④ 断言/故障钩子 * + 时间戳缓冲并入行缓冲(每个日志调用点原内联 192+32 B);④ 断言/故障钩子
* 脱离 HAL 发送回退 + 缓冲静态化(configASSERT 在 FreeRTOS 内部可达 → * 脱离 HAL 发送回退 + 缓冲静态化(configASSERT 在 FreeRTOS 内部可达 →
* 钩子在**每个**任务的最坏链尾)。详见 docs/内存管理/RAM使用分析与优化方案.md * 钩子在**每个**任务的最坏链尾)。详见 docs/内存管理/RAM使用分析与优化方案.md
* N-33(2026-10-12):B7 定值持久化把静态最坏链推到 **3016 B**(storage_bring_up →
* cfg 写 → f_rename → sync_fs → dhara GC → 控制台回显尾),1024 words 时余
* 1080 B < 30% 线(4096×30% = 1228 B)→ 抬至 **1280 words**(5120 B),余
* 2104 B / 41%;堆开销 +1024 B。栈值事实源仍是 `.ioc` 的 `FREERTOS.Tasks01`。
* netTask 960 words:静态最坏链 1872 B(2026-10-10 整改后;整改前 2664 B: * netTask 960 words:静态最坏链 1872 B(2026-10-10 整改后;整改前 2664 B:
* 发送停滞→断连→重监听→SPI 故障→日志尾,日志主导);3840 B 配置余量 1968 B * 发送停滞→断连→重监听→SPI 故障→日志尾,日志主导);3840 B 配置余量 1968 B
* (51%),过 stack_report 规则。运行时水位仅 ~0.9 KB(错误尾未 * (51%),过 stack_report 规则。运行时水位仅 ~0.9 KB(错误尾未
@@ -111,10 +115,14 @@ static int hook_ptr_ok(const void *p)
* (ARMCC 已叠放不重叠局部量)反增 256 B BSS,已回退——见 net_socket.c 注释。 * (ARMCC 已叠放不重叠局部量)反增 256 B BSS,已回退——见 net_socket.c 注释。
* testTask 2048 words:存储套件 deep call chain + 局部缓冲,原 1024(4 KB)实测溢出 * testTask 2048 words:存储套件 deep call chain + 局部缓冲,原 1024(4 KB)实测溢出
* (2026-09-20)。仅启用测试套件时创建。 * (2026-09-20)。仅启用测试套件时创建。
* timeSyncTask 512 words:本区下方手工定义(不在 `.ioc` 的 Tasks01 里 → 重生成会丢, * timeSyncTask 640 words:本区下方手工定义(不在 `.ioc` 的 Tasks01 里 → 重生成会丢,
* 靠审计 WARN 提示),建监听 → net_bind → CH395F → 日志尾。2026-10-10 整改后 * 靠审计 WARN 提示),建监听 → net_bind → CH395F → 日志尾。2026-10-10 整改后
* 静态最坏链 1024 B(整改前 1736 B)、实测峰值 616 B;⚠ 余量 1024 B **正好** * 静态最坏链 1024 B(整改前 1736 B)、实测峰值 616 B;⚠ 余量 1024 B **正好**
* 等于 ISR 底线 → 本任务链上再加任何调用(或新日志行)都必须先抬栈。 * 等于 ISR 底线 → 本任务链上再加任何调用(或新日志行)都必须先抬栈。
* N-33(2026-10-12):链已加深到 **1264 B**(同一控制台回显尾:`dbg_console_drain`
* → `MX_USART1_UART_Init` → `Error_Handler` → 回显 Cycle),512 words 时余
* 784 B < 1024 B ISR 底线 → 抬至 **640 words**(2.5 KB),余 1296 B / 50%;
* 堆开销 +512 B。
* adcTask 640 words:本区下方手工定义(同上,不在 `.ioc` 里)。B1(2026-10-10) * adcTask 640 words:本区下方手工定义(同上,不在 `.ioc` 里)。B1(2026-10-10)
* ADC 采集消费者;L2 相量(2026-10-11)+ L1-6 有效性校验(同日)后链上为 * ADC 采集消费者;L2 相量(2026-10-11)+ L1-6 有效性校验(同日)后链上为
* adc_input_poll + sample_ring/phasor + adc_health_report(DBG_ERROR + * adc_input_poll + sample_ring/phasor + adc_health_report(DBG_ERROR +
@@ -133,7 +141,7 @@ static int hook_ptr_ok(const void *p)
osThreadId_t timeSyncTaskHandle; osThreadId_t timeSyncTaskHandle;
const osThreadAttr_t timeSyncTask_attributes = { const osThreadAttr_t timeSyncTask_attributes = {
.name = "timeSyncTask", .name = "timeSyncTask",
.stack_size = 512 * 4, .stack_size = 640 * 4,
.priority = (osPriority_t) osPriorityNormal, .priority = (osPriority_t) osPriorityNormal,
}; };
/* B1(2026-10-10):ADC 采集消费者(TIM6 1 kHz 采样节拍 + 原子快照 + 帧统计)。 /* B1(2026-10-10):ADC 采集消费者(TIM6 1 kHz 采样节拍 + 原子快照 + 帧统计)。
@@ -176,7 +184,7 @@ const osThreadAttr_t protectTask_attributes = {
osThreadId_t defaultTaskHandle; osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = { const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask", .name = "defaultTask",
.stack_size = 1024 * 4, .stack_size = 1280 * 4,
.priority = (osPriority_t) osPriorityNormal, .priority = (osPriority_t) osPriorityNormal,
}; };
/* Definitions for netTask */ /* Definitions for netTask */