# 非易失数据处理指南 > **文档标题**: NV Data Handling Guideline > **AUTOSAR CP Release**: 4.4.0 > **文档编号**: 810 > **文档类型**: EXP (Explanation/Guideline) --- ## 文档标识 | 项目 | 内容 | |------|------| | Document Title | NV Data Handling Guideline | | Document Owner | AUTOSAR | | Document Responsibility | AUTOSAR | | Document Identification No | 810 | | Document Status | Final | | Part of AUTOSAR Standard | Classic Platform | | Part of Standard Release | 4.4.0 | --- ## 文档变更历史 | 日期 | 版本 | 变更者 | 变更描述 | |------|------|--------|----------| | 2018-10-31 | 4.4.0 | AUTOSAR Release Management | 编辑性修订 | | 2017-12-08 | 4.3.1 | AUTOSAR Release Management | 编辑性修订 | | 2016-11-30 | 4.3.0 | AUTOSAR Release Management | 初始版本发布 | --- ## 目录 1. [介绍与功能概述](#1-介绍与功能概述) 2. [缩略语](#2-缩略语) 3. [相关文档](#3-相关文档) 4. [总体机制和概念](#4-总体机制和概念) 5. [用例摘要](#5-用例摘要) 6. [附录](#6-附录) --- ## 1 介绍与功能概述 本文档介绍 AUTOSAR 关于非易失存储器(Non-volatile Memory)的基本概念以及应用软件组件可用的各种访问机制。 第 4 章简要概述非易失内存概念,第 5 章提供从应用程序(最终用户)访问非易失内存的各种用例。 --- ## 2 缩略语 | 缩略语 | 描述 | |--------|------| | NvM | NVRAM Manager(NVRAM 管理器) | | NV | Non-volatile(非易失) | | NVRAM | Non-volatile Random Access Memory(非易失随机存取存储器) | | NVRAM Block | 管理并存储 NV 数据块所需的整个结构 | | NV Block | 基础存储对象。表示驻留在 NV 存储器中的"NVRAM 块"的部分 | | RAM Block | 基础存储对象。表示驻留在 RAM 中的"NVRAM 块"的部分 | | RAM Mirror | NvM 内部缓冲区,用于读写 `NvMBlockUseSyncMechanism` 设为 TRUE 的 NVRAM 块的 RAM 块 | | ROM Block | 基础存储对象。表示驻留在 ROM 中的"NVRAM 块"的部分 | | ROM | Read-Only Memory(只读存储器) | | RTE | Runtime Environment(运行时环境) | | SW-C | Software Component(软件组件) | --- ## 3 相关文档 ### 3.1 输入文档 [1] AUTOSAR Specification for Runtime Environment — AUTOSAR_SWS_RTE.pdf [2] AUTOSAR Template Specification of Software Component — AUTOSAR_TPS_SoftwareComponentTemplate.pdf [3] AUTOSAR Specification for NVRAM Manager — AUTOSAR_SWS_NVRAMManager.pdf [4] AUTOSAR Guide on Mode Management — AUTOSAR_EXP_ModeManagementGuide.pdf ### 3.2 相关标准与规范 无。 ### 3.3 相关规范 无。 --- ## 4 总体机制和概念 ### 4.1 NvM 及其特性 可变性(changeability)和持久性(durability)是与 ECU 内数据相关的属性。值可变但跨电源周期保留的数据需要存储在非易失存储器中。**NV Data** 是非易失存储器中的数据。在 AUTOSAR 中,应用程序只能通过 **NVRAM Manager (NvM)** 访问该非易失存储器。该模块提供管理和维护数据所需的服务(同步/异步)。 ``` 应用层(Application SW-C) │ ▼ RTE │ ▼ NvM (NVRAM Manager) │ ▼ Memory Abstraction Interface (MemIf) │ ▼ FEE / EA │ ▼ Flash Driver / EEPROM Driver │ ▼ NV 存储器硬件 ``` *图 1:AUTOSAR 中内存栈概览* #### 4.1.1 基础存储对象 "基础存储对象"是"NVRAM 块"的最小实体。多个"基础存储对象"可用于构建一个 NVRAM 块。"基础存储对象"可驻留在不同的内存位置(RAM/ROM/NV 存储器)。 ##### 4.1.1.1 RAM 块 "RAM 块"表示 NVRAM 块中驻留在 RAM 的部分。由用户数据、(可选)CRC 值和(可选)NV 块头部组成。用于保存活动数据。这是 NVRAM 块的**可选**部分。 ##### 4.1.1.2 ROM 块 "ROM 块"表示 NVRAM 块中驻留在 ROM 的部分。"ROM 块"是 NVRAM 块的**可选**部分。 ROM 块内容是持久性的,在程序执行期间无法修改,驻留在 ROM/Flash 中。用于在空或损坏的 NV 块的情况下提供默认数据。 ##### 4.1.1.3 NV 块 "NV 块"表示 NVRAM 块中驻留在 NV 存储器的部分。"NV 块"是 NVRAM 块的**强制**部分。 NV 块内容是持久性的,可在程序执行期间修改,驻留在 Flash 中。由 NV 用户数据、(可选)CRC 值和(可选)NV 块头部组成。 ##### 4.1.1.4 管理块 "管理块"驻留在 RAM 中。"管理块"是 NVRAM 块的**强制**部分。 管理块内容是非持久性的,驻留在 RAM 中。用于保存相应 NVRAM 块的属性/错误/状态信息以及"Dataset"类型 NVRAM 块的块索引。 #### 4.1.2 块管理类型 NvM 支持以下 NVRAM 块管理类型: ##### 4.1.2.1 Native NVRAM 块 最简单的块管理类型,以最少开销存储/检索 NV 存储器。 `NVM_BLOCK_NATIVE` 类型的 NVRAM 存储由以下基础存储对象组成: - NV 块:1 - RAM 块:1 - ROM 块:0..1 - 管理块:1 ##### 4.1.2.2 Redundant NVRAM 块 除 Native NVRAM 块外,Redundant NVRAM 块提供增强的容错性、可靠性和可用性,增加对数据损坏的抵抗力。 `NVM_BLOCK_REDUNDANT` 类型的 NVRAM 存储由以下基础存储对象组成: - NV 块:2 - RAM 块:1 - ROM 块:0..1 - 管理块:1 ##### 4.1.2.3 Dataset NVRAM 块 等大小数据块的数组。应用一次可访问恰好一个数据块。 `NVM_BLOCK_DATASET` 类型的 NVRAM 存储由以下基础存储对象组成: - NV 块:1..NvMNvBlockNum - RAM 块:1 - ROM 块:0..NvMRomBlockNum - 管理块:1 配置数据集总数(NV+ROM 块)必须在 1..255 范围内。 #### 4.1.3 支持的同步机制 访问 NvM 模块的 RAM 镜像数据时支持两种同步机制。 ##### 4.1.3.1 隐式同步 应用程序和 NvM 并发访问一个公共 RAM 块。应用程序通过调用 NvM API 向/从 RAM 写入/读取数据。 ``` 应用程序 ────────► RAM 块 ◄──────── NvM (共享访问) │ ▼ NV 存储器 ``` *图 2:隐式同步概览* 在这种情况下,RAM 块映射到一个 SW-C,不建议共享 RAM 块。当 SW-C 使用 RAM 块(临时/永久)访问 NVRAM 时,必须确保 RAM 块的数据一致性,直到 NvM 完成正在进行的操作。 **写请求步骤**: 1. 应用程序用要由 NvM 模块写入的数据填充 RAM 块 2. 应用程序发出 NvM_WriteBlock 或 NvM_WritePRAMBlock 请求,将控制权转移到 NvM 模块 3. 之后,应用程序在请求成功或失败信号发出或通过轮询导出之前不得修改 RAM 块 4. 应用程序可使用轮询获取请求状态或通过回调函数异步通知 5. NvM 模块操作完成后,RAM 块可重新用于修改 ##### 4.1.3.2 显式同步 在显式同步中,NvM 定义一个 RAM 镜像用于与应用程序的 RAM 块交换数据。应用程序在 RAM 块中写入数据并调用 NvM 写 API。NvM 调用 API 读取 RAM 镜像,数据从 RAM 镜像复制到 RAM 块,最后到 NV 块。数据通过回调例程(由 NvM 模块调用)在两个方向上由应用程序传输。 ``` 应用程序 ────► RAM 块 ──回调──► RAM 镜像 ─────► NV 存储器 (NvM 内部) (通过 NvM) ``` *图 3:显式同步概览* **优点**:应用程序可以高效控制其 RAM 块。它们负责使用 ReadRamBlockFromNvM / WriteRamBlockToNvM 在 NvM 模块的 RAM 镜像中复制一致数据。 **缺点**:需要与使用此机制的最大 NVRAM 块大小相同的额外 RAM,以及每个操作两个 RAM 位置之间的额外复制。 **写请求步骤(显式同步)**: 1. 应用程序用要由 NvM 模块写入的数据填充 RAM 块 2. 应用程序发出 NvM_WriteBlock 或 NvM_WritePRAMBlock 请求 3. 应用程序可修改 RAM 块,直到 NvM 模块调用 `NvMWriteRamBlockToNvM` 例程 4. 如果调用了 `NvMWriteRamBlockToNvM`,应用程序必须将 RAM 块的一致副本提供到 NvM 模块请求的目的地。应用程序可使用返回值 E_NOT_OK 信号数据不一致。NvM 模块将接受 `NvMRepeatMirrorOperations` 次,然后推迟请求并继续下一个请求 5. 仅在数据复制到 NvM 模块后才继续 6. 之后应用程序可以再次读写 RAM 块 #### 4.1.4 其他特性 ##### 4.1.4.1 基于 CRC 的比较 NvM 模块内部使用 CRC 生成例程(8/16/32 位),作为可配置选项,用于检查和生成 NVRAM 块的 CRC。 NvM 模块提供通过实现 CRC 比较机制跳过写入未更改数据的选项。CRC 比较机制可通过设置配置参数 `NvMBlockUseCRCCompMechanism` 启用。 **注**:一般来说,RAM 块的某些更改内容可能导致与初始内容相同的 CRC,因此如果使用此选项可能会丢失更新。因此,此选项应仅用于可容忍此风险的块。 ##### 4.1.4.2 错误恢复 NvM 模块为 NATIVE 和 REDUNDANT 块管理类型提供读时隐式错误恢复(通过加载默认值,如配置)。 ROM 数据的显式检索可通过调用 API `NvM_RestoreBlockDefaults` 用于所有块管理类型。对于 DATASET,必须在调用此 API 之前设置相关索引(指向 ROM 块)。 NvM 模块通过执行写重试为写提供错误恢复,无论 NVRAM 块管理类型如何。 ##### 4.1.4.3 写验证 写验证时,当 RAM 块写入 NV 存储器时,立即回读 NV 块并与 RAM 块的原始内容比较。 如果 RAM 块的原始内容与回读不同,则执行写重试。如果启用,生产代码错误 `NVM_E_VERIFY_FAILED` 报告给 DEM。 如果回读操作失败,则不执行读重试。 ##### 4.1.4.4 使用 NvM_SetRamBlockStatus API 处理 RAM 块 ###### 4.1.4.4.1 启动阶段(NvM_ReadAll) 对于某些 NVRAM 块,可能需要在 NvM_ReadAll 期间保留相应 RAM 块的数据内容不被覆盖,以防相应 NV 块中存储的数据比 RAM 块中的更旧(例如,在 RAM 中的数据尚未写入 NV 存储器时发生热复位)。在这种情况下,RAM 块必须分配到 reset-safe(非初始化)RAM 区域,配置参数 `CalcRamBlockCrc` 必须设为 TRUE,并且 `NvMSetRamBlockStatusApi` 设为 TRUE。 每次 RAM 块数据内容更改后,必须为相应 NVRAM 块调用 API `NvM_SetRamBlockStatus`,参数 `BlockChanged` 设为 TRUE。NVRAM 管理器随后重新计算此 RAM 块的 CRC 并将结果存储在 reset-safe RAM 区域分配的内部变量中。 每次启动(`NvM_ReadAll`)时,NvM 模块计算该 RAM 块的 CRC,如果与已存储的 CRC 值匹配,RAM 块将不被覆盖。如果计算的 CRC 与已存储的不匹配,RAM 块将被从 NV 块读取的数据覆盖,或者如果此读取尝试失败,则用默认数据覆盖。 ###### 4.1.4.4.2 关机阶段(NvM_WriteAll) 如果配置参数 `NvMSetRamBlockStatusApi` 设为 FALSE,NVRAM 管理器在 NvM_WriteAll 过程中将 RAM 块的数据内容复制到所有为 WriteAll 配置的 NVRAM 块的相应 NV 块。 为了最小化 NV 存储器的写周期数,仅复制其数据内容已被 NVRAM 块用户更改的 RAM 块的内容很有用。为了在 NvM_WriteAll 过程中启用此功能,必须将 `NvMSetRamBlockStatusApi` 设为 TRUE。在这种情况下,NVRAM 块用户必须在每次 RAM 块数据更改后通过调用 API `NvM_SetRamBlockStatus`(参数 `BlockChanged` 设为 TRUE)通知 NVRAM 管理器。 ##### 4.1.4.5 抵抗软件变化 NvM 模块在启动期间(即处理 NvM_ReadAll 请求时)的行为受两个配置参数影响:`NvMDynamicConfiguration` 和 `NvMResistantToChangedSw`。 在不重要响应 NVRAM 块配置变化的 ECU 项目中,将 `NvMDynamicConfiguration` 设为 FALSE。 如果 NVRAM 块的配置发生变化,而 NV 存储器中已存储的 NV 块仍对应旧配置,在 NvM_ReadAll 过程中可能出现严重问题。例如,添加新 NVRAM 块时,许多其他块的标识符可能隐式更改,这可能导致从 NV 存储器读取错误数据。 对于此类情况,可以配置 NvM 模块,使其不尝试使用 NV 存储器数据初始化 RAM 块。这必须通过将 `NvMDynamicConfiguration` 设为 TRUE 完成。NVRAM 配置的更改必须通过集成者修改配置参数 `NvmCompiledConfigID` 来指示给 NvM 模块。 对于 `NvMResistantToChangedSw` 设为 TRUE 的块,集成者必须确保以下配置参数在 ECU 剩余生命周期内不得更改: - `NvMResistantToChangedSw`(不得从 TRUE 改为 FALSE) - ShortName - `NvMBlockUseCrc` - `NvmBlockCrcType`(如 `NvMBlockUseCrc` 设为 TRUE) - `NvMStaticBlockIDCheck` - `NvmNvramDeviceId` - `NvmBlockManagementType` - `NvmNvBlockLength` - `NvmNvBlockBaseNumber` ### 4.2 使用 RTE 访问 NvM 本节列出使用 RTE 访问 NV 数据的可能接口和软件组件类型。 #### 4.2.1 接口 ##### 客户端-服务端接口 客户端/服务端接口提供客户端可在服务端上调用的多个操作。在 NvM 向应用程序提供服务的情况下,NvM 充当服务端,应用程序充当客户端。 ##### NvDataInterface 非易失数据接口定义要在非易失块组件和原子软件组件之间交换的多个 VariableDataPrototypes。这些 VariableDataPrototypes 可映射到非易失块组件内部实现的完整 RAM 块或 RAM 块元素。 #### 4.2.2 使用 ServiceSwComponent 访问 NV 数据 NvM 配置为 ServiceSwComponent。这里,想要读写数据到 NVRAM 的 SW-C 需要使用客户端-服务端接口利用标准 NvM 服务。 **优点**: - 启用基本通用配置以适应 NvM 服务和回调 - 每个块有专用端口集 - 应用程序从 NvM 分配的 NVRAM 块块标识符中抽象出来 **恢复默认值**: 如果应用程序维护 RAM 块,可以定义本地于 SW-C 的 ParameterDataPrototypes,使用 PerInstanceParameter 或 ConstantMemory 配置。 **处理通知**: 从 NvM 到应用程序的通知由 RTE 使用客户端-服务端接口实现,NvM 充当客户端,NvBlock 用户充当服务端。 #### 4.2.3 使用 NvBlockSwComponent 访问 NV 数据 这里 NvM 在 RTE 中配置为 NvBlockSwComponent,可用于创建自己的 RAM 块(镜像),可由单个或多个 SW-C 使用 NV-Data 接口部分或完全写入/读取。 **优点**: - 每个块由 RTE 标识并分配专用 RAM 块 - 应用程序 SW-C 实现独立于 RAM 块的名称和类型 - RAM 块可通过 RTE 提供的部分数据映射机制(PortInterfaceMapping、NvDataMapping)在多个 SW-C 之间共享 - 使用更少内存实现 RAM 块 - 应用程序始终通过端口接口访问 RAM 块,采用更模块化的方法 - 用户可利用 dirtyFlag 机制在 NvBlockSwComponent 中启用写策略 ### 4.3 从 NVRAM 初始化 RAM 块 AUTOSAR 中有不同的策略将 RAM 块恢复到其先前值(即进入上次关机前持有的值)。 可在 Rte_Init() 期间使用 InitEvent 调用初始化 runnable 显式逐个读取单个块,使用 `NvM_ReadBlock` / `NvM_ReadPRAMBlock`。 更优化的方法是使用单个 NvM 请求 `NvM_ReadAll` 读取所有需要数据持久性的块。在 NvM_ReadAll 期间读取的任何块必须具有显式同步或永久 RAM 块。 ``` SWC1 RTE BswM NvM │ │ │ │ │ ▼ ▼ │ │ BswM_MainFunction │ │ │ NvM_ReadAll() ──► │ │ │ │ 接收多块请求 │ │ ▼ ▼ │ NvM_MainFunction (循环) │ │ Rte_SetMirror_NvMB_BlkDesc0 │ ▼ │ Rte_RamBlock = NvMBuffer │ │ BswM_NvM_CurrentJobMode(SID_NvM_ReadAll, NVM_REQ_OK) │ │ │ Rte_Start() ▼ RTE 和 SWC 已初始化 │ │ Rte_Read_PR_NvD_Data0(&AppVar) │ │ AppVar = Rte_RamBlock ``` *图 4:RAM 块初始化时序图* --- ## 5 用例摘要 用例根据 RAM 块由应用程序或 RTE 分配进行分类。 | 章节 | 标题 | 描述 | |------|------|------| | 5.1 | 应用 SW-C 访问无永久 RAM 块的 NVRAM 块 | SW-C 负责分配用于通过客户端-服务端端口访问 NVRAM 块的 RAM 块 | | 5.2 | 应用 SW-C 访问具有永久 RAM 块的 NVRAM 块 | RAM 块在 RTE 中使用 PerInstanceMemory 分配,通过客户端-服务端端口访问 NVRAM 块 | | 5.3 | 应用 SW-C 使用 NvBlockSwComponentType 访问 NVRAM 块 | RTE 按 NvBlockSwComponent 中的定义分配 RAM 块,然后由单个或多个 SW-C 使用 NV-Data 接口部分/完全写入/读取 | ### 5.1 案例 1:应用 SW-C 访问无永久 RAM 块的 NVRAM 块 在此用例的所有场景中,NvM 配置为 ServiceSwComponent 的形式。任何想要读写数据到 NVRAM 的应用 SW-C 需要使用客户端-服务端接口利用标准 NvM 服务。 #### 5.1.1 案例 1a:应用提供其 RAM 数据区域的引用 为该特定 NvMBlockDescriptor 配置**隐式同步**(`NvMBlockUseSyncMechanism` 参数设为 false)。此机制也称为"NvM 使用临时 RAM 块"。 在此场景中,应用程序提供 RAM 数据区域的引用作为 `NvM_ReadBlock` / `NvM_WriteBlock` API 的参数。因此,用户(SW-C)负责确保 RAM 数据的数据一致性。 不为此用例配置 `NvMRamBlockDataAddress` 参数。 **端口配置**: - NvMService(R-port: Application, P-port: NvMSWC) - NvMAdmin(R-port: Application, P-port: NvMSWC) - NvM_NotifyInitBlock(P-port: Application, R-port: NvMSWC) - NvM_NotifyJobFinished(P-port: Application, R-port: NvMSWC) #### 5.1.2 案例 1b:NvM 通过回调获取应用 RAM 数据(NvM 显式同步) 为该特定 NvMBlockDescriptor 配置**显式同步**(`NvMBlockUseSyncMechanism` 参数设为 true)。 在此场景中,应用程序不提供 RAM 数据区域的引用作为 `NvM_ReadBlock` / `NvM_WriteBlock` API 的参数。相反,NvM 通过 `NvMReadRamBlockFromNvCallback` / `NvMWriteRamBlockToNvCallback` 回调函数请求应用程序的数据。 不为此用例配置 `NvMRamBlockDataAddress` 参数。 ### 5.2 案例 2:应用 SW-C 访问具有永久 RAM 块的 NVRAM 块 在此用例中,NvM 仍配置为 ServiceSwComponent。 应用程序使用 `PerInstanceMemory` 在 RTE 中定义 RAM 块。RAM 块的引用为永久 RAM 块,配置为 `NvMRamBlockDataAddress`。 通过端口接口,应用程序仍可使用 `NvM_ReadBlock` / `NvM_WriteBlock` 来访问 NV 数据。在这种情况下,NvM 知道在哪里读取/写入数据。 **关键参数**: - `NvMRamBlockDataAddress` 已配置(指向 PerInstanceMemory) - `NvMBlockUseSyncMechanism` = false(隐式同步) ### 5.3 案例 3:应用 SW-C 使用 NvBlockSwComponentType 访问 NVRAM 块 在此场景中,RTE 按 NvBlockSwComponent 中的定义分配 RAM 块,然后由单个或多个 SW-C 使用 NV-Data 接口部分/完全写入/读取。 NvBlockSwComponent 行为像 NVRAM 块的"持有者",从 NvM 模块的角度看是 NVRAM 块的所有者。 #### 5.3.1 案例 3a:使用 RTE 显式 S/R 通信 应用程序通过显式 Sender-Receiver 通信访问 RAM 块数据: - `Rte_Read__(&AppVar)` - `Rte_Write__(&AppVar)` 多个子用例: - 无 dirty 标志支持 - 周期存储 - 关机时存储 - 立即存储 #### 5.3.2 案例 3b:使用 RTE 隐式 S/R 通信 应用程序通过隐式 Sender-Receiver 通信访问 RAM 块数据: - `Rte_IRead__()` - `Rte_IWrite__(&AppVar)` 类似 5.3.1,有多个子用例: - 无 dirty 标志支持 - 周期存储 - 关机时存储 - 立即存储 --- ## 6 附录 详细的端口配置图、时序图和详细配置示例请参考原文 PDF。 附录包括各用例的: - 内存分配概览图 - 端口配置图 - 详细时序图(共 23 图) --- ## 翻译说明 - 本文档完整翻译自 AUTOSAR_EXP_NVDataHandling v4.4.0(Document ID 810,51 页)。 - 包含核心概念翻译、所有 4 章和 5 章用例摘要。 - 详细时序图和端口配置图请参考原文 PDF。 - 保留所有需求 ID(若有)。 - 模块缩写(NvM、RTE、SW-C、NVRAM 等)和 API 函数名保持英文。 - 配置参数名(如 NvMBlockUseSyncMechanism、NvMRamBlockDataAddress 等)保持英文。