分享

学习笔记——NVM数据处理机制

 Kuai2012 2022-04-26

上图同时展示了整个 NvM Stack 的构成。
如上图所示,AUTOSAR规定,App只能通过NvM(NVRAM Manager)来访问NV Memory(比如FLASH)。

01


支持的同步机制(Synchronization Mechanism)

根据App对NvM Block'’s RAM的访问方式,数据同步机制可以分为两种:
隐式同步(Implicit synchronization)
显示同步(Explicit synchronization)
1.1 Implicit synchronization
AUTOSAR规范:在隐式同步机制下,一个NvM Block的 RAM 被映射到一个固定的 SWC,不建议共享RAM。每当SW-C使用RAM block(temporary/permanent)访问NVRAM时,都必须确保RAM块的数据一致性,直到NvM完成正在进行的操作为止。
说人话:
在隐式同步机制下,RAM block 和 SWC 之间是一一对应的关系,其他SWC不能访问该RAM。SWC要保持数据的一致性是说,从SWC调用NvM接口到NvM内部操作完成前,SWC不能再改变该RAM中的值。但是该RAM可以被read。
补充(个人理解):
temporary RAM:一般指局部变量;
permanent RAM:一般指全局变量。
使用隐式同步机制时分参考步骤:
1.2 Explicit synchronization
AUTOSAR 规范:在显式同步中,NvM会定义一个RAM mirror,用于与App的RAM block交换数据。App将数据写入RAM block,然后调用NvM Write API(NvM_WriteBlock / NvM_WritePRAMBlock)。NvM 调用API(NvMWriteRamBlockToNvM)将数据从 RAM Block 拷贝到RAM Mirror,进而写入 NV Block。
显示同步的优点:
1、App可以更好地管理自己的RAM block。在App调用NvM_WriteBlock / NvM_WritePRAMBlock 到NvM 调用NvMWriteRamBlockToNvM()这段期间,App仍然可以修改RAM block中的数据。
2、几个SWC可以共享一个NvM Block;
显示同步的缺点:
浪费内存:除了RAM block,又多了一个RAM Mirror(additional RAM),且RMA Mirror需要和使用显示同步机制的最大的NvM Block 具有相同的大小;
多了一步RAM间的拷贝操作:即多了RAM block 和 RAM mirror之间的拷贝操作;

02


其他机制

2.1 CRC 机制
NvM模块内部使用CRC生成例程(8/16/32bit)来对 NvM Block 进行相关的检查。当然是否使用CRC是可以配置的。NvM模块内的配置选项为 NvMBlockUseCRCCompMechanism,启用后,如果将要写入的数据(即RAM中的数据)没有改变,则NvM写入请求会被跳过。基于此,使用CRC的风险在于:如果RAM中的数据内容改变了,但是改变前后计算得出的CRC一致,就会导致数据无法正常写入。因此,此选项应仅用于可以容忍此风险的 NvM Block 。
2.2 错误恢复
2.2.1 对于 Read 操作的错误恢复机制
1. 隐式错误恢复:
NvM 模块对于 Native 和 Redundant 类型的NvM Block 的 Read 操作提供隐式的错误恢复机制,即如果配置了 NvMRomBlockDataAddress 或者NvMInitBlockCallback,则加载对应的默认数据。
2. 显示错误恢复:
对于任何管理类型(NATIVE,Redundant,dataset)的NvM Block,如果其配置了ROM数据,都可以使用显示数据恢复机制来恢复数据,方法是调用 NvM_RestoreBlockDefaults()这个API。当然,对于 Dataset类型的NvM block,在调用API之前必须设置相应的Index(指向ROM Block)。
3. 其他
NvM 模块对于Redundant 类型的NvM Block 的 Read 操作还提供一种错误恢复机制,即将默认数据加载到RAM中。
2.2.2 对于 Write 操作的错误恢复机制
即重新重写写操作,不区分NvM Block的管理类型。
2.3 写验证
写验证即为,将RAM block中的数据写入NV block后,立刻将其回读并与RAM Block的原数据内容做比较,如果比较结果不一致:则再次执行写操作,如果启用DET,则同时回向DEM模块报告错误 NVM_E_VERIFY_FAILED;
如果回读比较失败,则不会再次执行读操作。
2.4 NvMSetRamBlockStatusApi
2.4.1 During startup phase (NvM_ReadAll)
对于某些NVRAM块,可能需要保留相应RAM块的数据内容,以免其在NvM_ReadAll() 期间被覆盖,尤其是在NV块中的数据早于RAM块中的数据的场景下(例如当RAM中的数据尚未写入NV block时发生了热复位)。在这种情况下,必须将RAM block分配在复位安全(non-initialized)的RAM区域中,并且必须将配置参数CalcRamBlockCrc==TRUE 和 NvMSetRamBlockStatusApi==TRUE。(·CalcRamBlockCrc==TRUE,意味着相应的NV块也具有/具有 CRC配置)
每当RAM中的数据发生变化时都需要调用NvM_SetRamBlockStatus(blockID,TRUE),NvM 模块会重新计算RAM中的CRC并将其存储在一个内部变量(该变量存储在 reset-fase 区域)。当然前提 NVRAM Block 配置了PIM或启用显示同步机制。
在ReadAll()期间,会重新计算RAM的CRC,如果计算得出的CRC和之前存储的CRC一致,则RAM block的内容不会改变。如果不一致,则会将NV Block中的值读到RAM中(即RAM会重写),如果读失败,则会将使用默认数据恢复RAM(即将ROM中的值读到RAM中或者调用InitBlock )
2.4.2 During shutdown phase (NvM_WriteAll)
如果 NvMSetRamBlockStatusApi == FALSE,则 NvM_WriteAll() 会将所有 NVRAM Block 的RAM的内容拷贝到 NV Block中。当然前提是的这些 NVRAM Block 的要求配置:NvMSelectBlockForWriteAll ==TRUE 并且 配置了NvMRamBlockDataAddress 或者使用显示同步机制。
当然,为了提高 NvM_WriteAll() 的速度,我们可以将那些只有 RAM Block的内容发生变化的 NVRAM Block写到 NV Memory中,这就需要配置 NvMSetRamBlockStatusApi==TRUE。这种场景下,每当 RAM中的内容发生变化时,用户就需要调用 NvM_SetRamBlockStatus(BlockID, TRUE),从而告诉 NvM 模块在 NvM_WriteAll()时要处理该 NVRAM Block。
2.5 Resistant to changed software
NvM 模块的 start-up(即NvM_ReadAll() 的处理过程)行为受2个配置参数 NvMDynamicConfiguration 和 NvMResistantToChang 的影响。
在ECU项目中,如果如何处理NVRAM block的配置变更并不重要,则必须配置参数 NvMDynamicConfiguration==FALSE。对于每个NVRAM Block 的配置参数NvMCalcRamBlockCrc:
NvMCalcRamBlockCrc == FALSE,直接检查NV block 的有效性(validty)。如果检测结果为:
NV Block有效,则将NV block中的数据加载到 其对应的RAM Block。
NV Block无效,则将默认数据加载到RAM中(默认数据通过参数NvMRomBlockDataAddress或参数NvMInitBlockCallback进行配置)。
NvMCalcRamBlockCrc == TRUE ,NvM首先检查其 RAM block 的有效性(validty)。如果检测结果为:
RAM block内容有效,不再检查NV block 的有效性,也不再从NV Block加载数据。
RAM block内容无效,则继续检查NV block 的有效性。如果:
NV Block无效,则将默认数据加载到RAM中(默认数据通过参数NvMRomBlockDataAddress或参数NvMInitBlockCallback进行配置)。
NV Block有效,则将NV block中的数据加载到 其对应的RAM Block。
如果更改了NVRAM block 的配置,而已经存储在NV memory(比如FLASH)中的 NV block 仍与旧配置相对应,则在NvM_ReadAll()过程中可能会出现严重问题。例如,当添加新的NVRAM块时,许多其他块的标识符可能会隐式更改,这可能导致从NV存储器读取错误的数据。
在这种情况下,可以配置NvM模块,使其不使用NV memory 中的数据初始化RAM block。即配置参数 NvMDynamicConfiguration == TRUE。这时候集成商要修改配置参数NvmCompiledConfigID 从而告诉 NvM模块 NVRAM配置已经更改。NvM模块使用单独的NVRAM block 将 NvmCompiledConfigID 的值存储在NV memory中。每次执行启动过程(NvM_ReadAll)时,NvM模块都会将存储在NV memory中的值与配置参数NvmCompiledConfigID的值进行比较。如果两个值不相同,则NV memory 中的值将在下一个shutdown过程(NvM_WriteAll)中被新的配置值所覆盖。
在这种情况下,NvM 在 NvM_ReadAll()过程中会根据配置参数 NvMResistantToChangedSw 来决定如何初始化 NVRAM Blocks:
NvMResistantToChangedSw == FALSE:不管 RAM Block是否有效,都将忽略NV Block中的值,使用默认数据(ROM或InitBlockCallback)加载RAM Block,则必须配置 ;
NvMResistantToChangedSw == TRUE:必须将 NV Block中的数据加载到RAM中,即便是在配置变更的情况下。如此,NvM模块会像没有发生配置变更一样处理 NvM_ReadAll()。
因此,一旦将某个 NVRAM Block 配置为  NvMResistantToChangedSw == TRUE,则集成商必须确保在ECU的整个生命周期内不得更改以下配置参数,否则可能将无法成功地从NV memory 中恢复数据:
  •  NvMResistantToChangedSw (must not be changed from TRUE to FALSE)

  •  ShortName

  •  NvMBlockUseCrc

  •  NvmBlockCrcType (if NvMBlockUseCrc is set to TRUE)

  •  NvMStaticBlockIDCheck

  •  NvmNvramDeviceId

  •  NvmBlockManagementType

  •  NvmNvBlockLength

  •  NvmNvBlockBaseNumber
注意:根据所使用的NvM,Fee和Ea模块的具体实现,可能会施加其他约束。请参考相应的用户手册。

03


总结

总结一下:
NvMNvM_ReadAll()的过程如下:
首先检查NvmCompiledConfigID,看从NV Block中读出的ID和现在配置的ID(RAM中)是否一致:
1、一致,认为没有发生配置变更,正常加载所有NVRAM Block。
2、不一致,认为发生了配置变更,首先检查配置参数 NvMDynamicConfiguration:
2.1、NvMDynamicConfiguration == FALSE,配置已变更,不会读取NV Block中的值到RAM,使用默认数据(ROM或InitBlockCallback)加载RAM Block(具体过程待定,要结合NvM模块的具体实现);
2.2、NvMDynamicConfiguration==TRUE,对于每一个 NVRAM Block,查看参数 NvMResistantToChangedSw:
2.2.1、NvMResistantToChangedSw == FALSE,不管 RAM Block是否有效,都将忽略NV Block中的值,使用默认数据(ROM或InitBlockCallback)加载RAM Block;
2.2.2NvMResistantToChangedSw == TRUE,将 NV Block中的数据加载到RAM中,NvM模块会像没有发生配置变更一样处理 NvM_ReadAll()。
————————————————
版权声明:本文为CSDN博主「慕容静羽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明,已获作者转载许可。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多