文章目录
- 基础架构指南
- 分层结构
- 存储器硬件抽象的寻址机制
- 例子
- 基本储存对象
- NV块
- RAM块
- ROM块
- 管理块
- NV块头
- 块管理类型
- 块管理类型概述
- NVRAM块结构
- NVRAM 块描述符表
- Native NVRAM 块
- Redundant NVRAM块
- Dataset NVRAM块
- NVRAM管理器API配置类
- 扫描顺序/优先级机制
- 通常行为
- 功能要求
- 设计要点
- NVRAM管理器启动
- NVRAM管理器关闭
- 对NvM模块的(准)并行写访问
- NVRAM块一致性检查
- 错误恢复
- 具有ROM数据的RAM块的恢复
- 使用ROM默认数据的RAM块的隐式恢复
- 用ROM默认数据显式恢复RAM块
- 对NV块的未完成写操作的检测
- 单个块请求的终止
- 多块请求的终止
- 异步请求/作业处理的一般处理
- NVRAM块写保护
- RAM块数据的验证和修改
- 有效/未更改状态
- 有效/已更改状态
- 无效/未更改状态
- 应用程序和NVRAM管理器之间的通信和隐式同步
- 写请求(NvM_WriteBlock或NvM_WritePRAMBlock)
- 读取请求(NvM_ReadBlock或NvM_ReadPRAMBlock)
- 恢复默认请求(NvM_RestoreBlockDefaults和NvM_RestorePRAMBlockDefaults)
- 多块读取请求(NvM_ReadAll)
- 多块写请求(NvM_WriteAll)
- 取消操作(NvM_CancelWriteAll)
- 管理块的修改
- NVRAM块的正常和扩展运行时准备
- 应用程序和NVRAM管理器之间的通信和显式同步
- 写请求(NvM_WriteBlock或NvM_WritePRAMBlock)
- 读取请求(NvM_ReadBlock或NvM_ReadPRAMBlock)
- 多块读取请求(NvM_ReadAll)
- 多块写请求(NvM_WriteAll)
- 静态块ID检查
- 读取重试
- 写入验证
- 比较NvM中的NV数据
- NvM和BswM交互
- 块锁定情况下的NvM行为
- 示例
- 使用情况(按DCM):
- 块压缩
- 块加密
- 时序图
- 同步调用
- NvM_Init
- NvM_SetDataIndex
- NvM_GetDataIndex
- NvM_SetBlockProtection
- NvM_GetErrorStatus
- NvM_GetVersionInfo
- 异步调用
- 使用轮询的异步调用
- 使用回调的异步调用
- 多块请求的取消
- BSWM交互
NvM模块应,依据在车辆环境下各自的要求,保证NV(non volatile)数据的存储和维护服务。NvM模块可以管理EEPROM和FLASH EEPROM模拟设备的NV数据。NvM需要提供管理和维护NV数据所要求的同步/异步服务。不同块之间的关系如下图所示:
基础架构指南
分层结构
下图所示为与NvM存在交互的模块:
存储器硬件抽象的寻址机制
存储器抽象接口、底层闪存EEPROM仿真和EEPROM抽象层为NvM模块提供虚拟线性32位地址空间,该空间由16位块号和16位块地址偏移量组成。NvM模块允许(理论上)最多65536个逻辑块,每个逻辑块的(理论上)最大大小为64k字节。
NvM模块应进一步将16位Fee/Ea块号细分为以下部分:
• 位宽为(16 -NVM_DATASET_SELECTION_BITS)的NV块基础编号(NVM_NV_BLOCK_BASE_NUMBER);
• 位宽为(NVM_DATASET_SELECTION_BITS)的数据索引;
冗余NVRAM块的处理/寻址应以存储器硬件抽象完成,与数据集NVRAM块相同,即冗余NV块应通过使用配置参数NvMDatasetSelectionBits进行管理。
NV块基数(NVM_NV_BLOCK_BASE_NUMBER)应位于Fee/Ea块号的最高有效位。
配置工具应配置块标识符,NvM模块不能修改已配置的块标识符。
例子
为了阐明前面描述的用于NVRAM管理器和储存器硬件抽象接口之间的寻址机制,一下例子可以帮助理解NVRAM管理器侧的配置参数NvMNvBlockBaseNumber, NvMDatasetSelectionBits和储存器硬件抽象测的配置参数EA_BLOCK_NUMBER / FEE_BLOCK_NUMBER之间的相互关系。
针对给出例子A和B,使用如下简单的公式:
FEE/EA_BLOCK_NUMBER = (NvMNvBlockBaseNumber << NvMDatasetSelection Bits) + DataIndex.
例A:
• 配置参数NvMDatasetSelectionBits配置为2,这导致配置参数NvMNvBlockBaseNumber的可用范围为14bits;
• NvMNvBlockBaseNumber的范围:0x1…0x3FFE
• 数据索引的范围:0x0…0x3(=2ˆNvMDatasetSelectionBits-1)
• FEE_BLOCK_NUMBER/EA_BLOCK_NUMBER的范围:0x4…0xFFFB
在这种配置下,使用前面提到的公式计算的FEE/EA_BLOCK_NUMBER应如下例所示:
对于NvMNvBlockBaseNumber = 2的native类型NVRAM:
• 使用FEE/EA_BLOCK_NUMBER = 8 访问NV块
对于NvMNvBlockBaseNumber = 3的redundant类型NVRAM:
• 数据索引为0的第一个NV块使用FEE/EA_BLOCK_NUMBER = 12访问;
• 数据索引为1的第二个NV块使用FEE/EA_BLOCK_NUMBER = 13访问;
对于NvMNvBlockBaseNumber = 4, NvMNvBlockNum = 3的dataset类型NVRAM:
• 数据索引为0的NV块#0以FEE/EA_BLOCK_NUMBER = 16访问;
• 数据索引为1的NV块#1以FEE/EA_BLOCK_NUMBER = 17访问;
• 数据索引为2的NV块#2以FEE/EA_BLOCK_NUMBER = 18访问;
例B:
• 配置参数NvMDatasetSelectionBits被配置为4。这导致12位可用作配置参数NvMNvBlockBaseNumber的范围。
• NvMNvBlockBaseNumber的范围:0x1…0xFFE
• 数据索引的范围:0x0…0xF(=2ˆNvMDatasetSelectionBits-1)
• FEE/EA块号范围:0x10…0xFFEF
基本储存对象
NV块
NV块是基本存储对象,代表由NV用户数据和(可选的)CRC值和(可选的)NV块头组成的存储区域。
上图不代表NV块在实际物理内存的上的分布,只代表逻辑上分布。
RAM块
RAM块是一个基本的存储对象,代表RAM中的一个区域,由用户数据和(可选的)CRC值和(可选的)NV块头组成。
RAM块上CRC使用是有限制的:仅当相应NV模块也有CRC时,CRC才可用。CRC必须与相应NV模块的类型相同。
RAM块的用户数据区可以位于与RAM块状态不同的RAM地址位置(全局数据部分)。
RAM块的数据区应可从NVRAM管理器和应用程序侧访问(数据从/向相应的NV块传递)。
该图不代表RAM模块的物理内存布局,只表示逻辑上的分布。
由于NvM模块不支持对齐,这可以通过配置来管理,即可以通过添加填充来增加块长度,以满足对齐要求。
RAM块数据应包含永久或临时分配的用户数据。在永久分配用户数据的情况下,RAM块数据的地址在配置期间是已知的。在临时分配用户数据的情况下,RAM块数据的地址在配置期间是未知的,并且将在运行期间被传递到NvM模块。
可以在全局RAM区中分配每个RAM块,而没有地址限制。配置的RAM块的总数不需要位于连续的地址空间中。
ROM块
ROM块是基本存储对象,在ROM(闪存)中,用于在NV块为空或损坏时提供默认数据。
管理块
管理块应位于RAM中,并应包含一个与数据集NV块一起使用的块索引。此外,应包含相应NVRAM块的属性/错误/状态信息。
在显式同步(无效/有效)的情况下,NvM模块应使用NvM模块中永久RAM块或RAM镜像的状态信息来确定永久RAM块用户数据的有效性。
RAM块状态“无效”表示相应RAM块的数据区无效。RAM块状态“有效”表示相应RAM块的数据区有效。“无效”的值表示除“有效”之外的所有其他值。
管理块对于应用程序来说应该是不可见的,由NvM模块专用于RAM块和NVRAM块本身的安全和管理。
NvM模块应使用属性字段来管理NV块写保护,以保护/解除保护NV块数据字段。
NvM模块应使用错误/状态字段来管理上一次请求的错误/状态值。
NV块头
如果启用了静态块ID机制,NV块头应首先包含在NV块中。
块管理类型
块管理类型概述
NvM模块支持以下类型的NVRAM存储:
• NVM_BLOCK_NATIVE
• NVM_BLOCK_REDUNDANT
• NVM_BLOCK_DATASET
NVM_BLOCK_NATIVE类型的NVRAM存储应包括下列基本存储对象:
• NV Blocks: 1
• RAM Blocks: 1
• ROM Blocks: 0…1
• Administrative Blocks:1
NVM_BLOCK_REDUNDANT类型的NVRAM存储应包括以下基本存储对象:
• NV Blocks: 2
• RAM Blocks: 1
• ROM Blocks: 0…1
• Administrative Blocks:1
NVM_BLOCK_DATASET类型的NVRAM存储应包括以下基本存储对象:
• NV Blocks: 1…(m<256)*
• RAM Blocks: 1
• ROM Blocks: 0…n
• Administrative Blocks:1
• * 可能的数据集数量取决于配置参数NvMDatasetSelectionBits.
NVRAM块结构
NVRAM块应由强制基本存储对象NV块、RAM块和管理块组成。基本存储对象ROM块是可选的。
任何NVRAM块的组成在配置期间由相应的NVRAM块描述符固定。
所有地址偏移量都是相对于NVRAM块描述符中RAM或ROM的起始地址给出的。假设起始地址为零。
提示:如果需要,设备特定的基址或偏移量将由相应的设备驱动程序添加。
NVRAM 块描述符表
通过提供随后分配的块ID,将经由NvM模块API选择要处理的单个NVRAM块。
所有与NVRAM块描述符表相关的结构及其在ROM(闪存)中的地址都必须在NvM模块配置期间生成。
Native NVRAM 块
Native NVRAM块是最简单的块管理类型。它允许以最小的开销存储到NV存储器或从NV存储器中读取数据。
Native NVRAM块由单个NV块、一个RAM块和一个管理块组成。
Redundant NVRAM块
除了Native NVRAM块之外,冗余NVRAM块还提供了增强的容错能力、可靠性和可用性。它增加了对数据损坏的抵抗力。
Redundant NVRAM块由2个NV块、一个RAM块和一个管理块组成。
下图反映了冗余NV模块的内部结构:
注:此图不代表冗余NVRAM块的物理NV内存布局,仅表示逻辑上的布局。
如果与冗余NVRAM块相关联的一个NV块被视为无效(例如,在读取期间),则应尝试使用来自未损坏的NV块的数据来恢复NV块。如果恢复失败,则应报告到DEM故障码NVM_E_LOSS_OF_REDUNDANCY。
注:“恢复”表示重新建立冗余。这通常意味着将恢复的数据写回NV模块。
Dataset NVRAM块
Dataset NVRAM块是一个与数据块(NV/ROM)大小相等的数组。应用程序一次只能访问这些元素中的一个。
Dataset NVRAM 块包含多个NV用户数据,(可选的)CRC区域,(可选的)NV块头,一个RAM块和一个管理块。
数据集的索引位置通过相应管理块中的一个单独字段来表示。
NvM模块应能够读取所有分配的NV块。仅当写保护被禁用时,NvM模块才能够写入所有分配的NV块。
如果选择基本存储对象ROM块作为可选部分,则通常选择数据集的索引范围被扩展到ROM,使得可以选择ROM块而不是NV块。该索引涵盖了可能构成NVRAM数据集块的所有NV/ROM块。
NvM模块应只能读取可选ROM块(默认数据集)。NvM模块应将对ROM块的写入视为对受保护NV块的写入。配置数据集(NV+ROM块)的总数应在范围1~255.
对于可选ROM块,索引从0到NvMNvBlockNum - 1的数据区代表NV存储器中的NV块及其CRC。索引从NvMNvBlockNum到NvMNvBlockNum + NvMRomBlockNum - 1的数据区代表ROM块。
此图不代表数据集NVRAM模块的物理NV内存布局,仅表示逻辑布局。
NVRAM管理器API配置类
为了能够使NvM模块适应有限的硬件资源,应定义三种不同的API配置类别:
• API配置类3:所有指定的API调用都可用。支持最多的功能。
• API配置类2:中等的API调用集是可用的。
• API配置类1:特别是对于硬件资源非常有限的匹配系统,该API配置类只提供在任何情况下都需要的最小API调用集。
API配置类3应包括以下API:
• Type 1:
• NvM_SetDataIndex(…)
• NvM_GetDataIndex(…)
• NvM_SetBlockProtection(…)
• NvM_GetErrorStatus(…)
• NvM_SetRamBlockStatus(…)
• NvM_SetBlockLockStatus()
• Type 2:
• NvM_ReadBlock(…)
• NvM_WriteBlock(…)
• NvM_RestoreBlockDefaults(…)
• NvM_EraseNvBlock(…)
• NvM_InvalidateNvBlock(…)
• NvM_CancelJobs(…)
• NvM_ReadPRAMBlock(…)
• NvM_WritePRAMBlock(…)
• NvM_RestorePRAMBlockDefaults(…)
• Type 3:
• NvM_ReadAll(…)
• NvM_WriteAll(…)
• NvM_CancelWriteAll(…)
• NvM_ValidateAll(…)
• NvM_FirstInitAll(…)
• Type 4:
• NvM_Init(…)
API配置类2应包括以下API:
• Type 1:
• NvM_SetDataIndex(…)
• NvM_GetDataIndex(…)
• NvM_GetErrorStatus(…)
• NvM_SetRamBlockStatus(…)
• NvM_SetBlockLockStatus(…)
• Type 2:
• NvM_ReadBlock(…)
• NvM_WriteBlock(…)
• NvM_RestoreBlockDefaults(…)
• NvM_CancelJobs(…)
• NvM_ReadPRAMBlock(…)
• NvM_WritePRAMBlock(…)
• NvM_RestorePRAMBlockDefaults(…)
• Type 3:
• NvM_ReadAll(…)
• NvM_WriteAll(…)
• NvM_CancelWriteAll(…)
• NvM_ValidatedAll(…)
• Type 4:
• NvM_Init(…)
API配置类1应包括以下API:
• Type 1:
• NvM_GetErrorStatus(…)
• NvM_SetRamBlockStatus(…)
• NvM_SetBlockLockStatus(…)
• Type 2:
• –
• Type 3:
• NvM_ReadAll(…)
• NvM_WriteAll(…)
• NvM_CancelWriteAll(…)
• Type 4:
• NvM_Init(…)
• 注意:对于API配置等级1,不需要队列,不需要即时数据可以写。此外,API调用NvM_SetRamBlockStatus仅在由NvMSetRamBlockStatusApi配置时可用。
在API配置类1中,不支持块管理类型NVM_BLOCK_DATASET。
NvM模块应仅包含处理配置块类型所需的代码。
扫描顺序/优先级机制
NvM模块应支持基于优先级的作业处理。通过配置参数NvMJobPrioritization,应启用/禁用基于优先级的作业处理。
对于基于优先级的作业处理顺序,NvM模块应使用两个队列,一个用于立即写入作业(crash data),另一个用于所有其他作业(包括立即读取/擦除作业)。
如果通过配置禁用了基于优先级的作业处理,NvM模块将不支持立即写入作业。在这种情况下,NvM模块按FCFS2(First come first served,先到先得)顺序处理所有作业。
源自NvM_ReadAll、NvM_ValidateAll、NvM_FirstInitAll和NvM _ WriteAll APIs的多块请求的作业队列长度应为1(只有一个多块作业排队)。
NvM模块不得通过其他请求中断源自NvM_ReadAll请求的作业;NvM模块不得通过其他请求中断源自NvM_WriteAll请求的作业。唯一例外是具有立即优先级的写作业,它将抢占正在运行的读/写作业。被抢占的作业随后将由NvM模块恢复/重启。NvM模块应该将正在进行的NvM_ReadAll请求期间请求的读取作业排队,并随后执行它们。NvM模块应该将正在进行的NvM_WriteAll请求期间请求的写作业排队,并随后执行它们。
NvM模块应该将正在进行的NvM_ReadAll请求期间请求的写作业排队,并随后执行它们。NvM模块应该将正在进行的NvM_WriteAll请求期间请求的读取作业排队,并随后执行它们。
注意:NvM_WriteAll请求可以通过调用NvM_CancelWriteAll来中止。在这种情况下,当前块被处理完成,但不再写入其他块。
提示:如果请求在相关NVRAM块完成后变得过时,则应允许其出队。
被抢占的作业随后将由NvM模块恢复/重启。此行为应适用于单块请求以及多块请求。
通常行为
功能要求
对于每个异步请求,任务完成后通知调用者是一个可配置的选项。NvM模块应提供回调接口NvMSingleBlockCallback
提示:NvM模块的环境只能通过NvM模块访问非易失性存储器。不允许任何模块(NvM模块除外)直接访问非易失性存储器。
NvM模块仅提供访问NVRAM和共享存储器(RAM)中的块的隐式方式。这意味着,NvM模块将一个或多个块从NVRAM复制到RAM,反之亦然。
根据给定的限制(例如,以同步方式),应用程序直接访问RAM数据。
如果特定ID的块尚未入队或当前正在进行(多任务限制),NvM模块应将所有异步“单块”读/写/控制请求排队。
只要不发生队列溢出,NvM模块应接受多个异步“单块”请求。
NvM模块将从队列中取出最高优先级的请求,并按串行顺序进行处理。
NvM模块应实施隐式机制,对保存在NvM存储器中的数据进行一致性/完整性检查。
根据存储器堆栈的实现,由NvM模块提供和/或调用的回调例程可以在中断上下文中调用。提供在中断上下文中调用的例程的NvM模块因此必须确保它们的运行时间相当短。
如果在配置时没有可用的默认ROM数据,或者NvMInitBlockCallback没有定义回调,则应用程序应负责提供默认初始化数据。在这种情况下,应用程序必须使用NvM_GetErrorStatus()来区分首次初始化和损坏的数据。
在处理NvM_ReadAll期间,NvM模块应能够通过执行校验和计算来检测损坏的RAM数据。在处理NvM_ReadAll期间,NvM模块应能够通过测试管理块内数据的有效性来检测无效RAM数据。
在NvM_ReadAll的启动阶段和正常运行期间,如果NvM模块在NV块中检测到未恢复的错误,NvM模块应将默认数据(如果已配置)复制到相应的RAM块中。
为了使用操作系统服务,NvM模块应仅使用BSW调度器,而不是直接使用操作系统对象和/或相关的操作系统服务。
对RAM (start)与NvMBufferAlignmentValue不一致的情况,NvM模块应使用内部镜像作为所有操作的缓冲区,这些操作使用已配置的永久RAM(或API参数传递的RAM)读写NVRAM块中的RAM块。
设计要点
NVRAM管理器启动
NvM_Init应专门由BSW模式管理器调用。由于对ECU启动时间的严格限制,NvM_Init请求不应包含已配置NVRAM块的初始化。NvM_Init请求不应负责触发底层驱动程序和内存硬件抽象的初始化。这也应由BSW模式管理器处理。
RAM数据块的初始化应由另一个请求完成,即NvM_ReadAll。NvM_ReadAll应专门由BSW模式管理器调用。
使用NvM模块的软件组件应负责检查NvM模块启动产生的全局错误/状态信息。BSW模式管理器应通过使用NvM_GetErrorStatus来轮询(保留块ID 0)或回调通知(可配置选项NvM_MultiBlockCallback),以获取启动产生的全局错误/状态信息。如果使用轮询,应通过全局错误/状态NVM_REQ_OK或NVM_REQ_NOT_OK(在启动NVM_REQ_PENDING期间)来检测NVRAM启动程序的结束。如果选择回调进行通知,软件组件应在分配的NVRAM块已被处理时自动得到通知。
注1:如果为NvM_ReadAll中处理的每个NVRAM块配置了回调,RTE可以使用它们在早期启动SW-Cs
注2:为确保DEM在早期完全可操作,即其NV数据恢复至RAM,DEM相关NVRAM块应配置为具有低ID,以便在NvM_ReadAll中首先处理。
NvM模块不得永久性地自动存储当前使用的数据集索引。
软件组件应通过NvM_GetErrorStatus使用特定块的id来检查其负责的所有块的特定错误/状态,以确定相应RAM块的有效性。
对于块管理类型“NVRAM数据集”的所有块,软件组件应负责通过NvM_SetDataIndex设置适当的索引位置。例如,当前索引位置可以由软件组件存储/维护在唯一的NVRAM块中。为了获取“数据集块”的当前索引位置,软件组件应使用NvM_GetDataIndex API调用。
NVRAM管理器关闭
基本的关机程序应由请求NvM_WriteAll执行, NvM_WriteAll应由BSW模式管理器调用。
对NvM模块的(准)并行写访问
NvM模块应使用排队机制通过异步接口接收请求。NvM模块应根据优先级顺序处理所有请求。
NVRAM块一致性检查
NvM模块应提供隐式技术来检查NVRAM块的数据一致性。NVRAM块的数据一致性检查应通过其相应NV块的CRC重新计算来完成。数据一致性检查的隐含方式由内部功能的可配置选项提供。隐式一致性检查应可针对每个NVRAM块进行配置,并取决于可配置的参数NvMBlockUseCrc和NvMCalcRamBlockCrc。
对于NvMWriteBlockOnce = TRUE的NVRAM块,应启用NvMBlockUseCrc。对于NvMWriteBlockOnce = TRUE的NVRAM块,应禁用NvMBlockWriteProt,以便用户能够在CRC校验失败时将数据写入NVRAM块。
根据可配置参数NvMBlockUseCrc和NvMCalcRamBlockCrc,NvM模块应为所用的最大Crc分配内存。NvM用户不知道RAM块中数据的CRC内存(如大小、位置)的任何信息。
错误恢复
NvM模块应提供错误恢复技术。错误恢复取决于NVRAM块管理类型。NvM模块应通过加载默认值,为每种NVRAM块管理类型提供读取错误恢复。NvM模块应通过加载RAM块的默认值,为块管理类型为NVM_BLOCK_REDUNDANT的NVRAM块提供读取错误恢复。无论NvM块管理类型如何,NvM模块都应通过执行写重试来提供写错误恢复。
如果RAM块重新验证失败,NvM模块应在启动时为所有配置了RAM块CRC的NVRAM块提供读取错误恢复。
具有ROM数据的RAM块的恢复
NvM模块应提供隐式和显式恢复技术,以便在NV块出现不可恢复的数据不一致时,将ROM数据恢复到相应的RAM块。
使用ROM默认数据的RAM块的隐式恢复
在隐式恢复期间,相应NV块的数据内容应保持不变。
在启动(NvM_ReadAll的一部分)期间不应提供隐式恢复,当未配置默认数据(通过参数NvMRomBlock DataAddress或NvMInitBlockCallback)时,NvM_ReadBlock和NvM_ReadPRAMBlock都不应为每个NVRAM块提供隐式恢复。
对于以下情况,在启动期间(NvM_ReadAll的一部分),无论是NvM_ReadBlock还是NvM_ReadPRAMBlock都不能为每个NVRAM块提供隐式恢复:
• 默认数据已配置(通过参数NvMRomBlockDataAddress或参数NvMInitBlockCallback)。
• NvM模块中的永久RAM块或RAM镜像的内容(在显式同步的情况下)状态有效且CRC(数据)一致。
对于以下情况,在启动期间(NvM_ReadAll的一部分),无论是NvM_ReadBlock还是NvM_ReadPRAMBlock都不能为每个NVRAM块提供隐式恢复:
• 默认数据已配置(通过参数NvMRomBlockDataAddress或参数NvMInitBlockCallback)
• NvM模块中的永久RAM块或RAM镜像的内容(在显式同步的情况下)状态无效,CRC(数据)不一致。
• 从NV读取的尝试成功。
隐式恢复应在启动期间(NvM_ReadAll的一部分)由NvM_ReadBlock或NvM_ReadPRAMBlock为每个NVRAM块提供,条件如下:
• 默认数据已配置(通过参数NvMRomBlockDataAddress或参数NvMInitBlockCallback)
• NvM模块中的永久RAM块或RAM镜像的内容(在显式同步的情况下)状态无效,CRC(数据)不一致。
• 从NV读取的尝试失败
对于NVM_BLOCK_NATIVE和NVM_BLOCK_REDUNDANT类型的NVRAM块,应在NvM_ReadBlock()或NvM_ReadPRAMBlock()请求期间提供隐式恢复。
用ROM默认数据显式恢复RAM块
对于ROM块数据的显式恢复,NvM模块应提供函数NvM_RestoreBlockDefaults和NvM_RestorePRAMBlockDefaults,以将ROM数据恢复到其相应的RAM块中。
NvM_RestoreBlockDefaults和NvM_Restore PRAMBlockDefaults函数应保持相应NV块的数据内容不变。
每次需要时,应用程序应使用NvM_RestoreBlockDefaults或NvM_RestorePRAMBlockDefaults函数将ROM数据恢复到相应的RAM块中。
对NV块的未完成写操作的检测
对NV块的不完整写操作的检测超出了NvM模块的职能范围。这由存储器硬件抽象来处理和检测。如果被引用的NV块无效或不一致,并且在被请求时不能被读取,则NvM模块期望从存储器硬件抽象中获取信息。SW-Cs可以使用NvM _ InvalidateNvBlock来防止较低层传递旧数据。
单个块请求的终止
NvM模块提供的所有异步请求(NvM_CancelWriteAll除外)在相应管理块的指定错误/状态字段中显示其结果。
可选配置参数NvMSingleBlockCallback通过回调配置异步块请求终止时的通知(以及对于NvM_ReadAll)。
注1:在与应用软件SW-C通信时,ECU配置参数NvMSingleBlockCallback应配置成相应的Rte_call_<p>_<o> API。
多块请求的终止
NvM模块应使用单独的变量来存储异步多块请求的结果(NvM_ReadAll、NvM_WriteAll,包括NvM_CancelWriteAll、NvM_ValidateAll)。
函数NvM_GetErrorStatus应返回异步多块请求(包括NvM_CancelWriteAll)的最新错误/状态信息,结合保留块ID值0。
多块请求的结果应仅代表普通错误/状态信息。NvM模块提供的多块请求应在每个受影响管理块的指定错误/状态字段中指明其详细的错误/状态信息。
可选配置参数NvMMultiBlockCallback通过回调配置异步多块请求终止时的通知。
异步请求/作业处理的一般处理
每次在请求中处理CRC计算时,如果参考的NVRAM块长度超过参数NvMCrcNumOfBytes配置的字节数,NvM模块应分多步计算CRC。
对于CRC计算,NvM模块应使用CRC模块公布的初始值。
多个并发单块请求应可排队。
NvM模块应中断异步请求/作业处理,以支持具有立即优先级的作业(crash数据)。
如果NvM模块上异步函数的调用导致作业队列溢出,该函数应返回E_NOT_OK。
请求成功入队后,NvM模块应将相应NVRAM块的请求结果设置为NVM_REQ_PENDING。
如果NvM模块已经成功处理了一个任务,它应该返回NVM_REQ_OK作为请求结果。
NVRAM块写保护
NvM模块应提供可配置的不同种类的写保护。每种写保护都只与NVRAM块的NV部分相关,即RAM块数据可以修改,但不能写入NV存储器。
当NvMWriteBlockOnce为FALSE时,无论为NvMBlockWriteProt配置的值(真/假)如何,都允许使用NvM_SetBlockProtection函数启用/禁用写保护。
当NvMWriteBlockOnce为TRUE时,无论为NvMBlockWriteProt配置的值(True/False)如何,都不允许使用NvM_SetBlockProtection函数启用/禁用写保护。
对于使用NvMBlockWriteProt =TRUE配置的所有NVRAM块,NvM模块应启用默认写保护。
NvM模块的环境可以使用NvM_SetBlockProtection函数显式禁用写保护。
对于配置为NvMWriteBlockOnce = TRUE的NVRAM块,NvM模块应只向相关NV存储器写入一次,即在空白NV设备的情况下。
对于配置为NvMWriteBlockOnce = TRUE的NVRAM块,NvM模块不应允许使用NvM_SetBlockProtection函数显式禁用写保护。
对于配置了NVM_WRITE_BLOCK_ONCE (TRUE)的块,NVM应拒绝第一次读取请求之前的任何写入/擦除/无效请求。
注:在复位的情况下,NVM管理块中配置NVM_WRITE_BLOCK_ONCE (TRUE)的块的写保护标志被清除,为了重新激活保护。必须在处理第一个写入/擦除/无效请求之前读取数据块,以便仅为有效且一致的数据块设置写入保护。第一个读请求可以作为单个块请求或作为NvM_ReadAll的一部分来完成。
RAM块数据的验证和修改
本节将给出有关NVRAM管理器状态位内部处理的总结信息。下图描述了RAM模块的状态转换。
由于可以基于多个条件来进入和保存状态,并且将它们都放在上图中会使人难以理解,因此在下面的子章节中提供了更详细的解释。无效/已更改状态没有详细说明,因为它永远无法到达(如上图所述)。
初始化后,RAM模块处于无效/未更改状态,直到通过NvM_ReadAll进行更新,从而转换到有效/未更改状态。在这种状态下,不允许WriteAll。如果调用了NvM_SetRamBlockStatus,则离开此状态。如果出现CRC错误,RAM块将再次变为无效状态,这无效状态可以通过隐式或显式错误恢复机制来离开。错误恢复后,由于RAM内容不同于NVRAM内容,该块处于有效/已更改状态。
如果修改RAM块状态的API在配置中被禁用(通过NvMSetRamBlockStatusApi或NvMBlockUseSetRamBlockStatus ), NvM模块应将RAM块或NvM模块中的RAM镜像(在显式同步的情况下)视为有效,并在相应的NV块中写入数据时进行更改,即在NvM_WriteAll期间,NvM模块应将每个永久RAM块写入NV存储器。
如果用于修改RAM块状态的API在配置中被禁用(通过NvMSetRamBlockStatusApi或NvMBlockUseSetRamBlockStatus ),则当从NV块读取数据时,NvM模块应将RAM块视为无效(不理解无效为什么还读取?怀疑是文档错误,这里应该是有效),即在NvM_ReadAll期间,如果进行了相应的配置,NvM模块应将每个NVRAM块复制到RAM。
如果块读取尝试不成功,应用程序有责任在下一次写入尝试之前提供有效数据。
如果RAM块成功复制到NV存储器,RAM块状态应设置为“有效/未修改”。
有效/未更改状态
这种状态意味着RAM块的内容或者与相应NV块的内容相同,或者如果应用程序已经访问了RAM块,则还没有指示潜在的变化。对于数据集块,这些条件适用于最后处理的实例的RAM内容。此外,最后一个块操作是成功的,并且该块没有因请求而失效。
要进入有效/未更改状态,至少必须发生以下情况:
- NvM_ReadAll()成功读取该块;
- 该块的NvM_ReadBlock已成功完成;
- 该块的NvM_WriteBlock已成功完成;
- NvM_WriteAll()成功写入块;
有效/未改变状态被保留,当: BlockID的最后一次读取或写入成功(没有错误,也没有检索默认数据),且自上次读取或写入以来,应用程序未指示RAM块的潜在变化。
有效/已更改状态
这种状态意味着RAM模块的内容可能不同于相应NV模块的内容。对于数据集块,此条件适用于最后处理的RAM内容。此外,对该块的最后一次操作是成功的,并且该块没有被请求失效。块拥有者可以发信号通知该块的潜在RAM内容改变,使得块状态变得有效/改变。
要进入有效/已更改状态,至少以下条件中有一个发生:
- 为该块使用参数TRUE调用函数NvM_SetRamBlockStatus
- 为该块调用函数NvM_WriteBlock
- NvM_WriteAll也将处理该块
- 为该块调用的NvM_ReadBlock提供默认数据
- 为块调用的NvM_RestoreBlockDefaults成功完成
- 处理块时,NvM_ReadAll给出默认数据
- NvM_ValidateAll成功处理了块
有效/已更改状态在以下情况下被保持:
• 块所有者已经指出RAM块的潜在变化,或
• 上次读取时为块取回了默认数据(隐式或显式)
无效/未更改状态
这种状态意味着NV模块无效。对于数据集块,这意味着最后一个处理的NV块实例的内容是无效的。
要进入无效/未更改状态,必须至少出现以下情况之一:
- 使用参数FALSE为块调用了NvM_SetRamBlockStatus
- NvM_ReadBlock表示用户对块的请求无效
- NvM_ReadBlock表示该块的数据损坏 (如果配置了CRC)
- NvM_ReadBlock表示块的StaticID(如果已配置)错误
- 该块的NvM_WriteBlock未成功完成
- NvM_WriteAll针对该块的写入未成功
- 该块的NvM_InvalidateNvBlock已成功完成
- 该块的NvM_EraseNvBlock已成功完成
无效/未更改状态被保留,当:
• 此时块状态未知(早期初始化,直到对给定块请求ReadAll或第一次操作,或
• 检测到该块已损坏或具有错误的StaticID,或
• 对该块的最后一次成功操作是无效操作,或
• 当前读取失败,且没有默认数据,或
• 对该块的最后一次成功操作是擦除
应用程序和NVRAM管理器之间的通信和隐式同步
为了最小化锁定/解锁开销或其他同步方法的使用,应用程序和NvM模块之间的通信必须严格遵循下面描述的步骤序列。这确保了应用程序和NvM模块之间的可靠通信,避免了RAM块中的数据损坏,并保证了正确的同步。
这种访问模型假设两方参与RAM模块的通信:应用程序和NvM模块。
如果几个应用程序正在使用同一个RAM块,NvM模块的工作不是确保RAM块的数据完整性。在这种情况下,应用程序必须同步其对RAM块的访问,并且必须保证在NVRAM操作期间不会发生对RAM块的不当访问(详情见下文)。特别是如果几个应用程序通过使用(不同的)临时RAM块共享一个NVRAM块,应用程序之间的同步会变得更加复杂,并且这也不是由NvM模块处理的。在使用回调作为通知方法的情况下,可能会发生这样的情况,例如,尽管请求不是由应用发起的,但是该应用获得了通知。
所有应用程序都必须遵守以下规则。
写请求(NvM_WriteBlock或NvM_WritePRAMBlock)
为了应用程序和NVRAM管理器之间的隐式同步,应用程序在写请求期间必须遵守以下规则:
- 该应用用必须由NvM模块写入的数据填充RAM块
- 应用程序发出NvM_WriteBlock或NvM_WritePRAMBlock请求,将控制转移到NvM模块。
- 从现在开始,应用程序不应该修改RAM块,直到发出请求成功或失败的信号或通过轮询获得成功或失败的信号。与此同时,可以读取RAM块的内容。
- 应用程序可以使用轮询来获得请求的状态,或者可以通过回调函数异步地得到通知。
- NvM模块操作完成后,RAM块即可再用于修改。
读取请求(NvM_ReadBlock或NvM_ReadPRAMBlock)
为了应用程序和NVRAM管理器之间的隐式同步,读取请求期间应用程序必须遵守以下规则:
- 该应用程序提供了一个RAM块,必须用NvM模块端的NVRAM数据填充。
- 应用程序发出NvM_ReadBlock请求,将控制转移到NvM模块。
- 从现在开始,应用程序不能读取或写入RAM块,直到发出请求成功或失败的信号或通过轮询获得请求成功或失败的信号。
- 应用程序可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
- 在NvM模块操作完成后,更新了新数据的RAM块可供应用程序使用。
恢复默认请求(NvM_RestoreBlockDefaults和NvM_RestorePRAMBlockDefaults)
为了应用程序和NVRAM管理器之间的隐式同步,应用程序在恢复默认请求期间必须遵守以下规则:
- 该应用程序提供了一个RAM块,其中必须填充来自NvM模块端的ROM数据。
- 应用程序发出NvM_RestoreBlockDefaults或NvM_RestorePRAMBlockDefaults请求,将控制转移到NvM模块。
- 从现在开始,应用程序不能读取或写入RAM块,直到发出请求成功或失败的信号或通过轮询获得请求成功或失败的信号。
- 应用程序可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
- 在NvM模块操作完成后,用 ROM数据填充的RAM块可供应用程序使用。
多块读取请求(NvM_ReadAll)
该请求只能在系统启动时由BSW模式管理器触发。该请求为所有已配置的永久RAM块填充启动所需的数据。
如果请求失败或请求处理仅部分成功,NVRAM管理器会将此情况通知DEM,并向BSW模式管理器返回一个错误。DEM和BSW模式经理必须决定进一步采取的措施。这些步骤超出了NvM模块的范围,在DEM和BSW模式管理器的规范中处理。
为了在应用程序和NVRAM管理器之间的隐式同步,多块读取请求期间,应用程序必须遵守以下规则:
BSW模式管理器发起NvM_ReadAll。
- BSW模式管理器可以使用轮询来获得请求的状态,或者可以通过回调函数得到通知。
- 在NvM_ReadAll期间,在完全处理一个NVRAM块之后,将调用一个单独的块回调(如果已配置)。这些回调使RTE分别启动每个SW-C。
多块写请求(NvM_WriteAll)
该请求只能在系统关闭时由BSW模式管理器触发。该请求将所有已修改的永久RAM块的内容写入NV存储器。通过仅在ECU关闭期间调用此请求,BSW模式管理器可以确保在操作结束之前,任何软件组件都不能修改RAM块中的数据。这些措施超出了NvM模块的范围,在BSW模式管理器的规范中处理。
对于应用程序和NVRAM管理器之间的隐式同步,在多块写入请求期间,应用程序必须遵守以下规则:
- BSW模式管理器发出NvM_WriteAll请求,将控制转移到NvM模块。
- BSW模式管理器可以使用轮询来获得请求的状态,或者可以通过回调函数得到通知。
取消操作(NvM_CancelWriteAll)
此请求取消了一个挂起的NvM_WriteAll请求。这是一个异步请求,可以调用它来终止挂起的NvM_WriteAll请求。NvM_CancelWriteAll请求只能由BSW模式管理器使用。
管理块的修改
出于管理目的,管理块是每个配置的NVRAM块的一部分。如果NVRAM块存在挂起的单块操作,则在挂起的作业完成之前,不允许应用程序调用任何修改管理块的操作,如NvM_SetDataIndex、NvM_SetBlockProtection、NvM_SetRamBlockStatus。
NVRAM块的正常和扩展运行时准备
根据两个配置参数NvMDynamicConfiguration和NvMResistantToChangedSw,NVRAM管理器在启动期间,即在处理请求NvM_ReadAll()时,将以不同的方式运行。
如果NvMDynamicConfiguration设置为FALSE,NVRAM管理器将忽略存储的配置ID,并继续NVRAM块的正常运行时准备。在这种情况下,应检查RAM块的有效性。如果检测到RAM块内容无效,应检查NV块的有效性。被检测为有效的NV块应被复制到其分配的RAM块。如果检测到NV块无效,则应加载默认数据。
如果NvMDynamicConfiguration设置为TRUE,并且检测到配置ID不匹配,则应为那些配置了NvMResistantToChangedSw(FALSE)的NVRAM块执行扩展运行时准备。在这种情况下,默认数据应被加载,无论分配的RAM或NV块的有效性。
应用程序和NVRAM管理器之间的通信和显式同步
与应用和NvM模块之间的隐式同步相反,可选的显式同步机制是可用的。这是通过NvM模块中的RAM镜像实现的。数据由应用程序通过NvM模块调用的回调例程双向传输。
下面是对这一机制的简要分析:
这样做的好处是应用程序可以更好地控制它们的数据。它们负责将一致的数据复制到NvM模块的RAM镜像,以及从中复制数据,因此它们知道时间点。RAM块绝不会因并发访问而处于不一致状态。
缺点是需要具有与使用这种机制的最大NVRAM块相同大小的额外的RAM,并且每次操作都需要在两个RAM位置之间进行额外的复制。
该机制尤其能够实现不同应用程序共享NVRAM块。如果存在同步这些应用程序的模块,且从NvM模块的角度来看,该模块是NVRAM块的所有者。
对于每个NVRAM块,应能够通过参数NvMBlockUseSyncMechanism配置显式同步机制的使用。如果没有块被配置为使用显式同步机制,NvM模块不应分配RAM镜像。如果至少有一个模块被配置为使用显式同步机制,NvM模块应仅分配一个RAM镜像。此RAM镜像不应超过配置为使用显式同步机制的最长NVRAM块的大小。
NvM模块应使用内部镜像作为所有操作的缓冲器,这些操作是读/写这些NvMBlockUseSyncMechanism = TRUE的NVRAM块中的RAM块。该缓冲区不应用于其他NVRAM块。
针对NvMBlockUseSyncMechanism = TRUE的所有NVRAM块,NvM模块应调用例程NvMWriteRamBlockToNv回调,将数据从RAM块复制到的镜像。该回调不应用于其他NVRAM模块。
针对NvMBlockUseSyncMechanism = TRUE的所有NVRAM块,NvM模块应调用NvMReadRamBlockFrom NvCallback例程,将所有的数据从镜像复制到RAM块。该程序不应用于其他NVRAM模块。
在单个块请求期间,如果例程NvMReadRamBlockFromNvCallback返回E_NOT_OK,则NvM模块应重试例程调用NvMRepeatMirrorOperations次。此后,单个块读取作业应将特定于块的请求结果设置为NVM_REQ_NOT_OK,并向DEM报告NVM_E_REQ_FAILED。
如果NvMReadRamBlockFromNvCallback例程返回E_NOT_OK,NvM模块应在下一次调用NvM_MainFunction时重试该例程调用。
在单个块请求期间,如果例程NvMWriteRamBlockToNvCallback返回E_NOT_OK,则NvM模块应重试例程调用NvMRepeatMirrorOperations次。此后,单个块写入作业应将特定于块的请求结果设置为NVM_REQ_NOT_OK,并向DEM报告NVM_E_REQ_FAILED。
如果NvMWriteRamBlockToNvCallback例程返回E_NOT_OK,NvM模块应在下一次调用NvM_MainFunction时重试该例程调用。
在多块请求(NvM_WriteAll)期间,如果例程NvMWriteRamBlockToNvCallback返回E_NOT_OK,则NvM模块应重试例程调用NvMRepeatMirrorOperations次。此后,函数NvM_WriteAll的任务应将块特定请求结果设置为NVM_REQ_NOT_OK,并向DEM报告NVM_E_REQ_FAILED。
在多块请求(NvM_ReadAll)期间,如果例程NvMReadRamBlockFromNvCallback返回E_NOT_OK,则NvM模块应重试例程调用NvMRepeatMirrorOperations次。此后,函数NvM_ReadAll的任务应将块特定请求结果设置为NVM_REQ_NOT_OK,并向DEM报告NVM_E_REQ_FAILED。
如果一个块配置了显式同步,则它不应配置永久RAM映像。
下面两节阐明了使用显式同步机制时的区别。
写请求(NvM_WriteBlock或NvM_WritePRAMBlock)
为了应用程序和NVRAM管理器之间的显式同步,在写入请求期间,应用程序必须遵守以下规则:
- 该应用必须用由NvM模块写入的数据填充RAM块。
- 应用程序发出NvM_WriteBlock或NvM_WritePRAMBlock请求。
- 应用程序可能会修改RAM块,直到NvM模块调用例程NvMWriteRamBlockToNvCallback。
- 如果NvM模块调用例程NvMWriteRamBlockToNvCallback,则应用程序必须向NvM模块请求的目标提供RAM块的一致副本。应用程序可以使用返回值E_NOT_OK来表示数据不一致。NvM模块将接受该NvMRepeatMirrorOperations次,然后推迟请求并继续下一个请求。
- 仅当数据被复制到NvM模块时才继续:
- 从现在开始,应用程序可以再次读写RAM块。
- 应用程序可以使用轮询来获得请求的状态,或者可以通过回调例程异步地得到通知。
注:如果NvM_WriteBlock或NvM_WritePRAMBlock被请求,但尚未被NvM模块处理,应用程序可能会将几个写请求合并到一个RAM块中的不同位置。如果未调用回调例程NvMWriteRamBlockToNvCallback,则不会处理请求(个人理解这据表达的是不会处理真正写入NV的请求,所以可以合并多个写入请求到一个RAM块中)。
读取请求(NvM_ReadBlock或NvM_ReadPRAMBlock)
为了应用程序和NVRAM管理器之间的显式同步,在读取请求期间,应用程序必须遵守以下规则:
- 应用程序提供了一个RAM块,必须用NvM模块端的NVRAM数据填充。
- 应用程序发出NvM_ReadBlock或NvM_ReadPRAMBlock请求。
- 应用程序可能会修改RAM块,直到NvM模块调用例程NvMReadRamBlockFromNvCallback。
- 如果NvM模块调用NvMReadRamBlockFromNvCallback例程,则应用程序将数据从NvM模块给出的目的地复制到RAM块。应用程序可以使用返回值E_NOT_OK来表示数据没有被复制。NvM模块将接受该NvMRepeatMirrorOperations次,然后推迟请求并继续下一个请求。
- 仅当数据从NvM模块复制时才继续:
- 现在,应用程序在RAM块中找到NV块值。
- 应用程序可以使用轮询来获得请求的状态,或者可以通过回调例程得到通知。
注意:如果请求了NvM_ReadBlock或NvM_ReadPRAMBlock,但NvM模块尚未处理,应用程序可能会将多个读取请求合并到一个NV块中的不同位置。如果未调用回调例程NvMReadRamBlockFromNvCallback,则不会处理请求(个人理解这据表达的是不会处理真正读取NV的请求,所以可以合并多个读取请求到一个RAM块中)。
注意:NvM_RestoreBlockDefaults和NvM_RestorePRAMBlockDefaults的工作方式与NvM_ReadBlock类似。
多块读取请求(NvM_ReadAll)
该请求只能在系统启动时由BSW模式管理器触发。该请求用启动所需的数据填充所有已配置的永久RAM块。
如果请求失败或请求处理仅部分成功,NVRAM管理器会将此情况通知DEM,并向BSW模式管理器返回一个错误。DEM和BSW模式经理必须决定必须采取的进一步措施。这些步骤超出了NvM模块的范围,在DEM和BSW模式管理器的规范中处理。
正常操作:
- BSW模式管理器发出NvM_ReadAll。
- BSW模式管理器可以使用轮询来获得请求的状态,或者可以通过回调函数得到通知。
- 在NvM_ReadAll作业期间,如果为某个块配置了同步回调(NvM_ReadRamBlockFromNvm ),它将由NvM模块调用。在该回调中,应用程序应将数据从NvM模块给出的目的地复制到RAM块。应用程序可以使用返回值E_NOT_OK来表示数据没有被复制。NvM模块将接受此NvMRepeatMirrorOperations次,然后报告读取操作失败。
- 现在,如果读取操作成功,应用程序会在RAM块中找到NV块值。
- 在NvM_ReadAll期间,在完全处理一个NVRAM块之后,将调用一个单独的块回调(如果已配置)。这些回调使RTE单独启动每个SW-C。
- 在处理完最后一个程序块并调用其单个程序块回调(如果已配置)后,将调用多程序块回调(如果已配置)。
多块写请求(NvM_WriteAll)
该请求只能在系统关闭时由BSW模式管理器触发。该请求将所有已修改的永久RAM块的内容写入NV存储器。通过仅在ECU关闭期间调用此请求,BSW模式管理器可以确保在操作结束之前,任何软件组件都不能修改RAM块中的数据。这些措施超出了NvM模块的范围,在BSW模式管理器的规范中处理。
正常操作:
- BSW模式管理器发出NvM_WriteAll请求,将控制转移到NvM模块。
- 在NvM_WriteAll作业期间,如果为块配置了同步回调(NvM_WriteRamBlockToNvM ),它将由NvM模块调用。在该回调中,应用必须向NvM模块请求的目的地提供RAM块的一致副本。应用程序可以使用返回值E_NOT_OK来表示数据不一致。NvM模块将接受此NvMRepeatMirrorOperations次,然后报告写操作失败。
- 现在,应用程序可以再次读写RAM块。
- BSW模式管理器可以使用轮询来获得请求的状态,或者可以通过回调函数得到通知。
静态块ID检查
注意:NVRAM管理器在NV块每次被写入NV存储器时存储NV块头,NV块头包括NV块中的静态块ID。当读取一个块时,将其静态块ID与所请求的块ID进行比较。这允许检测会导致错误块被读取的硬件故障。
每次将块写入NV存储器时,NVRAM管理器应存储块标题的静态块ID字段。每次从NVRAM存储器中读取块时,NVRAM管理器应检查块头。
如果静态块ID检查失败,则将失败NVM _ E _ WRONG _ BLOCK _ ID报告给DEM。
如果静态块ID检查失败,则启动读取错误恢复。提示:应在配置期间进行检查,以确保所有静态块id都是唯一的。
读取重试
如果NVRAM管理器在NV存储器的读取操作中检测到故障、CRC错误,则在继续读取冗余NV块之前,应按照NVM_MAX_NUM_OF_READ_RETRIES的配置进行一次或多次额外的读取尝试。
如果NVRAM管理器在NV存储器的读取操作中检测到故障,CRC错误,则在继续读取rom块之前,应按照NVM_MAX_NUM_OF_READ_RETRIES的配置,进行一次或多次额外的读取尝试。
如果NVRAM管理器在NV存储器的读取操作中检测到故障,静态ID检查错误,则在继续读取冗余NV块之前,应按照NVM_MAX_NUM_OF_READ_RETRIES的配置,进行一次或多次额外的读取尝试。
如果NVRAM管理器在NV存储器的读取操作中检测到故障,静态ID检查错误,则在继续读取rom块之前,应按照NVM_MAX_NUM_OF_READ_RETRIES的配置,进行一次或多次额外的读取尝试。
写入验证
当RAM块写入NV存储器时,则应立即回读NV块,并与RAM块中的原始内容进行比较,如果NVM_WRITE_VERIFICATION启用了该行为。
RAM块中的原始内容和块回读之间的比较应分步进行,以便读取和比较的字节数不大于配置参数NVM _ WRITE _ VERIFICATION _ DATA _ SIZE指定的值。
如果RAM块中的原始内容与回读内容不同,则应向DEM报告生产代码错误NVM_E_VERIFY_FAILED。
如果RAM块中的原始内容与回读不同,则应按照本文件中的规定进行写重试。
如果读回操作失败,则不应进行任何读重试。
初始写入尝试以及所有配置的重试,如果RAM块中的原始内容与回读不同, NvM应设置为请求结果NVM_REQ_NOT_OK。
比较NvM中的NV数据
为了避免NV存储器中不必要的写操作,如果特定RAM块的NV数据在运行时没有更新,NvM模块提供基于CRC的比较机制,该机制可以在处理写作业时应用。
NvM模块应通过实施基于CRC的比较机制,提供跳过未更改数据写入的选项。
注意:一般来说,RAM块的某些更改内容会导致与初始内容相同的CRC,因此如果使用此选项,更新可能会丢失。因此,该选项应仅用于可承受该风险的区块。
对于每个NVRAM块,如果参数NvMBlockUseCrc设置为真,则应可以通过参数NvMBlockUseCRCCompMechanism配置使用基于CRC的比较机制。
NvM和BswM交互
当NvM需要通知BswM多块请求状态变化时,应使用BswM API BswM_NvM_CurrentJobMode()。
如果NvMBswMMultiBlockJobStatusInformation为真,则NvM不应调用已配置的多块回调。
当NvM需要通知BswM单个块请求的接受(作为挂起)和结果时,应使用BswM API BswM_NvM _ CurrentBlockMode()。
如果NvMBswMMultiBlockJobStatusInformation为真,当NvM接受多块操作时,NvM应通过使用相关的多块请求类型和模式NVM_REQ_PENDING调用BswM_NvM_CurrentJobMode,通知BswM所接受的多块操作已挂起。
如果NvMBswMMultiBlockJobStatusInformation为真,当多块操作完成或取消时,NvM应通过使用相关多块的请求类型及模式、多块操作的输出,调用BswM_NvM_CurrentJobMode,将多块操作的结果告知BswM。
如果NvMBswMBlockStatusInformation为真,当NvM接受单个块操作时,NvM应通过使用相关块ID和模式NVM_REQ_PENDING调用BswM_NvM_CurrentBlockMode,将接受的单个块操作通知BswM为挂起。
如果NvMBswMBlockStatusInformation为true,则当单个块操作完成或取消时,NvM应通过调用BswM_NvM_CurrentBlockMode,带有相关块ID及模式、单个块操作的结果,来通知BswM单个块操作的结果。
如果NvMBswMBlockStatusInformation为真,并且NvM正在进行多块操作,对于因多块操作而处理的每个块,NvM应在开始处理该块时,使用相关的块ID和模式NVM_REQ_PENDING调用BswM_NvM_CurrentBlockMode通知BswM已挂起。
如果NvMBswMBlockStatusInformation为真,并且NvM正在进行多块操作,对于因多块操作而处理的每个块,NvM应在块完成处理时,通过使用相关块ID及模式、单块操作的输出的结果,调用BswM_NvM_CurrentBlockMode,将块的处理结果通知BswM。
块锁定情况下的NvM行为
NvM_SetBlockLockStatus API服务只能由BSW组件使用,它没有在SWC描述中作为服务发布。因此,无法通过RTE访问它。
如果调用函数NvM_SetBlockLockStatus时参数BlockLocked为真,NvM应保证与BlockId所标识的NVRAM块相关的NV内容不会被任何请求修改。在NvM_WriteAll期间,应跳过该块,其他请求,即NvM_WriteBlock、NvM_WritePRAMBlock、NvM_InvalidateNvBlock、NvM _ EraseNvBlock,应被拒绝。
如果调用函数NvM_SetBlockLockStatus时参数BlockLocked为真,则NvM应保证在下一次启动时,在处理NvM_ReadBlock或NvM_ReadPRAMBlock期间,应从NV存储器中加载该NVRAM块。
如果调用函数NvM_SetBlockLockStatus时,参数BlockLocked为FALSE,NvM应保证以AUTOSAR指定的正常方式处理NVRAM块。
示例
通过诊断服务将NVRAM块的新数据保存到NV内存中。这些数据应在下一次ECU启动时提供给应用软件,即它们既不会被来自应用软件的请求覆盖,也不会在关机期间被永久RAM块的数据覆盖(NvM_WriteAll)
使用情况(按DCM):
- DCM请求NvM_SetBlockLockStatus(< block id >,FALSE),以便重新启用对此块的写入。(它可能因之前执行此过程而被锁定)。
- DCM请求NvM_WriteBlock(<blockId >,< DataBuffer >)
- DCM轮询写入请求是否完成(使用NvM_GetErrorStatus())
- 如果成功(NVM_REQ_OK),DCM将发出NvM_SetBlockLockStatus(<块Id >,TRUE)
块压缩
块数据在写入NV存储器之前会被压缩。压缩类型(块分割、压缩、增量)因供应商而异。
用例是针对较大的数据块,只更改较小的部分(如drivecycle日志)。目标是不需要将整个数据块写入NV存储器,以减少总写入周期。
块分割会将块分成多个子块,并且只有改变的子块会被写入。或者,可以只写入改变的内容。无论如何,任何数据压缩算法都可以使用。
缺点是写入或读取数据总是需要更长的运行时间。
如果NvMBlockUseCompression设置为true,NvM应压缩往NV存储器中存储的数据。
块加密
出于安全目的,NvM支持通过CSM模块使用对称16字节对齐算法(如AES128)进行同步加密和解密。
用户总是使用普通数据,NV RAM存储加密数据:
- 写入数据:NvM加密普通用户数据,然后将加密数据转发给设备。
- 读取数据:NvM从设备中读取加密数据,解密数据,最后将明文数据提供给用户。
为了检查加密数据的完整性,可以配置一个CRC。然后,NvM将计算加密数据的CRC,并在解密前重新计算和检查CRC:CRC总是与加密数据匹配。
如果给定了NvMBlockCipheringRef,则在向MemIf转发写请求之前,NvM应使用Csm_Encrypt()和NvMCsmEncryptionJobReference中给定的Csm作业加密普通数据。
CRC计算(如果配置)应包含整个加密后的数据。
如果Csm_Encrypt()返回CRYPTO_E_BUSY,NvM
将重试重做该作业。在NvMCsmRetryCounter次重试后若仍未成功,NvM应中止写入作业,并将NvM结果设置为NVM_REQ_NOT_OK,并通过NvM_JobErrorNotification()发出错误信号。
如果Csm_Encrypt()返回除CRYPTO_E_BUSY或CRYPTO_E_OK之外的任何其他错误,NvM应中止写入作业,并将NvM结果设置为NVM_REQ_NOT_OK,并通过NvM_JobErrorNotification()发出错误信号。
如果Csm_Encrypt()成功返回CRYPTO_E_OK,NvM应使用NvMNvBlockNVRAMDataLength中给出的新长度继续写入作业(例如,使用CRC计算)。
如果resultLengthPtr中返回的长度不同于NvMNvBlock NVRAMDataLength,则应触发开发错误NVM_E_BLOCK_CHIPHER_LENGTH_MISSMATCH。
如果给定了NvMBlockCipheringRef,NvM应在将读取请求转发给应用程序之前,使用Csm_Decrypt()和NvMCsmDecryptionJobReference中给定的Csm作业对存储的数据进行解密。应对加密数据进行CRC校验(如果已配置)。如果CRC不匹配,NvM将不会解密数据,而是通过NVM_REQ_INTEGRITY_FAILED中止作业。
如果Csm_Decrypt()返回CRYPTO_E_BUSY,NvM应重试重做该作业。在NvMCsmRetryCounter次重试后仍未成功,则NvM应中止读取作业,并将NvM结果设置为NVM_REQ_NOT_OK,并通过NvM_JobErrorNotification()发出错误信号。
如果Csm_Decrypt()返回除CRYPTO_E_BUSY或CRYPTO_E_OK之外的任何其他错误,NvM应中止读取作业,并将NvM结果设置为NVM_REQ_NOT_OK,并通过NvM_JobErrorNotification()发出错误信号。
如果Csm_Decrypt()成功返回CRYPTO_E_OK,NvM应以NvMNvBlockLength中给出的新长度继续读取作业。
如果resultLengthPtr中返回的长度不同于NvMNvBlockLength,则应触发开发错误NVM_E_BLOCK_CHIPHER_LENGTH_MISSMATCH。
时序图
同步调用
NvM_Init
NvM_SetDataIndex
NvM_GetDataIndex
NvM_SetBlockProtection
NvM_GetErrorStatus
NvM_GetVersionInfo
异步调用
下面的序列图集中在NvM模块和SW-C或BSW模式管理器之间的交互。关于内存接口的交互,请参考[Specification of EEPROM Abstraction AUTOSAR_SWS_EEPROMAbstraction]或[Specification of Flash EEPROM Emulation AUTOSAR_SWS_FlashEEPROMEmulation]
使用轮询的异步调用
下图显示了NvM_WriteBlock函数作为异步执行请求的示例。所有其他异步功能的顺序都是相同的,只有处理的块数量和块类型可能不同。异步函数的结果是通过轮询对错误/状态信息的请求获得的。
使用回调的异步调用
下图显示了NvM_WriteBlock函数作为异步执行请求的示例。所有其他异步功能的顺序都是相同的,只有处理的块数量和块类型可能不同。异步函数的结果是在异步通知(回调)后通过请求错误/状态信息获得的。
多块请求的取消
下图显示了取消操作对正在运行的NvM_WriteAll多块请求的影响。正在运行的NvM_WriteAll函数完成实际正在的NVRAM块并停止进一步的写入。
BSWM交互
下图显示了NvM和BswM在单块操作和多块操作方面的交互。