本文框架
- 0.前言
- 1. NVM状态机介绍
- 2. NVM读/写基本逻辑
- 2.1 NVM读操作
- 2.2 NVM写操作
- 2.2.1 实时写
- 2.2.2 下电写
- 2.3 NVM写入注意事项
0.前言
本系列是Autosar存储入门系列,希望能从学习者的角度把存储相关的知识点梳理一遍,这个过程中如果大家觉得有讲得不对或者不够清晰的地方,还请一定指出来,一起探讨,加深学习。
另外根据本人多年的开发经验,做了一些AutosarMCAL配置,通信,诊断,模式管理等实战总结,如果您有需求可以参见AutoSar 实战进阶系列专栏,快速链接:AutoSar实战进阶系列导读
本篇介绍一下Autosar中NVM状态机及读写调用逻辑,基本框架如下:
1. NVM状态机介绍
在NvM模块中,通过异步请求接口NvM_GetErrorStatus()获取Block的状态,可能状态如下:
NVM_REQ_OK:表明对应的异步请求操作成功完成,该状态对应的编号为0,为NvM的初始状态;
NVM_REQ_NOT_OK:表明上一次的异步读写请求操作未成功完成;
NVM_REQ_PENDING:表明当前异步请求读写操作正在进行中;
NVM_REQ_INTEGRITY_FAILED:表明最后一个次的异步请求NvM_ReadBlock或NvM_Read All结果的数据完整性失败,如在NvM_ReadBlock的情况下,RAM块的内容已更改,但已变为无效;
NVM_REQ_BLOCK_SKIPPED:在执行NvM_ReadAll或NvM_WriteAll期间跳过了引用的块,如全部Block都被NvM_ReadAll或NvM_WriteAll期间操作完成则该状态会被设置为NVM_REQ_OK状态;
NVM_REQ_NV_INVALIDATED:需要操作的对应Block是无效的;
NVM_REQ_CANCELED:通过调用NvM_CancelWriteAll取消了多块的请求NvM_WriteAll,或者通过调用NvM_CancelJobs取消了任何单个块作业请求(NvM_ReadBlock、NvM_WriteBlock、NvM_EraseNvBlock、NvM_InvalidateNvBlock和NvM_RestoreBlockDefaults)。
NVM_REQ_RESTORED_FROM_ROM:The referenced NV block had the default values copied to the RAM image.
以上状态的NvM操作过程中都可能会遇到,在一般正常的写操作请求中会遇到最多的状态就是:NVM_REQ_PENDING,NVM_REQ_OK及NVM_REQ_NOT_OK。
2. NVM读/写基本逻辑
接下来,进一步看一下NVM读及写的基本逻辑。
2.1 NVM读操作
在AUTOSAR中有不同的策略来将RAM Block恢复到ECU上次休眠前保存的结果:
1)可以使用NvM_ReadBlock/NvM_ReadPRAMBlock在Rte_Init()期间逐个显式读取单个Block;
2)另一种更好的方法是使用单个NvM请求NvM_ReadAll读取所有Block的结果,在NvM_ReadAll期间要读取的任何块都必须具有显式同步或具有永久RAM块。
一般项目开发中会在EcuM_StartupTwo()期间调用NvM_ReadAll接口实现NvM数据读取。
2.2 NVM写操作
在NVM写操作中按根据存储数据写入时机的不同可分为实时写及下电写,例如对于某些重要的数据,发现其发送改变如一些2E相关的DID存储,但对于一些下线相关的参数可能只需要在下电前存一次即可就没必要实时写,下电前存一次即可。
2.2.1 实时写
在SWC实际运行中,通过调用NvM_WriteBlock()来对单个Block执行写操作,对应的时序操作如下:
需要注意的是,虽然是实时写,但对于NvM的操作仍然是异步的,需要在NvM_MainFunction()中周期性的去判断Block状态是否为Pending,如选择了CRC校验的话NVM还会根据当前CRC与Block中的CRC值对比是否有变化,如CRC不同并对并执行对应的操作。
在NvM_MainFunction()中会继续调用MemIf及底层接口对Block进行操作,例如当选Fls做模拟EEPROM时的调度逻辑。
2.2.2 下电写
在NvM的Block属性配置中,有一个WriteAll的选项,该选项配置与否意味着该Block在NvM_WriteAll()接口调用时是否写该Block。
一般NvM_WriteAll()接口是在下电前,在BswM执行下电逻辑的时候,调用NvM_WriteAll进行所有数据的下电存储,存储完成后ECU进入Shutdown或Sleep状态。
2.3 NVM写入注意事项
如有不同SWC操作同一Block进行存储的情况,需要注意在Block操作前需要调用NvM_GetErrorStatus()判断接口状态,如Block为Pending状态时不能直接写,否则程序会出问题(进Det等导致程序跑飞)。