查证 SHCSR 的 Fault 使能位无法在 CubeMX 配置,补入文档与审计提示
用户问 fault_handler_enable() 能否通过 CubeMX 配置。查 CubeMX 安装目录的 模板源码后确认:不能。三重证据: 1. tpl_main_c.ftl 的 MX_NVIC_Init() 用 [#if vector.systemHandler=="false"] 才生成 HAL_NVIC_EnableIRQ;而 NVIC-STM32F417_Modes.xml 里 MemoryManagement/BusFault/UsageFault_IRQn 都标 Y(=systemHandler), 故 CubeMX 对这三个永不生成使能代码(只生成优先级,且仅当优先级 != 0)。 2. 全部模板中 SHCSR 只出现 1 次(tpl_main_c.ftl:2269),且是 MPU 清理时的 SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk(禁用),无任何 |= 置位。 3. MPU 路径也堵死:.ioc 的 Mcu.IP 列表无 MPU,且 HAL_MPU_Enable 只置 MEMFAULTENA 一位,BUSFAULTENA/USGFAULTENA 仍拿不到。 实测印证:Src/stm32f4xx_hal_msp.c 的 HAL_MspInit() 里只有 HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0),三个 Fault 一行代码都没生成。 结论:只能手工写。但函数体在 USER CODE BEGIN 1 区(L2),重生成不会丢, 另有审计项 fault-handler-enable 兜底 -- 故这不是风险,只是无法享受 L1。 顺带记录一个易踩的误解:.ioc 里 NVIC.MemoryManagement_IRQn=true 的第 1 段 只是"向量在 NVIC 表里可见/已配优先级",与 SHCSR 使能位无关, 不要以为勾了 NVIC 面板的 Enabled 就等于使能了故障。 改动: - 看门狗设计说明.md:§10.2 新增"为什么 fault_handler_enable() 写不进 .ioc" (三路径对照表 + 实测印证 + 结论);四个 Fault 采集小节加警示; L1 表格补该行;变更记录新增 2026-10-01 条。 - AGENTS.md:新增"SHCSR 的 Fault 使能位无法在 CubeMX 配置"铁律条目。 - scripts/check_cubemx_survival.py:fault-handler-enable 的 hint 补上 "无法 CubeMX 配置"及其原因,便于日后重生成后看提示就能回忆。 验证:pre-commit 13 钩子全通过;审计 18 通过 / 1 警告 / 0 失败。本次仅改 文档与脚本注释,未动代码,无需重编译。
This commit is contained in:
+33
-1
@@ -867,7 +867,32 @@ external pin → "pin reset" (新增)
|
||||
| `configCHECK_FOR_STACK_OVERFLOW` | 在 `USER CODE BEGIN FREE_RTOS_CONFIG_HARDENING` 区(L2) | ⚠️ CubeMX 的 FreeRTOS 界面**没有**这一项的勾选框,只能靠 L2 + 审计。**保持现状** |
|
||||
| `configUSE_MALLOC_FAILED_HOOK` | 同上 | 同上 |
|
||||
| `configASSERT` 定义 | 在 `USER CODE BEGIN 1` 区(L2) | 同上。CubeMX 无对应界面项 |
|
||||
| `MemManage/BusFault/UsageFault_Handler` | `stm32f4xx_it.c` 标记区**外**(L3) | ⚠️ CubeMX 为这些函数**不生成** `USER CODE` 区,无法 L2。见下方"存量清单" |
|
||||
| 4 个 Fault Handler 实体 | `stm32f4xx_it.c` 标记区**外**(L3) | ⚠️ CubeMX 为这些函数**不生成** `USER CODE` 区,无法 L2。见下方"存量清单" |
|
||||
| `fault_handler_enable()`(SHCSR 使能三位) | `Src/stm32f4xx_it.c` 的 `USER CODE BEGIN 1` 区(L2) | ❌ **CubeMX 无此配置项**(已查模板源码证实,见下) |
|
||||
|
||||
##### 为什么 `fault_handler_enable()` 写不进 `.ioc`(2026-10-01 查模板源码证实)
|
||||
|
||||
用户问"能否通过 CubeMX 配置",逐条查证 CubeMX 安装目录
|
||||
`db/templates/*.ftl` 与 `db/mcu/IP/NVIC-STM32F417_Modes.xml`
|
||||
(F407 复用 F417 定义),**三条可能路径全部否定**:
|
||||
|
||||
| 路径 | 查证结果 |
|
||||
|---|---|
|
||||
| ① NVIC 面板勾选三个 Fault 的 `Enabled` | `tpl_main_c.ftl` 的 `MX_NVIC_Init()`:`[#if vector.systemHandler=="false"]` **才**生成 `HAL_NVIC_EnableIRQ(...)`。而 `NVIC-STM32F417_Modes.xml` 中 `MemoryManagement/BusFault/UsageFault_IRQn` 都标 `Y`(= `systemHandler`)→ **永不生成使能代码**(`HardFault_IRQn` 标 `N` 是个例外,但它恒使能、无需使能) |
|
||||
| ② 任何模板里找 `SHCSR` 置位 | 全部模板中 `SHCSR` **只出现 1 次**(`tpl_main_c.ftl:2269`),且是 MPU 清理时的 `SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk`(**禁用**)。**无任何 `\|=` 置位** |
|
||||
| ③ 启用 MPU(`HAL_MPU_Enable` 内部会置 `MEMFAULTENA`) | `.ioc` 的 `Mcu.IP0..13` 列表**无 MPU**;且该函数**只置 `MEMFAULTENA` 一位**,`BUSFAULTENA`/`USGFAULTENA` 仍拿不到 |
|
||||
|
||||
**实测印证**:`Src/stm32f4xx_hal_msp.c` 的 `HAL_MspInit()` 里只有
|
||||
`HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0)`(因它优先级 ≠ 0 才生成),
|
||||
三个 Fault **一行代码都没生成**——与模板逻辑完全吻合。
|
||||
|
||||
> **结论**:`fault_handler_enable()` **只能手工写**。但它是 **L2**(放在
|
||||
> `USER CODE BEGIN 1` 区)——**重生成不会丢**,所以这条不是风险,只是
|
||||
> "无法享受 L1 的'CubeMX 自己生成'待遇"。**已挂审计项 `fault-handler-enable` 兜底。**
|
||||
|
||||
> ⚠️ 顺带提醒:`.ioc` 里那三行 `NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:...`
|
||||
> **不代表"已使能"**——第 1 段 `true` 只是"该向量在 NVIC 表里可见/已配置优先级",
|
||||
> 与 `SHCSR` 使能位无关。**不要误以为勾了 CubeMX 的 Enabled 就等于使能了故障。**
|
||||
|
||||
> **判断口诀**:能在外设/中间件的图形界面里找到对应输入框的 → 一定写 `.ioc`;
|
||||
> 找不到(如 FreeRTOS 的两个加固宏、断言定义、故障异常处理函数体)→ 只能 L2/L3。
|
||||
@@ -932,6 +957,12 @@ external pin → "pin reset" (新增)
|
||||
声明在 `Inc/stm32f4xx_it.h` 的 `USER CODE BEGIN EFP` 区),在
|
||||
`app_main_init()` **第一行**调用(纯寄存器写,不依赖日志/时钟)。
|
||||
|
||||
> ⚠️ **这三位没法在 CubeMX 里配**(2026-10-01 查模板源码证实,详见 §10.2
|
||||
> 「为什么 `fault_handler_enable()` 写不进 `.ioc`」)。**不要以为在 NVIC 面板
|
||||
> 勾了 `Enabled` 就使能了故障**——CubeMX 对 System Exception 只生成优先级
|
||||
> (且仅当优先级 ≠ 0),**从不生成使能代码**。好在函数体在 `USER CODE BEGIN 1`
|
||||
> 区,重生成不会丢(L2),另有审计项 `fault-handler-enable` 兜底。
|
||||
|
||||
**刻意不打开的两项**(都会把普通 bug 升级成死机,对本项目弊大于利):
|
||||
|
||||
- `CCR.UNALIGN_TRP`:非对齐访问陷入。Cortex-M4 硬件本可处理非对齐访问,
|
||||
@@ -1050,3 +1081,4 @@ python scripts/check_cubemx_survival.py --write # 重建基线(确认改动
|
||||
| 2026-09-29 | **新增 §10.2 三层手段 + 审计脚本** | 沉淀通用方法论(L1 `.ioc` / L2 `USER CODE` 区 / L3 审计+基线);新建 `scripts/check_cubemx_survival.py`(16 项清单 + 漂移检测)+ `.cubemx_survival_baseline.json` + pre-commit `cubemx-survival` 钩子;`AGENTS.md` 与 `docs/代码规范/pre-commit使用说明.md` 同步 |
|
||||
| 2026-09-29 | **第二次重生成验证 + 机制修正** | 审计脚本**实测有效**(准确检出 5 处覆盖)。⚠️ **关键发现**:CubeMX 换了一代中断函数模板(旧 `HardFault_Handler`/`HardFault_Report` 自造区 → 新函数体内 `HardFault_IRQn 0`/`W1_HardFault_IRQn 0`),**"生成区外的自造标记区"同样不被保留**——上一轮假设被证伪。据此升级恢复方案:报告实现迁入 `USER CODE BEGIN 0`(标准保护位);Handler 本体改为生成区整函数替换(`#define` 改名保留生成实体,链接器自动移除,`.map` 已验证)+ `HARD-FAULT-ANCHOR` 锚点。同步修正审计脚本(`hardfault-handler` 改 `wholefile` + 锚点)、`UNPROTECTED_LEGACY` 清单、§10.1/§10.2 全文。`@build` 0 错误 0 警告 |
|
||||
| 2026-09-29 | **3 个 Fault 升级为崩溃采集** | `MemManage` / `BusFault` / `UsageFault` 由空 `while(1)`(死机静默)升级为与 `HardFault` 同一套采集:生成区整函数替换(各带独立锚点 `MEMFAULT-ANCHOR` / `BUSFAULT-ANCHOR` / `USAGEFAULT-ANCHOR`)+ `#define X X_Gen` 改名保留生成实体(链接器各移除 2 字节)。新增 `fault_handler_enable()` 使能 `SHCSR` 后三者(默认只开 HardFault,不开则故障被升级、看不出根因),声明入 `Inc/stm32f4xx_it.h`、调用在 `app_main_init()` 第一行。因 ARMCC `__asm` 取不到 C 数据符号,改为 per-fault C 入口 `fault_entry_{hard,mem,bus,usage}` 带故障名调 `hard_fault_report(tag, frame)`。**刻意不启用** `UNALIGN_TRP` / `DIV_0_TRP`(避免把普通 bug 升级成死机)。审计脚本新增 `fault-handlers-3` / `fault-handler-enable` 两项、`UNPROTECTED_LEGACY` 清掉 3 个 Fault(WARN 2→1)、清单 16→18 项。`@build` 0 错误 0 警告;审计 18 通过 / 1 警告 / 0 失败 |
|
||||
| 2026-10-01 | **查证 `fault_handler_enable()` 的 CubeMX 可行性** | 用户问"能否通过 CubeMX 配置"→ **否**。查 CubeMX 安装目录模板源码得三重证据:① `tpl_main_c.ftl` 的 `MX_NVIC_Init()` 只在 `systemHandler=="false"` 时生成 `HAL_NVIC_EnableIRQ`,而 `NVIC-STM32F417_Modes.xml` 中三个 Fault 都标 `Y`(=systemHandler)→ 永不生成使能代码;② **全部模板中 `SHCSR` 只出现 1 次**且是 MPU 清理的 `&= ~MEMFAULTENA`(禁用),**无任何 `\|=` 置位**;③ `.ioc` 无 MPU(`Mcu.IP` 列表),且 `HAL_MPU_Enable` 只置 `MEMFAULTENA` 一位。实测印证:`HAL_MspInit()` 里三个 Fault 一行代码都没生成。结论:只能手工写,但属 **L2**(`USER CODE BEGIN 1` 区)→ 重生成不丢,有审计项兜底。另新增警示:`.ioc` 的 `NVIC.MemoryManagement_IRQn=true` **不代表已使能**(第 1 段只是"向量可见")。写入 §10.2 与四个 Fault 采集小节 |
|
||||
|
||||
Reference in New Issue
Block a user