1、概述
NvM模块负责管理和从非易失性内存中读写数据。在系统启动和关闭阶段,同步应用程序RAM区的数据。此模块还提供其他服务,例如用于上层数据保护的冗余数据单元。同时,RTE提供了简单灵活和接口(NvData Interface)用于非易失内存的数据处理。
AUTOSAR4.2.2配置指导如下:
从AUTOSAR的描述可以看出总共牵涉三个模块,NvMBlockDescriptor、NvMCommon与NvmDemEventParameterRefs。
配置思维导图如下
2、NvMCommon
用于通用配置选项的容器。
配置实例如下:
NvMApiConfigClass:配置类型,这点相关联的点是NVM的APIs,打开的哪些,关闭哪些。
NvMBswMMultiBlockJobStatusInformation:该参数指定是否通知BswM当前多块作业的状态。
True:如果ReadAll和WriteAll开始、完成、取消,则调用BswM_NvM_CurrentJobModestarted。
False:不通知BswM。
例如下面调用:
NvMCompiledConfigId:唯一标识NV内存布局的配置ID。这个配置ID应该被发布,例如SW-C应该有可能将其写入NV内存。
NvMCrcNumOfBytes:[NVM493_Conf]如果至少为一个永久RAM块配置了CRC(重)计算,则该参数定义了在一个作业处理周期内应处理的最大字节数。当前版本的NvM不支持此功能,因此当前会忽略给定的设置。个人理解这就是CRC所占用的字节数。
NvMDatasetSelectionBits:不知道为什么ETAS的没有,但是这个配置项较为重要,一定要记录。定义最低有效位的数量,该位数将用于在内存硬件抽象接口内对NVRAM块的某个数据集进行寻址。
0 . .8:用于数据集或冗余块的位数寻址。
0:根本不配置数据集或冗余NVRAM块,不需要选择位。
1:配置了冗余NVRAM块,但没有配置数据集NVRAM块。
NvMDrvModeSwitch:预处理器开关,允许在执行NvM_ReadAll和NvM_WriteAll时将内存驱动切换到快速模式。true:启用快速模式。false:关闭快速模式。ETAS的NVM是不支持此特性的。
NvMDynamicConfiguration:预处理器开关启用NvM_ReadAll请求的动态配置管理处理。
true:启用动态配置管理处理。
false:禁用动态配置管理处理。
NvMJobPrioritization:预处理器开关启用作业优先级处理
true:启用作业优先级处理。
false:禁用作业优先级处理。
NvMMainFunctionCycleTime:理论上NvMMainFunctionCycleTime在4.2.2是移除了的,但是ETAS依旧存在,并且配置这个有效果的。
定义NvM主函数周期性调用的周期时间,单位为秒。如果将周期时间设置为0,则在后台任务中执行NvMM主函数。
NvMMainFunctionPeriod:连续调用主函数之间的间隔,以秒为单位。项目工程里面这个没填写,依据ETAS的Demo就是这样,所以这个点是不理解的点。
注意点:NvMMainFunctionPeriod与NvMMainFunctionCycleTime配置生成文件里面没有体现,直接在RTE_Editor里面进行匹配了。
NvMMultiBlockCallback:在每个异步多块请求终止时调用的通用回调例程的名称(NvM Rb firstitall, NvM ReadAll,移除非必要更改的SW块或NvM WriteAll)。如果显式地想要指定不调用这样的回调例程,请在这里输入NULL_PTR。
NvMPollingMode:定义NvM与内存介质驱动程序通信的方式。如果设置为true,则NvM MainFunction在某些操作正在进行时从这些驱动轮询状态。如果设置为false,媒体驱动程序将通过NvM提供的专用回调函数异步报告操作状态的任何更改。NvM不支持来自内存介质驱动程序的异步通知,因此该参数目前必须始终设置为true。
NvMRbSetWriteAllTriggerApi:启用/禁用NvM Rb SetWriteAllTrigger API。这个API允许触发WriteAll参与独立于RAM块状态或块当前是否繁忙。
NvMRepeatMirrorOperations:定义在延迟当前作业之前,让应用程序从NvM模块的镜像复制数据的重试次数。较低的多重性被设置为0。实际上,如果没有任何块被配置为使用显式同步,则不必配置此参数。参见块配置中的NvMBlockUseSyncMechanism参数。
定义重试次数,以便让应用程序将数据复制到或从NvM模块的镜像,然后再延迟当前作业。
NvMSetRamBlockStatusApi:是否打开NvM_SetRamBlockStatus的API。
NvMSizeImmediateJobQueue:定义当前优先级作业队列的队列条目数。此参数仅在nvmjobpriority参数设置为true时适用。
NvMSizeStandardJobQueue:定义标准作业队列的队列条目数。
3、NvMBlockDescriptor
配置NVM的Block信息。
简要配置图示如下:
NvMBlockCrcType:选择的CRC类型,配置参数需配置NVM_BLOCK_USE_CRC==true
NvMBlockHeaderInclude:定义包含的头文件名。
NvMBlockJobPriority:定义NVM块的优先级,上面有介绍1代表可以多个块的读写。
NvMBlockManagementType:管理块的类型
NVM_BLOCK_DATASET | 1个NVblock |
NVM_BLOCK_NATIVE | 2个NVblock |
NVM_BLOCK_REDUNDANT | 1…255个NVblock |
NvMBlockUseAutoValidation:定义RAM块是否应在关机阶段自动验证。有个问题,验证花费时间,是不是不利于存储呢?
NvMBlockUseCrc:是否使用CRC。
NvMBlockUseSyncMechanism:定义NV块是否使用带有RAM镜像的显式同步机制和用于向NvM模块的RAM镜像传输数据的回调例程。如果使用同步机制,则为True,否则为false。此处False,那么就是隐式同步。
NvMBlockWriteProt:定义NV块的初始写保护
true:开启初始块写保护。
false:不开启初始块写保护。
NvMCalcRamBlockCrc:定义用于配置为使用显式同步机制的永久RAM块或NVRAM块的CRC (re)计算。true:将(重新)计算此永久RAM块的CRC。false:不会(重新)计算此永久RAM块的CRC。
NvMInitBlockCallback:块特定回调例程的入口地址,如果没有,则调用该例程ROM数据可用于初始化NVRAM块。如果没有配置,则不会调用特定的回调例程来初始化具有默认数据的NVRAM块。
NvMMaxNumOfReadRetries:最大尝试读的次数
NvMMaxNumOfWriteRetries:最大尝试写的次数。
NvMNvBlockLength:以字节为单位NV数据的长度、不包含CRC字节。
NvMNvBlockNum:定义NV块的数量,NATIVE形式的为1个。
NvMNvramBlockIdentifier:通过唯一的块标识符标识NVRAM块。这个在ETAS里面无需配置,会自动按照顺序生成。
NvMNvramDeviceId: NVRAM块所在设备的标识。与AUTOSAR的NvM规范相反,这不是来自Ea/Fee模块配置上的块配置的参数,而是在这里直接指定设备标识符(Ea/Fee块配置完全自动生成)。此外,设备ID 0固定为地址Fee,设备ID 1以后固定为地址Eep设备。
NvMRamBlockDataAddress:定义RAM块数据的起始地址。如果不配置,则所选块管理类型没有永久RAM数据块可用。
NvMReadRamBlockFromNvCallback:块特定回调例程的入口地址,为了让应用程序将数据从NvM模块的镜像复制到RAM块中,应该调用该例程。实现类型:Std_ReturnTypeE_OK:复制成功E_NOT_OK:复制不成功,回调例程将再次调用
NvMResistantToChangedSw:定义NVRAM块是否应被处理为不受配置更改的影响。如果在配置时没有可用的默认数据,则应用程序应负责提供默认初始化数据。在这种情况下,应用程序必须使用NvM_GetErrorStatus()来区分首次初始化和损坏的数据。true: NVRAM块不受软件更改的影响。false: NVRAM块不抵抗软件更改。
NvMRomBlockDataAddress:定义ROM块数据的起始地址。如果不配置,则所选块管理类型没有可用的ROM块。
NvMRomBlockNum:根据给定的块管理类型,定义连续区域内多个ROM块的数量。允许的ROM块数量0..1表示本机块或冗余块, 0..n对于一个数据集块。此外,还必须满足以下条件: NvMNvBlockNum + NvMRomBlockNum <=255
NvMSelectBlockForReadAll:定义在NvM_ReadAll期间是否处理NVRAM块。此配置参数仅对那些配置为具有永久RAM块或配置为使用显式同步机制的NVRAM块有影响。true: NvM_ReadAll处理NVRAM块false: NvM_ReadAll不处理NVRAM块
NvMSelectBlockForWriteAll:定义在NvM_WriteAll期间是否处理NVRAM块。此配置参数仅对那些配置为具有永久RAM块或配置为使用显式同步机制的NVRAM块有影响。true: NvM_WriteAll处理NVRAM块false: NvM_WriteAll不处理NVRAM块。
NvMSingleBlockCallback:执行此块的回调函数。
NvMStaticBlockIDCheck:定义是否启用静态块ID检查。
false:不启用静态块ID校验。
true:启用静态块ID检查。
NvMWriteBlockOnce:定义首次写后的写保护。NVRAM管理器在NV块第一次写入后设置写保护位。这意味着在第一次初始化之后,NVRAM中的一些NV块不应该被擦除,也不应该被默认的ROM数据替换。
true:定义首次写后写保护。
false:禁用首写后写保护。
NvMWriteRamBlockToNvCallback:块特定回调例程的入口地址,为了让应用程序将数据从RAM块复制到NvM模块的镜像,应该调用该例程。实现类型:Std_ReturnTypeE_OK:复制成功E_NOT_OK:复制不成功,回调例程将再次调用
NvMWriteVerification:定义是否启用了写验证。false:不开启写校验。true:开启写校验。
NvMWriteVerificationDataSize:[NVM538 Conf]定义写校验时比较RAM块内容和块读回内容时每一步比较的字节数。如果已禁用该块的写校验特性,则忽略该参数。
4、配置生成代码浅析
在ISOLAR-AB工具里面,NVM只生成了两个配置文件NvM_Cfg.c与NvM_Cfg.h,分析一下生成了什么。
NvM_Cfg.c分析
const NvM_Prv_BlockDescriptor_tst NvM_Prv_BlockDescriptors_acst
描述块相关的信息,这些是由配置决定的。
注意一下:
FeeConf_FeeBlockConfiguration_ECUM_CFG_NVM_BLOCK在FEE里面并没有配置,但是出现在了FEE的配置文件Fee_Cfg.h里面了,符合前面文章介绍的FeeBlockConfiguration无需配置,ISOLAR-AB工具会自己匹配的说法。
NvM_Prv_BlockLengths_acu16是索引此配置项数据长度的配置
NvM_Prv_RamBlockAdr_acpv是RAM存储空间的索引
注意一下,上图并未显示ROM Block数据地址,因为截的图比较特殊,是与ECUM的关联,配置自己生成的,假设配置了,此处会显示的。
const uint16 NvM_Prv_BlockLengths_acu16
描述了配置block的数据长度。
const NvM_Prv_PersId_BlockId_tst NvM_Prv_PersId_BlockId_acst描述配置块的ID信息。
void * const NvM_Prv_RamBlockAdr_acpv描述RAM地址信息列表。
提供一种策略:
1、上电ReadAll之后
2、预留一个前置缓存区,ReadAll之后会将数据放置在RAM里面,再准备一个RAM,属于前置RAM,开启任务之前前置RAM全是0,与读取之后的RAM比较,不一致,通过RTE将数据传输到其他SWC。
3、在周期任务起来之后,考虑到用比较方式进行NVM存储,比较方式即为当数据有所更改的时候再存储,需要在NVM的SWC进行自身的P与R Port交互,先将RAM数据复制到前置RAM,然后再将RAM数据发给NVM的SWC,当然这个过程只需要上电执行一次即可,之后就进行放数据更改时刻存NVM,当NVM数据更改时候通过RTE告知其他SWC。