背景
在基于 Infineon TC3xx 平台和最新版 AUTOSAR 架构的中央域控/区控项目联调中,我们遭遇了一个非常典型的“灵异事件”:系统在运行态正常检测到故障,通过诊断仪读取 UDS 0x19 服务,DTC 状态字节正确显示为 0x28(即 Bit 3 ConfirmedDTC 且 Bit 5 TestFailedSinceLastClear 均置位)。然而,在向 ECU 发送 11 01 (Hard Reset) 硬复位指令,或者执行完整的下电休眠再唤醒后,该 DTC 的状态却离奇地变成了 0x00。
故障现场就像被清道夫打扫过一样,毫无痕迹。为了揪出这个幕后黑手,我们对 DEM(诊断事件管理器)、NvM(非易失性存储器)以及 BswM/EcuM(系统状态机)进行了一场深度的联合排查。
疑点一:是新版 DEM 操作周期机制导致的“老化”重置吗?
起初,怀疑的方向指向了 DEM 的操作周期(Operation Cycle)机制。在新版本 AUTOSAR (R19-11 及以后) 中,诊断架构发生了重大升级:Dem_SetOperationCycleState 显式设置 END 的做法被废弃,取而代之的是使用 Dem_RestartOperationCycle 作为连续周期的刷新脉冲。
在新架构下,DTC 的老化(Aging)结算不再发生在周期结束时,而是顺延到了下一次新周期重启的瞬间(Look-back 机制)。
然而,即使老化完成导致 Bit 3 (Confirmed) 清零,Bit 5 (TestFailedSinceLastClear) 也必须保持为 1,除非收到了外部的 0x14 清码服务。因此,状态从 0x28 直接突变为 0x00,绝非 DEM 正常的诊断逻辑所为,核心问题必然出在存储(Storage)环节。
疑点二:Event Memory 溢出还是 NvM 配置失效?
顺着存储的线索,我们检查了 DEM 模块的底层家底:
- 排查溢出:利用 Dem_GetEventMemoryOverflow API 和底层机制,我们确认系统并未因为网络风暴导致 Primary Memory(主记忆体,通常配置如 20 或 40 个槽位)溢出。
- 确认 NvM 映射:通过审查工具链生成的 Dem_Cfg_AssertionChk.h 静态断言和 Dem_GenericNvData.h 结构体,我们精准定位到了存储所有 DTC 全局状态的数组:Dem_AllEventsStatusByte(大小 100 Byte)。 该数组已经正确映射到了 NvM 的独立 Block 中,并且开启了 SAVED_ZONE 的内存属性。这意味着配置层面上,这 100个字节是拥有合法“房产证”的。
此时结论呼之欲出:数据就在 RAM 里,只是在复位或下电的死亡瞬间,没能成功刷写进 DFlash 中。
终极真相:状态机时序走位与 NvM 的“异步之殇”
通过对系统下电和复位时序(Shutdown & Reset Sequence)的逐帧级复盘,我们终于在 EcuM(ECU State Manager)的深处抓到了真凶。
问题的根源在于:集成工程师虽然在配置中调用了 Dem_Shutdown 和 NvM_WriteAll,但调用的时机实在太晚了——它们被放置在了 EcuM_GoOffTwo 阶段。
这暴露了对 AUTOSAR NvM **异步处理机制(Asynchronous Processing)**和 OS 生命周期的理解偏差:
- 异步队列的假象:NvM_WriteAll() 并非一个阻塞型的同步函数。调用它,只是在 NvM 内部的一个 RAM 队列中挂入了一张“写请求任务单”,随后函数立刻返回 E_OK。
- 执行者是谁?:真正负责清空队列、驱使底层 Flash 驱动干活的,是需要被 OS 周期性调度的 NvM_MainFunction(以及 Fee/Fls_MainFunction)。
- 致命的 GoOffTwo:在 AUTOSAR 规范中,进入 GoOffTwo 阶段的前提是:操作系统已经通过 ShutdownOS() 被杀死了,且全局中断已关闭。
- 憋死在 RAM 里:当代码在 GoOffTwo 里调用 NvM_WriteAll 时,请求虽然成功入队,但由于 OS 已死,再也没有任何 Task 会去调度 MainFunction。写请求彻底变成了“死队列”,直到 Mcu_PerformReset 强行拔除电源,RAM 里的 0x28 就此灰飞烟灭。下次上电,NvM 只能读出空数据覆盖 RAM,导致状态归零。
破局与最佳实践:优雅的关机/复位时序
为了彻底修复这个时序断层,避免类似的数据倒灌或丢失,我们将 BswM / EcuM 针对 11 01 复位及下电休眠的处理逻辑重构为以下标准范式:
- PREP_SHUTDOWN 阶段(OS 存活期):
- 停止应用层业务逻辑与 Com 报文收发。
- 调用 Dem_Shutdown(),冻结诊断状态。
- 调用 NvM_WriteAll(),将所有 NV Block 请求入队。
2.WAIT_FOR_NVM 阶段(关键的轮询防线):
- 配置一个专属的 BswM Rule,周期性检查(通过 Mode Request 或直接调 API)NvM_GetErrorStatus。
- 核心约束:系统必须在此状态停留,让 OS 持续调度 NvM_MainFunction,直到总体状态返回 NVM_REQ_OK 或超时。
3.GoOff 阶段(不可逆的死亡宣告):
- 确认数据落盘完毕后,才允许 EcuM 步入 GoOffOne,关闭 OS 并进入 GoOffTwo。
- 最后干净利落地执行 Mcu_PerformReset 或断电休眠。
总结
底层基础软件(BSW)的集成,绝非单纯的 API 连线堆砌,而是对无数个跨模块状态机、异步队列机制以及硬件物理时序的精细编排。只有对 OS 调度和外设时延心存敬畏,才能在配置工具的汪洋中避开这些致命的暗礁。