前言很多工程师第一次接触AUTOSAR NvM时都会有一个疑问ECU断电以后车辆重新上电后里程、配置参数、学习值等Flash里的数据到底什么时候搬到RAM是谁触发的NvM、Fee、MemIf、Fls之间到底是什么关系今天我们从ECU真实启动流程出发把AUTOSAR非易失存储Non Volatile Memory的完整工作机制一次讲透。第一章 ECU上电后变量为什么能够“自动恢复”在汽车电子开发过程中经常会遇到这样的场景RAM虽然速度快但是它有一个致命特点掉电丢失。例如MCU运行时RAM: VehicleConfig 5 Mileage 123456km LearningValue 200如果突然断电RAM ↓ 数据消失但是FlashFlash: VehicleConfig 5 Mileage 123456km LearningValue 200依然存在。所以汽车ECU必须解决一个问题如何在重新上电以后把Flash里的历史数据恢复到RAM让软件继续运行这就是AUTOSAR NvM存在的意义。NvM到底保存什么很多人认为NvM就是保存几个变量。实际上并不准确。NvM管理的是非易失数据生命周期。例如车辆配置数据车型配置 区域配置 功能开关用户数据座椅位置 驾驶模式 空调偏好ECU学习数据发动机学习值 传感器补偿值 控制算法参数故障相关数据DTC状态 冻结帧数据 故障计数这些数据都有一个共同特点需要跨越ECU上下电周期保存。因此运行期间RAM负责快速访问。掉电保存RAM ↓ NvM ↓ Flash重新启动Flash ↓ NvM ↓ RAM第二章 ECU启动全过程NvM到底什么时候开始工作很多工程师第一次调试启动问题时会认为上电 ↓ NvM读取数据 ↓ 应用启动实际上真实AUTOSAR启动链路更加复杂。一个典型ECU启动过程如下这里有几个关键点。1. Startup Code阶段MCU刚复位以后首先执行的是启动代码。主要完成Stack初始化CPU寄存器配置Cache配置RAM初始化.data拷贝.bss清零。例如C语言uint32 Counter 100;编译后初始值Flash | | 100启动Flash ↓ RAM Counter100这属于C语言变量初始化。和NvM没有关系。2. .bss变量初始化例如uint32 Counter;没有初始值。启动RAM清零结果Counter0所以普通变量Startup Code负责NvM变量NvM负责这是两个完全不同的机制。3. BSW启动阶段进入AUTOSAR BSW以后开始初始化EcuMBswMOSCommunication StackNvM其中NvM初始化非常关键。第三章 AUTOSAR存储架构NvM、MemIf、Fee、Fls到底是什么关系AUTOSAR设计最大的特点就是分层。应用不应该关心底层Flash如何擦写。因此形成NvM非易失存储管理器NvM是最上层。主要负责1. Block管理例如Block ID: 100 Length: 64 Byte RAM Address: 0x700010002. 数据恢复启动Flash ↓ RAM3. CRC检查判断Flash里面的数据是否有效。4. 默认值恢复如果Flash数据损坏使用ROM Default。MemIf存储抽象层MemIf全称Memory Interface。作用屏蔽下面存储差异。对于NvM来说它不知道下面到底是EEPROM还是Flash模拟EEPROM统一调用MemIf_Read() MemIf_Write()FeeFlash EEPROM Emulation现代汽车MCU很多没有真正EEPROM。例如Infineon AURIX TC3xx。通常使用内部Flash模拟EEPROM。因此NvM Block不会直接对应Flash地址。中间经过NvM ↓ Fee ↓ Flash SectorFee负责Block管理地址映射Flash擦写Wear Leveling。FlsFlash Driver最底层负责真正操作硬件Flash。例如Erase Sector Program Page Read Data第四章 NvM Block到底是什么Flash数据如何进入RAM理解NvM最核心的概念就是BlockAUTOSAR不会直接保存变量。而是保存Block。例如车辆配置NvM Block 20 长度: 128 Byte里面包含车型 区域 功能配置 校验信息一个Block通常包含NvM Block / \ Flash RAM 保存副本 工作副本为什么需要RAM Mirror因为应用运行频率很高。如果每10ms读取FlashRunnable ↓ Flash ↓ 返回数据会导致延迟增加CPU负载增加Flash寿命降低。所以设计启动读取一次Flash ↓ RAM运行期间Application ↓ RAM需要保存RAM ↓ Flash第五章 NvM ReadAll全过程Flash数据如何真正加载到RAM这是整个NvM最核心流程。很多工程师知道NvM_ReadAll()但是不知道里面发生了什么。下面拆开。Step1NvM_Init()系统启动调用NvM_Init()它负责创建Block管理表初始化RAM映射初始化内部状态。但是注意NvM_Init不会读取Flash。很多调试问题都来源于这里。Step2NvM_ReadAll()真正的数据恢复发生在NvM_ReadAll()流程假设读取NvM Block 50过程① 查询Block配置NvM知道Block ID: 50 RAM地址: 0x70002000 长度: 64Byte② 请求底层读取调用MemIf_Read()③ Fee定位Flash位置例如Fee内部管理Block50 Sector 12 Offset 0x500④ Flash读取返回Data CRC Header⑤ CRC检查如果正确Flash Data ↓ RAM Mirror如果错误ROM Default ↓ RAM Mirror第六章 为什么第一次启动是默认值第二次启动才恢复这是生产项目中非常常见的问题。很多工程师测试第一次刷程序发现参数正确第二次启动发现参数变化为什么第一次启动ECU刚生产Flash没有有效数据启动NvM_ReadAll ↓ CRC失败 ↓ 加载ROM Default ↓ RAM例如默认语言: 中文 车型: SUV运行过程中用户修改语言: 英文执行NvM_WriteBlock()保存RAM ↓ NvM ↓ Flash第二次启动Flash有效数据于是Flash ↓ RAM所以第一次默认值。第二次保存值。第七章 工程中最容易踩坑的NvM问题问题1数据写成功但是掉电丢失现象测试过程中NvM_WriteBlock成功但是重新上电数据恢复失败。原因可能NvM_MainFunction没有周期运行NvM很多操作异步执行。例如NvM_WriteBlock() ↓ 等待NvM_MainFunction处理 ↓ Fee写Flash如果系统马上掉电Flash还没有完成。问题2应用启动后读取到默认值现象偶现。原因启动顺序错误。例如错误OS启动 ↓ Runnable运行 ↓ NvM_ReadAll正确NvM_ReadAll完成 ↓ RTE启动 ↓ Runnable运行问题3软件升级后NvM数据异常原因Block结构变化。例如旧版本Block: 64 Byte新版本Block: 128 ByteCRC失败。解决NvM MigrationBlock版本管理默认恢复。问题4多核启动同步问题现代域控制器例如AURIX TC3xx可能Core0BSW NvMCore1Application如果Core1提前运行读取RAM Mirror可能得到无效数据。必须NvM Ready ↓ Application Start第八章 从传统ECU到智能汽车为什么NvM越来越重要过去一个ECU几十个配置参数。现在智能汽车一个域控制器可能保存自动驾驶配置用户画像OTA状态学习数据故障历史网络配置安全密钥状态。NvM的重要性越来越高。它已经不是简单的数据存储模块。而是ECU软件可靠运行的基础设施。总结汽车软件看到的不是Flash已经恢复好的RAM数据所以当你下一次看到不要只认为它是两个API。背后实际上是一套完整的数据生命流程这才是AUTOSAR NvM真正解决的问题。