前言
存储协议栈负责ECU中非易失性数据的存储管理。存储协议栈的分享包括NVM、MemI、Ea、Fea、Eep、Fls模块的详细介绍及代码分析,具体的项目实战请关注本号的后续文章,本篇为NVRAM Manager(NVM)模块详细介绍篇(二)。
正文
3.5 功能需求 Functional requirements
对于每个异步请求,在任务完成后通知调用者应该是一个可配置选项。
NvM模块应提供一个回调接口。
提示:NvM模块的环境只能通过NvM模块访问非易失性内存。不允许任何模块(除了NvM模块)直接访问非易失性内存。
NvM模块只提供了一种隐式的方式来访问NVRAM和共享内存(RAM)中的块。这意味着,NvM模块将一个或多个块从NVRAM复制到RAM,反之亦然。
应用程序直接访问RAM数据,根据给定的限制(例如同步)。
NvM模块将对所有异步的“单块”读/写/控制请求进行排队,如果具有特定ID的块尚未排队或正在进行(多任务限制)。
只要不发生队列溢出,NvM模块将接受多个异步的“单块”请求。
优先级最高的请求将由NvM模块从队列中获取,并以序列化的顺序处理。
NvM模块应该实现隐式机制来对保存在NV内存中的数据进行一致性/完整性检查。
根据内存堆栈的实现,NvM模块提供和/或调用的回调例程可能在中断上下文中被调用。
提示:提供在中断上下文中调用的例程的NvM模块因此必须确保它们的运行时间相当短。
如果在配置时没有默认的ROM数据可用,或者没有NvMInitBlockCallback定义的回调,那么应用程序将负责提供默认的初始化数据。
在这种情况下,应用程序必须使用NvM_GetErrorStatus()来区分首次初始化和损坏的数据。
在处理NvM_ReadAll的过程中,NvM模块应该能够通过执行校验和计算来检测损坏的RAM数据。
在处理NvM_ReadAll的过程中,NvM模块应该能够通过测试管理块内数据的有效性来检测RAM中的无效数据。
在启动阶段和NvM_ReadAll的正常运行期间,如果NvM模块在NV块内检测到不可恢复的错误,NvM模块将复制默认数据(如果配置)到相应的RAM块。
为了使用OS服务,NvM模块只能使用BSW调度器,而不能直接使用OS对象和/或相关的OS服务。
3.6 NVM启动 NVRAM manager startup
NvM_Init应该由ECU状态管理器独占调用。
由于ECU启动时间的强约束,NvM_Init请求不能包含配置的NVRAM块的初始化。
NvM_Init请求不负责触发底层驱动和内存硬件抽象的初始化。这也应由EcuM处理。
内存数据块的初始化应该由另一个请求完成,即NvM_ReadAll。
如果使用EcuM Fixed, NvM_ReadAll将由EcuM调用,如果使用EcuM Flex,则由集成代码调用。
使用NvM模块的软件组件应负责检查由于NvM模块启动而产生的全局错误/状态信息。ECU状态管理器应该通过使用NvM_GetErrorStatus(预留块ID 0)或回调通知(可配置选项NvM_MultiBlockCallback)来轮询启动过程中产生的全局错误/状态信息。如果使用轮询,NVRAM启动过程的结束将由全局错误/状态NVM_REQ_OK或NVM_REQ_NOT_OK检测(在启动过程NVM_REQ_PENDING期间)。如果回调被选择用于通知,如果指定的NVRAM块已被处理,软件组件将被自动通知。
注1:如果回调被配置为每个NVRAM块在NvM_ReadAll内处理,它们可以被RTE在早期的时间点启动,例如SW-Cs。
注2:为了确保DEM在早期完全运行,即它的NV数据被恢复到RAM中,与DEM相关的NVRAM块应该配置为低ID,在NvM_ReadAll中首先处理。
NvM模块不能以持久的方式自动存储当前使用的Dataset索引。软件组件应该检查他们负责的所有块的特定错误/状态,使用带有特定块id的NvM_GetErrorStatus来确定对应RAM块的有效性。
对于块管理类型为“NVRAM数据集”的所有块,软件组件应负责通过NvM_SetDataIndex设置适当的索引位置。例如,当前索引位置可以被软件组件存储/维护在一个唯一的NVRAM块中。为了获得“数据集块”的当前索引位置,软件组件应该使用NvM_GetDataIndex API调用。
3.7 NVM关机 NVRAM manager shutdown
基本的关闭过程应该由请求NvM_WriteAll完成。
提示:NvM_WriteAll将被ECU状态管理器调用
3.8 对NvM模块的并行写访问 Parallel write access to the NvM module
NvM模块应该通过一个使用排队机制的异步接口来接收请求。NvM模块将根据请求的优先级顺序处理所有请求。
3.9 NVM一致性检查 NVRAM block consistency check
NvM模块应该提供隐式的技术来检查NVRAM块的数据一致性。
NVRAM块的数据一致性检查应通过CRC对其相应的NV块进行重新计算来完成。
数据一致性检查的隐式方式应由内部功能的可配置选项提供。隐式一致性检查对每个NVRAM块都是可配置的,依赖于可配置的参数NvMBlockUseCrc和NvMCalcRamBlockCrc。
当NVRAM块的NvMWriteBlockOnce = TRUE时,应该启用NVRAM块校验NvMBlockUseCrc。当NVRAM块的NvMWriteBlockOnce = TRUE时,应该禁用NVRAM块的NvMBlockWritePort,以便在CRC检查失败的情况下,用户可以向NVRAM块写入数据。
根据可配置参数NvMBlockUseCrc和NvMCalcRamBlockCrc, NvM模块将为使用的最大CRC分配内存。
提示:NvM用户必须不知道关于CRC内存(例如大小,位置)的任何东西,为他们的数据在RAM块。
3.10 错误恢复 Error Recovery
NvM模块应该提供错误恢复的技术。错误恢复取决于NVRAM块管理类型。
NvM模块通过加载默认值,为每一种NVRAM块管理类型提供读取时的错误恢复。
NvM模块将通过加载RAM块的默认值,在读取块管理类型为 NVM_BLOCK_REDUNDANT的NVRAM块时提供错误恢复。
无论NVRAM块管理类型如何,NvM模块都应该通过执行写重试来提供写时的错误恢复。
在RAM块重新验证失败的情况下,NvM模块应在启动时为所有配置了RAM块CRC的NVRAM块提供读取错误恢复。
3.11 用ROM数据恢复RAM块
当NV块出现不可恢复的数据不一致时,NvM模块应提供隐式和显式恢复技术,将ROM数据恢复到相应的RAM块。
3.12 使用ROM默认数据隐式恢复RAM块
在隐式恢复过程中,相应NV块的数据内容保持不变。
在启动(NvM_ReadAll的一部分)时不提供隐式恢复,当没有配置ROM块时(通过参数NvMRomBlockDataAddress或NvMInitBlockCallback),每个NVRAM块都不提供NvM_ReadBlock或NvM_ReadPRAMBlock。
在以下情况下,在启动(NvM_ReadAll的一部分)和NVRAM块的NvM_ReadBlock或NvM_ReadPRAMBlock不会提供隐式恢复: (1)&&(2)
(1) 配置了ROM块(通过参数nvromblockdataaddress或参数NvMInitBlockCallback)
(2) NvM模块中的永久RAM块或RAM镜像的内容(在显式同步的情况下)状态是有效的,CRC(数据)是一致的。
在以下情况下,在启动(NvM_ReadAll的一部分)和NVRAM块的NvM_ReadBlock或NvM_ReadPRAMBlock不会提供隐式恢复: (1)&&(2)&&(3)
(1) 配置了ROM块(通过参数nvromblockdataaddress或参数NvMInitBlockCallback)
(2) NvM模块中的永久RAM块或RAM镜像的内容(在显式同步的情况下)无效,CRC(数据)不一致。
(3) 从NV成功读取尝试。
在以下情况下,隐式恢复应该在启动时(NvM_ReadAll的一部分)或者NVRAM块的NvM_ReadBlock或NvM_ReadPRAMBlock时被提供:
(1)配置了ROM块(通过参数nvromblockdataaddress或参数NvMInitBlockCallback)
(2)NvM模块中的永久RAM块状态或RAM镜像的内容(在显式同步的情况下)是无效的,CRC(数据)不一致。
(3)从NV读取失败。
隐式恢复应该在NvM_ReadBlock()或NvM_ReadPRAMBlock()请求NVM_BLOCK_NATIVE和NVM_BLOCK_REDUNDANT类型的NVRAM块时提供。
3.13 使用ROM默认数据显式恢复RAM
对于使用ROM块数据的显式恢复,NvM模块应该提供NvM_RestoreBlockDefaults和NvM_RestorePRAMBlockDefaults函数来将ROM数据恢复到相应的RAM块。
NvM_RestoreBlockDefaults和NvM_RestorePRAMBlockDefaults函数不会修改对应NV块的数据内容。
提示:应用程序每次需要将ROM数据恢复到相应的RAM块时,使用NvM_RestoreBlockDefaults或NvM_RestorePRAMBlockDefaults函数。
3.14 检测对NV块的写操作未完成
检测NV块的未完成写操作不在NvM模块的范围之内。这是由内存硬件抽象处理和检测的。NvM模块期望从内存硬件抽象中获取信息,如果引用的NV块无效或不一致,并且在请求时无法读取。
SW-Cs可能会使用NvM_InvalidateNvBlock来阻止底层传递旧数据。
3.15 终止单个块请求
NvM模块提供的所有异步请求(除了NvM_CancelWriteAll)都应该在相应的管理块的指定的错误/状态字段中指明结果。
可选配置参数NvMSingleBlockCallback在异步块请求终止时通过回调来配置通知(NvM_CancelWriteAll除外)。
注意:在与应用SW-C通信时,NvMSingleBlockCallback需要映射到Rte_call_ _
3.16 终止一个多块请求
NvM模块应该使用一个单独的变量来存储异步多块请求的结果(NvM_ReadAll, NvM_WriteAll包括NvM_CancelWriteAll, NvM_ValidateAll)。
函数NvM_GetErrorStatus将返回异步多块请求(包括NvM_CancelWriteAll)的最新错误/状态信息,并将保留的块ID值设置为0。
多块请求的结果只能代表一个常见的错误/状态信息。
NvM模块提供的多块请求应在每个受影响的管理块指定的错误/状态字段中指明其详细的错误/状态信息。
可选配置参数NvMMultiBlockCallback在异步多块请求终止时通过callback配置通知。
3.17 异步请求/作业处理的一般处理
每次在一个请求中处理CRC计算时,如果NVRAM块的长度超过参数NvMCrcNumOfBytes.配置的字节数,NvM模块就会分多次计算CRC。
对于CRC计算,NvM模块应使用CRC模块公布的初始值。
多个并发的单个块请求应该是可排队的。
NvM模块将中断异步请求/任务处理,优先处理具有即时优先级的任务(崩溃数据)。
如果在NvM模块上调用异步函数导致作业队列溢出,该函数将返回E_NOT_OK。
当一个请求成功进入队列时,NvM模块应该将对应NVRAM块的请求结果设置为NVM_REQ_PENDING。
如果NvM模块已经成功处理了一个任务,它将返回NVM_REQ_OK作为请求结果。
3.18 NVRAM块写保护
NvM模块应该提供不同类型的写保护,这些写保护应该是可配置的。每一种写保护都只与NVRAM块的NV部分有关,即RAM块数据可以修改,但不能写入NV内存。
当“NvMWriteBlockOnce”为FALSE时,无论“ NvMBlockWriteProt”配置的值(True/ FALSE)是多少,使用“NvM_SetBlockProtection”功能都允许开启/关闭写保护。
当“NvMWriteBlockOnce”为TRUE时,无论“NvMBlockWriteProt”配置的值是(TRUE /False),使用NvM_SetBlockProtection功能都不允许开启/关闭写保护。
对于所有配置了NVRAM块的NvMBlockWriteProt = TRUE, NvM模块应该启用默认写保护。
NvM模块的环境可以使用NvM_SetBlockProtection功能显式地禁用写保护。
对于配置了NvMWriteBlockOnce == TRUE的NVRAM块,NvM模块只能向相关的NV内存写入一次,即在空白NV设备的情况下。
对于配置了NvMWriteBlockOnce == TRUE的NVRAM块,NvM模块不允许使用NvM_SetBlockProtection功能显式地禁用写保护。
对于配置了MVM_WRITE_BLOCK_ONCE (TRUE)的块,NvM将拒绝第一个读请求之前的任何写/擦除/无效请求。
注意:如果重置,NvM管理块中配置了NVM_WRITE_BLOCK_ONCE (TRUE)的块的写保护标志将被清除。为了重新激活该保护,必须在第一个写/擦除/失效请求被处理之前读取该块,以便设置写保护仅对有效且一致的块有效。第一个读请求可以作为单个块请求完成,也可以作为NvM_ReadAll的一部分完成。
3.19 验证和修改RAM块数据
下图描述了RAM块的状态转换。
由于进入和保持一种状态可以基于多种条件,而把它们都放在上面的图中会让人难以理解,所以在下面的小节中会提供更详细的解释。INVALID / CHANGED状态没有详细说明,因为它永远无法到达(如上图所示)。
在初始化之后,RAM块的状态是INVALID/UNCHANGED,直到通过NvM_ReadAll更新它,这将导致转换到VALID/UNCHANGED状态。在这个状态下,不允许WriteAll。如果调用了NvM_SetRamBlockStatus,这个状态是左边的。如果发生CRC错误,RAM块再次改变到无效状态,这可以通过隐式或显式错误恢复机制离开。错误恢复后,块的状态是VALID/CHANGED,因为RAM的内容不同于NVRAM内容。
如果修改RAM块状态的API已经配置好了(通过NvMSetRamBlockStatusApi或NvMBlockUseSetRamBlockStatus), NvM模块在写入一个RAM块或NvM模块中的RAM镜像时(在显式同步的情况下),NvM模块应将其视为有效且被修改,即在NvM_WriteAll期间,NvM模块应将每个永久RAM块写入NV内存。
如果修改RAM块状态的API已经配置好了(通过vmsetramblockstatusapi或
NvMBlockUseSetRamBlockStatus) NvM模块在读取RAM块时将其视为无效的,即在NvM_ReadAll期间,NvM模块将每个NVRAM块复制到RAM中,如果配置了相应的NVRAM块。
如果块读取尝试失败,则应用程序负责在下一次写尝试之前提供有效的数据。
如果一个RAM块成功地复制到NV内存,那么RAM块的状态将被设置为“有效/未修改”。
3.19. 1 The VALID / UNCHANGED state
这种状态意味着RAM块的内容要么与相应的NV块的内容相同,要么——如果应用程序已经访问了RAM块——还没有表明潜在的变化。对于DATASET块,这些条件适用于最后处理的实例的RAM内容。另外,最后一个块操作是成功的,并且该块没有被请求无效。
要进入 VALID / UNCHANGED状态,至少必须发生以下任一情况:
1) NvM_ReadAll()成功读取块
2) 该块的NvM_ReadBlock成功完成
3)块的NvM_WriteBlock成功完成
4) NvM_WriteAll()写块成功
同时满足以下条件时,VALID / UNCHANGED状态被保存:
-- 对BlockID的最后一次读或写是成功的(没有错误,也没有获取默认数据)
-- 应用程序没有表明RAM块自上次读或写以来的潜在变化
3.19.2 The VALID / CHANGED state
这种状态意味着RAM块的内容可能与相应的NV块的内容不同。对于DATASET块,此条件适用于最后处理的实例的RAM内容。此外,对该块的最后一个操作是成功的,并且该块没有被请求无效。块所有者可以通知块的潜在RAM内容发生了变化,从而导致块状态变为VALID / CHANGED。
要进入 VALID / CHANGED状态,至少必须发生以下任一情况:
1. NvM_SetRamBlockStatus被调用时为TRUE
2. 对该块调用NvM_WriteBlock
3.NvM_WriteAll也将处理该块
4. 调用该块的NvM_ReadBlock会给出默认数据
5. 为块调用的NvM_RestoreBlockDefaults函数成功完成
6. 当处理该块时,NvM_ReadAll给出默认数据
7. NvM_ValidateAll成功处理了该块
满足以下任一条件时,VALID / CHANGED状态被保存:
-- 块所有者指出了RAM块的潜在变化
-- 在上次读取时,会(隐式或显式地)为块检索默认数据
3.19.3 The INVALID / UNCHANGED state
这种状态意味着NV块无效。对于DATASET块,这意味着NV块内容对于处理的最后一个实例无效。
要进入 INVALID / UNCHANGED状态,至少必须发生以下任一情况:
1. 调用NvM_SetRamBlockStatus时为该块设置FALSE
2. NvM_ReadBlock表示用户请求块无效
3.NvM_ReadBlock表示块的数据损坏(如果配置了CRC)
4. NvM_ReadBlock表示该块的StaticID错误(如果配置了)
5. 该块的NvM_WriteBlock完成不成功
6. NvM_WriteAll写块不成功
7. 该块的NvM_InvalidateNvBlock成功完成
8. 该块的NvM_EraseNvBlock成功完成
满足以下任一条件时,INVALID / UNCHANGED状态被保存:
-- 块的状态在当时是未知的(早期初始化,直到ReadAll或第一个操作请求一个给定的块)
-- 该块被检测到损坏或错误的StaticID
-- 对该块的最后一次成功操作是无效的
-- 当前读取失败,没有默认数据
--- 对该块的最后一次成功操作是删除操作
3.20 应用程序和NVRAM Manager之间的通信和隐式同步
为了最小化锁/解锁的开销或使用其他同步方法,应用程序和NvM模块之间的通信必须遵循下面描述的严格的步骤序列。这确保了应用程序和NvM模块之间的可靠通信,避免了RAM块中的数据损坏,并保证了适当的同步。
此访问模型假设双方参与了与RAM块的通信:应用程序和NvM模块。
如果多个应用程序都在使用同一个RAM块,NvM模块就不能确保RAM块的数据完整性。在这种情况下,应用程序必须同步它们对RAM块的访问,并且必须保证在NVRAM期间不会发生对RAM块不合适的访问操作。
特别是当几个应用程序通过使用(不同的)临时RAM块来共享一个NVRAM块时,应用程序之间的同步会变得更加复杂,而且NvM模块也不会处理这个问题。在使用回调作为通知方法的情况下,可能会发生这样的情况:应用程序获得一个通知,尽管该请求尚未由该应用程序发起。所有申请必须遵守以下规则。
3.20.1 写请求(NvM_WriteBlock or NvM_WritePRAMBlock)
应用程序和NVRAM Manager之间的隐式同步在写请求时必须遵守以下规则:
1)应用程序用NvM模块必须写入的数据填充RAM块
2)应用程序发出NvM_WriteBlock或NvM_WritePRAMBlock请求,将控制权转移给NvM模块。
3)从现在开始,应用程序不得修改RAM块,直到发出或通过轮询获得请求的成功或失败。在此期间,可以读取RAM块的内容。
4)应用程序可以使用轮询来获取请求的状态,也可以通过回调函数异步获得通知。
5)在完成NvM模块操作后,RAM块可用于修改。
3.20.2 读请求(NvM_ReadBlock or NvM_ReadPRAMBlock)
在应用程序和NVRAM Manager之间进行隐式同步时,应用程序必须遵守以下规则:
1)应用程序提供了一个RAM块,必须用NvM模块侧的NVRAM数据来填充它。
2)应用程序发出NvM_ReadBlock请求,将控制权转移给NvM模块。
3)从现在开始,在请求成功或失败被通知或通过轮询派生之前,应用程序不能读写RAM块。
4)应用程序可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
5)在完成NvM模块操作之后,RAM块就可以使用新数据供应用程序使用。
3.20.3 恢复默认请求(NvM_RestoreBlockDefaults and NvM_RestorePRAMBlockDefaults)
在恢复应用程序和NVRAM Manager之间隐式同步的默认请求时,应用程序必须遵守以下规则:
1) 应用程序提供了一个RAM块,它必须用来自NvM模块端的ROM数据填充。
2)应用程序发出NvM_RestoreBlockDefaults或NvM_RestorePRAMBlockDefaults请求,将控制权转移到NvM模块。
3)从现在开始,在请求成功或失败被通知或通过轮询派生之前,应用程序不能读写RAM块。
4) 应用程序可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
5) 在完成NvM模块操作之后,RAM块就可以与ROM数据一起供应用程序使用。
3.20.4 多块读请求 (NvM_ReadAll)
如果使用EcuM Fixed,这个请求只能由ECU状态管理器触发;如果在系统启动时使用EcuM Flex,则只能由集成代码触发。这个请求用启动所需的数据填充所有配置的永久RAM块。
如果请求失败或请求处理仅部分成功,NVRAMManager将此条件信号给DEM,并向EcuM返回一个错误。DEM和EcuM必须决定采取进一步的措施。这些步骤在DEM和ECU状态管理器的模块中处理。
在应用程序和NVRAM Manager之间进行隐式同步的多块读请求时,应用程序必须遵守以下规则:
ECU状态管理器发出NvM_ReadAll。
-- ECU状态管理器可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
-- 在NvM_ReadAll过程中,一个单独的块回调(如果配置)将在处理完一个NVRAM块之后被调用。这些回调使RTE能够单独启动每个SW-C。
3.20.5 多块写请求(NvM_WriteAll)
这个请求只能由ECU状态管理器在系统关闭时触发。这个请求将所有修改后的永久RAM块的内容写入NV内存。通过仅在ECU关闭期间调用该请求,ECU状态管理器可以确保在操作结束之前没有SW组件能够修改RAM块中的数据。这些措施在EcuM中处理。
在应用程序和NVRAM管理器之间进行隐式同步的多块写请求时,应用程序必须遵守以下规则:
1. EcuM发出NvM_WriteAll请求,该请求将控制权转移给NvM模块。
2. EcuM可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
3.20.6 删除操作 (NvM_CancelWriteAll)
这个请求取消了一个挂起的NvM_WriteAll请求。这是一个异步请求,可以调用它来终止一个挂起的NvM_WriteAll请求。
NvM_CancelWriteAll请求只能被EcuM使用。
3.20.7 管理块的修改 Modification of administrative blocks
为了管理目的,管理块是每个配置NVRAM块的一部分。
如果NVRAM块有一个待处理的单块操作,应用程序不允许调用任何修改管理块的操作,如NvM_SetDataIndex, NvM_SetBlockProtection, NvM_SetRamBlockStatus,直到待处理的作业完成。
3.21 NVRAM块的正常和扩展运行时准备
根据两个配置参数NvMDynamicConfiguration和NvMResistantToChangedSw, NVRAM管理器在启动过程中会以不同的方式运行,例如在处理请求 NvM_ReadAll()时。
如果NVRAM NvMDynamicConfiguration设置为FALSE, NVRAM管理器将忽略存储的配置ID,继续正常运行时准备NVRAM块。在这种情况下,RAM块应检查其有效性。如果RAM块内容被检测为无效,则应检查NV块的有效性。一个被检测到有效的NV块将被复制到指定的RAM块中。如果检测到无效的NV块,将加载默认数据。如果NvMDynamicConfiguration设置为TRUE,并且检测到配置ID不匹配,则需要对那些配置了NvMResistantToChangedSw(FALSE)的NVRAM块进行扩展运行准备。在这种情况下,默认数据应该加载独立的有效性分配RAM或NV块。
3.22 应用程序和NVRAM管理器之间的通信和显式同步
与应用程序和NvM模块之间的隐式同步相比,显式同步机制是可选的(即可配置的)。它是通过NvM模块中的RAM镜像实现的。通过NvM模块调用的回调例程,应用程序在两个方向上传输数据。
以下是对这种机制的简短分析:
-- 优点是应用程序可以以更好的方式控制它们的数据。它们负责从NvM模块的RAM镜像中复制一致的数据,因此它们知道时间点。RAM块不会因为并发访问而处于不一致的状态。
-- 缺点是额外的RAM需要与使用这种机制的最大NVRAM块相同的大小,并且每个操作都需要在两个RAM位置之间进行额外的拷贝。
这种机制特别允许不同应用程序共享NVRAM块,如果有一个模块对这些应用程序进行同步,并且从NvM模块的角度来看,它是NVRAM块的所有者。
对于每个NVRAM块,都应该有可能通过参数NvMBlockUseSyncMechanism来配置显式同步机制的使用。
如果没有配置块使用显式的同步机制,NvM模块不能分配RAM镜像。
如果至少有一个块被配置为使用显式同步机制,NvM模块应该只分配一个RAM镜像。这个RAM镜像不能超过配置为使用显式同步机制的最长NVRAM块的大小。
NvM模块应该使用内部镜像作为所有读写NVRAM块的RAM块的操作的缓冲区,这些NVRAM块带有NvMBlockUseSyncMechanism== TRUE。该缓冲区不能用于其他NVRAM块。
NvM模块需要调用NvMWriteRamBlockToNvM例程,以便使用NvMBlockUseSyncMechanism== TRUE将所有NVRAM块的数据从RAM块复制到镜像。这个例程不能用于其他NVRAM块。
NvM模块需要调用NvM的NvMReadRamBlockFromNvM例程,以便用NvMBlockUseSyncMechanism == TRUE将所有NVRAM块的数据从镜像复制到RAM块。这个例程不能用于其他NVRAM块。
在单个块请求过程中,如果例程NvMReadRamBlockFromNvM返回E_NOT_OK,那么NvM模块应该重试例程调用NvMRepeatMirrorOperations次数。之后,单块读作业将块特定的请求结果设置为NVM_REQ_NOT_OK,并向DEM报告NVM_E_REQ_FAILED。
在NvM例程返回E_NOT_OK的情况下,NvM模块应该在下次调用NvM_MainFunction时重试例程调用。
在单个块请求过程中,如果例程NvMWriteRamBlockToNvM返回E_NOT_OK,那么NvM模块将重试例程调用NvMRepeatMirrorOperations次数。之后单块写作业将块特定的请求结果设置为NVM_REQ_NOT_OK,并向DEM报告NVM_E_REQ_FAILED。
在这种情况下,NvMWriteRamBlockToNvM例程返回E_NOT_OK, NvM模块应该在下次调用NvM_MainFunction时重试例程调用。
在一个多块请求(NvM_WriteAll)中,如果例程NvMWriteRamBlockToNvM返回E_NOT_OK,那么NvM模块将重试例程调用NvMRepeatMirrorOperations次数。之后,函数NvM_WriteAll的任务将block特定请求结果设置为NVM_REQ_NOT_OK,并向DEM报告NVM_E_REQ_FAILED。
在一个多块请求(NvM_ReadAll)中,如果例程NvMReadRamBlockFromNvM返回E_NOT_OK,那么NvM模块应该重试例程调用NvMRepeatMirrorOperations次数。之后NvM_ReadAll函数的任务将block特定请求结果设置为NVM_REQ_NOT_OK,并向DEM报告nvm_req_failed。
如果一个块为它配置了显式的同步,那么它一定没有配置永久RAM映像。
3.22.1 写请求(NvM_WriteBlock or NvM_WritePRAMBlock)
在写请求过程中,应用程序和NVRAM Manager之间必须遵循以下规则进行显式同步:
1) 应用程序用NvM模块必须写入的数据填充RAM块。
2) 应用程序发出NvM_WriteBlock或NvM_WritePRAMBlock请求。
3) 应用程序可能会修改内存块,直到例程NvMWriteRamBlockToNvM被NvM模块调用。
4) 如果例程NvMWriteRamBlockToNvM被NvM模块调用,那么应用程序必须提供一个一致的RAM块副本到NvM模块请求的目的地。应用程序可以使用返回值E_NOT_OK来表示数据不一致。NvM模块将接受这个NvMRepeatMirrorOperations次数,然后推迟请求并继续它的下一个请求。
5) 延续仅当数据复制到NvM模块时:
6) 从现在开始,应用程序可以再次读写RAM块。
7) 应用程序可以使用轮询来获取请求的状态,也可以通过回调例程异步获得通知。
注意:如果请求了NvM_WriteBlock或NvM_WritePRAMBlock,但还没有被NvM模块处理,应用程序可能会将多个写请求组合到一个RAM块的不同位置。如果没有调用回调例程NvMWriteRamBlockToNvM,则请求未被处理。
3.22.2 读请求 (NvM_ReadBlock or NvM_ReadPRAMBlock)
在应用程序和NVRAM Manager之间进行显式同步时,应用程序必须遵守以下规则:
1)应用程序提供了一个RAM块,必须用NvM模块侧的NVRAM数据来填充它。
2)应用程序发出NvM_ReadBlock或NvM_ReadPRAMBlock请求。
3)应用程序可能会修改RAM块,直到NvM模块调用NvMReadRamBlockFromNvM例程。
4)如果例程NvMReadRamBlockFromNvM被NvM模块调用,那么应用程序将数据从NvM模块指定的目的地复制到RAM块。应用程序可以使用返回值E_NOT_OK来表示没有复制数据。NvM模块将接受这个NvMRepeatMirrorOperations次数,然后推迟请求并继续它的下一个请求。
5)只有从NvM模块复制数据时才会延续:
6)现在,应用程序在RAM块中查找NV块值。
7)应用程序可以使用轮询来获取请求的状态,也可以通过回调例程得到通知。
注意:如果请求了NvM_ReadBlock或NvM_ReadPRAMBlock,但还没有被NvM模块处理,应用程序可能会将多个读请求组合到一个NV块的不同位置。如果回调例程NvMReadRamBlockFromNvM没有被调用,请求就没有被处理。
注意:NvM_RestoreBlockDefaults和NvM_RestorePRAMBlockDefaults的工作原理与NvM_ReadBlock类似。
3.22.3 多块读请求(NvM_ReadAll)
这个请求只能由EcuM在系统启动时触发。
这个请求用启动所需的数据填充所有配置的永久RAM块。
如果请求失败或请求处理仅部分成功,NVRAMManager将此条件信号给DEM,并向EcuM返回一个错误。DEM和EcuM必须决定采取进一步的措施。这些步骤在DEM和EcuM中处理。
正常的操作:
1) EcuM发出NvM_ReadAll。
2) EcuM可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
3)在NvM_ReadAll任务中,如果为一个块配置了同步回调(NvM_ReadRamBlockFromNvm),它将被NvM模块调用。在这个回调中,应用程序将从NvM模块给出的目的地复制数据到RAM块。应用程序可以使用返回值E_NOT_OK来表示没有复制数据。NvM模块将接受这个NvMRepeatMirrorOperations次数,然后报告读取操作失败。
4)现在,如果读取操作成功,应用程序将在RAM块中查找NV块值。
5) 在NvM_ReadAll过程中,一个单独的块回调(如果配置)将在处理完一个NVRAM块之后被调用。这些回调使RTE能够单独启动每个SW-C。
3.22.4 多块写请求(NvM_WriteAll)
这个请求只能由EcuM在系统关闭时触发。这个请求将所有修改后的永久RAM块的内容写入NV内存。通过仅在ECU关闭期间调用该请求,EcuM可以确保在操作结束之前没有SW组件能够修改RAM块中的数据。这些措施在EcuM中处理。
正常的操作:
1)ECU状态管理器发出NvM_WriteAll请求,该请求将控制权转移给NvM模块。
2)在NvM_WriteAll作业期间,如果为一个块配置了一个同步回调(NvM_WriteRamBlockToNvM),它将被NvM模块调用。在这个回调中,应用程序必须提供一个一致的副本将RAM块发送到NvM模块请求的目的地。应用程序可以使用返回值E_NOT_OK来表示数据不一致。NvM模块将接受这个NvMRepeatMirrorOperations次数,然后报告写操作失败。
3)现在应用程序可以再次读写RAM块了。
4)ECU状态管理器可以使用轮询来获取请求的状态,也可以通过回调函数得到通知。
3.23 静态块ID检查
注意:NVRAM Manager存储NV块头,包括静态块ID在NV块每次写入NV内存的时候。当读取一个块时,将其静态块ID与请求的块ID进行比较。这允许检测导致读取错误块的硬件故障。
NVRAM Manger应该在每次将块写入NV内存时存储块头的静态块ID字段。
NVRAM Manger应该在每次从NV内存读取区块时检查区块头。
如果静态块ID检查失败,则向DEM报告失败的NVM_E_WRONG_BLOCK_ID。
如果静态块ID检查失败,则启动读取错误恢复。
提示:配置时需要检查,确保所有的Static Block id都是唯一的。
3.24 读重试
如果NVRAM Manger在从NV内存读取操作期间检测到失败,CRC错误,那么在继续读取冗余NV块之前,将进行一次或多次额外的读取尝试,如NVM_MAX_NUM_OF_READ_RETRIES配置的那样。
如果NVRAM Manger在从NV内存读取操作期间检测到失败,CRC错误,那么在继续读取ROM块之前,将进行一次或多次额外的读取尝试,如NVM_MAX_NUM_OF_READ_RETRIES所配置的。
如果NVRAM Manger在从NV内存读取操作中检测到失败,静态块ID检查,然后在继续读取冗余的NV块之前,根据NVM_MAX_NUM_OF_READ_RETRIES配置,进行一次或多次额外的读取尝试。
如果NVRAMManger在从NV内存读取操作中检测到一个失败,一个静态块ID检查,然后在继续读取ROM块之前,根据NVM_MAX_NUM_OF_READ_RETRIES配置,进行一次或多次额外的读取尝试。
3.25 写校验
当一个RAM Block被写入NV内存时,NV块会被立即读回来,并与RAM Block中的原始内容进行比较,前提是该行为被NVM_WRITE_VERIFICATION激活。
RAM Block中的原始内容与回读的块的比较应分步骤进行,以保证读取和比较的字节数不大于配置参数NVM_WRITE_VERIFICATION_DATA_SIZE所指定的字节数。
如果RAM Block中的原始内容与读回来的内容不相同,那么将向DEM报告生产代码错误NVM_E_VERIFY_FAILED。
如果RAM块中的原始内容与回读不相同,则应按照本文档的规定执行写重试。
如果回读操作失败,则不应执行读重试。
如果RAM块中的原始内容与回读不相同,对于初始的写尝试以及所有配置的重试,则NvM应将请求结果设置为NVM_REQ_NOT_OK。
3.26 比较NvM中的NV数据
为了避免在NV内存中进行不必要的写操作,如果特定RAM块的NV数据在运行时没有更新,NvM模块提供了一种基于CRC的比较机制,可以在处理写作业时应用。
NvM模块应该提供一个选项,通过实现基于CRC的比较机制来跳过写入未改变的数据。
注意:一般来说,有一个风险,RAM块的一些改变的内容导致相同的CRC作为初始内容,所以更新可能会丢失,如果使用这个选项。因此,这个选项应该只用于可以容忍这种风险的区块。
对于每个NVRAM块,都应该有可能通过参数NvMBlockUseCRCCompMechanism配置基于CRC比较机制的使用。
NvM模块应该为NVRAM块提供基于CRC的比较功能,且参数NvMCalcRamBlockCrc和NvMBlockUseCrc设置为true。
3.27 NvM和BswM交互
当NvM需要通知BswM一个多块请求状态变化时,它应该使用BswM API BswM_NvM_CurrentJobMode()。
如果NvMBswMMultiBlockJobStatusInformation为true, NvM将不会调用配置的多块回调。
当NvM需要通知BswM单个块请求接受(正在等待中)和结果时,它应该使用BswM API BswM_NvM_CurrentBlockMode()。
如果NvMBswMMultiBlockJobStatusInformation为true,当NvM接受一个多块操作时,NvM应该通过调用BswM_NvM_CurrentJobMode(具有相关服务ID,作为模式,为NVM_REQ_PENDING)来通知BswM接受的多块操作正在等待。
如果NvMBswMMultiBlockJobStatusInformation为true,当一个多块操作结束或被取消时,NvM将通过调用BswM_NvM_CurrentJobMode,将多块操作的结果通知给BswM,该BswM使用相关的服务ID和作为模式的多块操作的结果。
如果NvMBswMBlockStatusInformation为true,当NvM接受单个块操作时,NvM应该通过调用BswM_NvM_CurrentBlockMode(带有相关的block ID和作为模式的NVM_REQ_PENDING)来通知BswM接受的单个块操作正在等待。
如果NvMBswMBlockStatusInformation为true,当单个块操作完成或被取消时,NvM将通过调用BswM_NvM_CurrentBlockMode将单个块操作的结果通知BswM,该BswM调用带有相关块ID的BswM_NvM_CurrentBlockMode,作为模式,表示单个块操作的结果。
如果NvMBswMBlockStatusInformation为true,并且NvM有一个正在进行的多块操作,对于每一个由于多块操作而处理的块,NvM应该在开始处理该待处理的块时通知BswM,通过调用BswM_NvM_CurrentBlockMode与相关的块ID和作为模式的NVM_REQ_PENDING。
如果NvMBswMBlockStatusInformation为true,并且NvM有一个正在进行的多块操作,对于每一个由于多块操作而处理的块,NvM应该通过调用BswM_NvM_CurrentBlockMode来通知BswM该块处理完成的结果,该BswM使用相关的块ID和作为模式的单块操作的结果。
3.28 块锁定情况下的NvM行为
NvM_SetBlockLockStatus API服务只能被BSW组件使用,它没有作为服务发布在SWC-Description中。因此,它将不能通过RTE访问。
如果该API被调用时参数Locked为TRUE, NVM必须保证与BlockId标识的NVRAM块相关的NV内容不会被任何请求修改。在NvM_WriteAll过程中,Block应该被跳过,其他的请求,如NvM_WriteBlock, NvM_WritePRAMBlock, NvM_InvalidateNvBlock, NvM_EraseNvBlock,应该被拒绝。
如果API被调用时参数Locked为TRUE, NVM应该保证在下次启动时,在处理NvM_ReadBlock或NvM_ReadPRAMBlock时,这个NVRAM块应该从NV内存中加载。
如果Locked参数的值为FALSE,则NVM必须保证该NVRAM块按照AUTOSAR的规定正常处理。
使用该服务的设置不能被NvM_SetRamBlockStatus或NvM_SetBlockProtection改变。
3.28.1 用例
通过诊断服务为NVRAM块保存新数据到NV内存。这些数据应在下一次ECU启动时提供给swc (s),即它们既不能被来自swc的请求覆盖,也不能在关机期间被永久RAM块的数据覆盖(NvM_WriteAll)。
3.28.2 使用(DCM)
1)DCM请求NvM_SetBlockLockStatus(
2) DCM请求NvM_WriteBlock(
3)DCM轮询完成写请求(使用NvM_GetErrorStatus())
4) 当成功(NVM_REQ_OK), DCM发出NvM_SetBlockLockStatus(
审核编辑:汤梓红
评论
查看更多