点火信号关闭后,ECU 往往不能立刻断电:应用可能需要完成短时收尾,诊断状态需要结算,非易失数据需要异步写入,主继电器还必须保持到最后一步。真正困难的不是增加几个状态名,而是明确每个阶段还能运行什么、谁有权延长供电、重新唤醒如何打断关机,以及超时后如何收敛。
本文基于一套实际 ECU 软件的静态调用链复核,讨论 After-run、Post-Run 与低功耗协同。这套实现沿用了 MCAL、RTE、NvM 等 AUTOSAR 分层思想,但生命周期控制并不由标准 EcuM/BswM/ComM/CanSM 状态机完成,而是由一个固定周期运行的自研电源状态机统一推进。
为便于阅读,后文统一使用功能术语:正常运行表示主要应用仍被调度;After-run表示应用层的短时延后运行;Post-Run表示主要应用停止后的系统收尾窗口;Shutdown表示非易失数据保存与最终切电。实际工程中的状态名可以不同,判断阶段边界应以“哪些任务还在运行、哪些资源仍在供电”为准。
先给结论:主路径是 正常运行 -> After-run -> Post-Run -> Shutdown -> 关闭主电源继电器 -> SBC LPOFF。After-run 期间主要应用仍可运行;进入 Post-Run 后主要应用停止,但继电器继续保持,为诊断结算和数据保存留出时间。
一、先看完整状态与供电关系
本文讨论的 ECU 由系统基础芯片(SBC)管理外部供电与硬件唤醒。
正常运行
-> After-run(主要应用仍可运行)
-> Post-Run(主要应用停止,系统继续收尾)
-> Shutdown(异步保存非易失数据)
-> 关闭主电源继电器
-> 普通下电:SBC LPOFF
Boot 请求:复位进入 Bootloader
| 阶段 | 主要动作 | 主要应用任务 | 主电源继电器 |
|---|---|---|---|
| 正常运行 | 控制、通信、监控与诊断 | 运行 | 保持接通 |
| After-run | 应用层执行短时延后运行,框架保留数十秒级兜底上限 | 仍可运行 | 保持接通 |
| Post-Run | 恢复数据参考视图,触发诊断周期的开始/结束收尾 | 停止 | 保持接通 |
| Shutdown | 请求写入诊断状态数据,并轮询异步结果 | 停止 | 等待收尾 |
| 最终切电 | 普通下电进入 LPOFF;Boot 请求则复位进入 Bootloader | 停止 | 关闭 |
这里有两个容易混淆的边界。第一,After-run 可以只是正常运行状态中的一个应用子模式,不能只看顶层电源状态就判断应用是否已开始收尾。第二,Post-Run 并不等于立即切电;它先停掉主要应用任务,把剩余供电时间留给诊断和数据处理。
二、周期状态机是整个流程的时基
系统按固定周期更新模拟量、离散输入和唤醒状态,然后推进电源状态机。点火输入的软件去抖也在状态判断之前完成。高频控制任务带有“应用是否允许运行”的守卫条件,因此状态一旦进入 Post-Run,主要控制应用的周期函数就停止调用;底层硬件抽象与后台服务仍可继续完成必要维护。
这与标准 AUTOSAR 模式管理链路并不等价。即使工程中存在 RTE、NvM 等标准模块,也不能据此推断系统一定采用 EcuM 主导下电、BswM 仲裁模式或 ComM/CanSM 收敛网络。理解一套 ECU 的真实生命周期,仍要回到实际调度入口、状态守卫和调用关系。
三、哪些信号可以继续保持 ECU 唤醒
状态机把点火输入、外部唤醒输入和 CAN 唤醒合成为一个“是否继续保持供电”的判断:
| 唤醒源 | 来源 | 运行期处理 |
|---|---|---|
| 点火输入(T15) | SBC 逻辑输入 | 连续多个调度周期确认,形成百毫秒级软件去抖 |
| 外部唤醒输入 A | SBC 外部输入 | 随周期输入更新直接参与保持判断 |
| 外部唤醒输入 B | SBC 外部输入 | 随周期输入更新直接参与保持判断 |
| CAN | SBC 或收发器唤醒锁存 | 启动时读取,应用消费后清除锁存 |
只有所有保持源都失效,系统才开始沿下电方向迁移。Boot 请求是特殊分支:它不要求普通唤醒条件消失,而是让系统先完成同一套收尾,再通过复位进入 Bootloader,避免从运行态直接跨越关机事务。
四、After-run:框架能力不等于当前业务行为
当所有唤醒保持源消失时,顶层电源状态仍可暂时留在正常运行阶段,只把应用协调层切换到 After-run。主要应用任务此时仍按原有条件运行。框架为这一阶段设置了数十秒级的可配置强制上限:如果应用始终不宣布结束,超时后仍会进入 Post-Run,避免 ECU 长时间保持高功耗。
但框架能力不等于当前业务行为。在所分析的实现中,应用协调层检测到点火关闭后,会在同一次周期调用中立即发出关机请求。电源状态机随后进入 Post-Run。因此,After-run 实际通常只持续一个状态机周期;数十秒级上限只是防止异常滞留的兜底,并不是已实现的延时运行时长。
如果产品需要“点火关闭后继续工作一段时间”,不能只配置一个更长的超时上限。还要明确 After-run 中允许继续运行的功能、正常结束条件、谁可以延长保持时间,以及延长请求与再次唤醒之间的优先级。
五、Post-Run:主要应用停止后的系统收尾窗口
进入 Post-Run 后,主继电器仍保持接通,但主要控制应用因失去运行许可而停止。系统随后按周期子状态完成以下动作:
- 数据与标定管理模块切回参考数据页,避免在线工作页影响关机后的数据视图。
- 诊断状态管理模块触发 Post-Run Begin,结算驾驶循环、暖机循环等通用诊断条件。
- 经过为存储或外部事件预留的等待子状态。
- 触发 Post-Run End,完成对应的诊断结束条件。
- 满足最短保持时间后转入 Shutdown。
所分析实现配置了秒级最短保持和十秒级最大超时。正常情况下,快速子状态在少量调度周期内走完,然后停在最短时间守卫;若流程没有正常收敛,最大超时会强制进入 Shutdown。这个窗口用于诊断与数据视图收尾,不应被描述为主要控制功能继续运行的 After-run。
六、Shutdown:异步保存完成或超时后才切电
Post-Run 结束后,Shutdown 请求写入诊断状态对应的 NvM 数据块,而不是直接同步擦写,也不是无条件触发全块保存。后台循环持续执行 NvM_MainFunction,电源状态机周期查询请求结果:
NVM_REQ_PENDING:继续保持主继电器并等待。NVM_REQ_OK:允许进入主继电器关闭步骤。- 其他结果:重新提交同一诊断状态数据块的写请求。
- 达到十余秒级全局上限:不再无限等待,进入最终关闭步骤。
这是一种“异步请求 + 后台执行 + 周期轮询 + 全局超时”的典型结构。它避免在周期状态机中同步擦写存储,但也有明确边界:写失败会持续重试,当前没有独立的重试次数与失败记录;全局超时保证 ECU 最终能够下电,却不能证明诊断状态数据一定保存成功。
七、SBC LPOFF 与 MCU Sleep 是两种恢复语义
正常下电完成数据收尾后,软件先关闭主电源继电器,再通过 SPI 命令让 SBC 进入 LPOFF。这条路径没有建立 MCU 上下文保留式 Sleep;低功耗的主体是管理外部供电与唤醒的 SBC。
两类低功耗的恢复语义完全不同:
| 方案 | 低功耗主体 | 唤醒后的软件入口 | 上下文语义 |
|---|---|---|---|
| SBC LPOFF | SBC 控制外部电源与唤醒 | 重新经过 Bootloader,再进入应用初始化并读取唤醒原因 | 按重新启动处理 |
| MCU Sleep/Standby | MCU 内核与片上电源域 | 由芯片低功耗恢复路径返回 | 可能保留部分 RAM 或寄存器上下文 |
因此,不能把这类实现描述为“CPU 睡眠后原地恢复”。点火输入、外部输入或 CAN 触发硬件唤醒后,软件重新走 Bootloader 和应用启动链,在 SBC 初始化阶段读取唤醒原因,再恢复正常运行。
八、切电前的唤醒可以取消关机
Post-Run 与 LPOFF 前的 Shutdown 都会周期检查唤醒保持源。只要点火输入、任一路外部输入或 CAN 再次有效,软件就取消当前下电路径,回到运行前准备阶段,再进入正常运行,同时重置关机计数和诊断运行状态。
这个保护只在切电仍可撤销时成立。主继电器关闭并发出 LPOFF 命令后,后续唤醒属于一次新的硬件启动,不再是原状态机中的“取消 Shutdown”。因此系统必须明确一个不可逆提交点:提交点之前允许唤醒否决关机,提交点之后按重新启动处理。
九、预留接口不等于能力已经接入
源码里的状态名、标定项和扩展接口看起来往往比实际行为完整。对所分析实现而言,以下能力目前不能包装成“已经实现”:
| 预留点 | 当前事实 | 不能宣称的能力 |
|---|---|---|
| After-run 进入 Bootloader 的标定项 | 标定项存在,但没有参与状态迁移 | 不能据此宣称支持 After-run 定时进入 Bootloader |
| Post-Run 存储等待子状态 | 多数子状态按周期直接跳到下一状态 | 不能宣称已等待 Flash 或 EEPROM 作业完成 |
| 外部等待变量与掩码 | 变量已初始化,但没有形成实际迁移守卫 | 不能宣称存在可扩展的外部事件屏障 |
| Shutdown 诊断收尾接口 | 接口存在,但当前没有实际处理 | 不能宣称 Shutdown 阶段执行了额外诊断清理 |
| NvM 保存范围 | 只明确保存诊断状态数据块 | 不能宣称所有脏数据块或全部业务数据都会保存 |
| 主继电器反馈 | 存在控制命令,但没有反馈通道 | 不能宣称软件确认了继电器或主电源已实际断开 |
这些缺口未必意味着产品一定失效:有些能力可能不在当前需求范围,有些安全性由外部硬件或系统级假设承担。但在设计说明中,必须把“接口已预留”“当前调用为空”“功能已完成并验证”三个层次分开。
十、迁移到其他 ECU 时应保留的设计边界
这套流程真正可复用的不是状态名,而是各阶段之间的责任边界:
- 把业务模式与电源生命周期分开。After-run 可以是正常供电状态中的应用子模式,但必须明确哪些任务继续运行、哪些任务已经停止。
- 区分 After-run 与 Post-Run。前者解决“应用是否还要工作”,后者解决“主要应用停止后系统还要收什么尾”。
- 把 Shutdown 设计成异步事务。写请求、后台执行、结果轮询、重试策略和总超时必须有清晰契约,不能把提交写请求等同于保存完成。
- 在不可逆切电前保留唤醒否决权。重新出现的唤醒源应能够中止关机,并把状态、计数和诊断上下文恢复到一致起点。
- 区分 SBC 断电式低功耗与 MCU 上下文保留式 Sleep。两者的启动入口、RAM 假设、驱动初始化和唤醒原因读取方式完全不同。
- 把控制命令与物理结果分开。软件发出继电器关闭命令,不代表电源已经断开;没有反馈通道时,应明确这是系统假设而不是闭环确认。
- 不要把预留接口写成现有能力。状态名、空回调和未参与守卫的变量只能说明扩展意图,不能证明功能已经接入。
结语
这类 ECU 下电流程可以概括为一条由周期状态机主导的电源事务:After-run 保留应用层的短时延后运行能力,Post-Run 在主要应用停止后完成诊断与数据视图收尾,Shutdown 异步保存必要的非易失数据,最后关闭主电源继电器并让 SBC 进入 LPOFF。切电前的重新唤醒可以撤销事务,切电后则按一次新的启动处理。
理解这条链路时,最重要的方法是把“状态名称”“接口存在”和“运行时真正发生”分开:配置上限不等于业务一定等待到上限,预留存储子状态不等于已经执行存储作业,空的收尾接口不代表已有清理逻辑,继电器控制命令也不代表物理电源已经得到闭环确认。
系列导航:ECU 软件工程系列总纲 | 上一篇:ECU 系统运行状态机设计:从上电启动到休眠、唤醒与 Bootloader