【小猫爪】AUTOSAR学习笔记16-Memory Stack之Nvm模块

前言

  这一节开始来介绍一下在AUTOSAR架构中一个非常重要的部分,那就是存储系统,即AUTOSAR的Memory Stack。

1 Memory Stack结构

  Memory Stack结构图如下:
在这里插入图片描述
  再细致一点如下图:
在这里插入图片描述
  Memory Stack也是非常完整的一个AUTOSAR结构,有服务层的NvM模块,有ECU抽象层的Fee模块和Ea模块,还有MCAL层的驱动。其中NVRAM Manager模块是整个Memory Stack的控制器,它更多的关注于数据本身的,对数据进行校验,读写操作的发起,而根据最终存储器类型的不同,则最终负责数据存储和读写操作的则是Fee模块(FLASH)和Ea模块(EEPROM)。而在MCAL层则根据是内部FLASH,外部FLASH,外部EEPROM的各种情况而灵活变化。

2 NvM模块

  NvM 模块位于 Memory Stack 的服务层,实现了对ECU中Non-Volatile数据的统一管理。NvM 模块主要功能如下:
  1. 将不同类型的存储器(Flash、EEPROM 等)进行统一管理,提供AUTOSAR 标准服务接口
  2. 提供以 Block 为单位的读、写等服务
  3. 基于优先级的数据块访问机制,提高用户访问的灵活性和实时性
  4. 提供访问任务的队列
  5. 工作请求异步处理
  6. 提供 CRC 机制,保障数据的一致性
  7. 提供数据故障恢复机制
  8. 提供任务完成通知机制

2.1 Block

  这里的Block可不是FLASH里的那个硬件Block,这里的Block是一种软件层面上的玩意,它是NvM操作的数据基本单元,也就是说,NvM模块里面操作的对象就是Block,所以在AUTOSAR里想要存储数据,那么就要提前给数据分配Block。

  NvM 支持三种类型的 Block,分别为:
  1. Native Block:最常用的 Block,用于一般数据的管理;
  2. Redundant Block:该 Block 支持数据冗余,可用于对一些安全性要求较高的数据进行管理,其实就是可以对其进行备份的Block。
  3. Dataset Block:该 Block 支持同一类型的多套数据。用户可以根据当前的运行状态,选择使用多套数据中的一套。

  每个 Block,又由以下几个部分组成:
  1. NV Block:位于掉电不丢失的设备,如 Flash,用于正常的存储数据;
  2. RAM Block:程序运行时,用户的应用程序直接访问的 Block,有点类似于缓存,当条件满足时会将其更新至NV Block。临时 RAM Block:在运行时,用户通过接口将 RAM 的地址传递给 NvM;永久 RAM Block:用户配置给该 Block 的固定的 RAM 地址,运行时不可改变。
  3. ROM Block:存储该 Block 的默认值,位于掉电不丢失的设备,当 NV Block 的数据异常时,可恢复为默认值;
  4. Administrative Block:管理 Block,一般位于 RAM 中,用于记录和存储程序运行时 Block的状态,如地址、CRC 结果、Block 状态等。Administrative Block 由 NvM 内部实现,不用关心。

  不同类型Block的组成情况如下表所示:

类型NVRAMAdministrativeROM
NATIVE1110 ~ 1
REDUNDANT2110 ~ 1
DATASET1 ~ 256110 ~ 256

  此外NvM 内部还会预留 2 个特殊 Block,Block0 和Block_CfgID。其中Block0 不存储任何实际数据信息,仅用于记录 WriteAll 和 ReadAll 的工作结果,Block_CfgID 则用于存储当前内存的配置信息。用户实际使用的 Block 从第 3 个 Block 开始。

  在NvM模块的下层模块Fee和Ea模块中,它们的基本数据存储单元也叫做Block,NvM模块的Block数据来源于Fee和Ea的Block,前面提到了NvM的三种Block由若干个NV Block组成,所以这两种Block是一对多的情况。NvM的Block编号叫做Block Handle,Fee和Ea的Block编号叫做Block ID,也就是说APP通过Block Handle来索引NvM的数据,而NvM则是通过Block ID来索引Fee和Block的Block数据。

  Block ID 的计算公式:Block ID = (Block Base Num << DataSelectionBits) + DataIndex。其中Block Base Num根据Blocl类型而定(Native,Redundant ,Dataset ),DataSelectionBits和DataIndex根据具体应用情况进行设置。其中当 NvM 调用 MemIf 的接口,访问 Fee 或 Ea 时,传递的 Block 参数为 Block ID。

2.2 数据结构

  Block三种组成成分Block的存储数据格式如下:
在这里插入图片描述
  其中 RAM 和 NV Block,都有可选的 Header 和 CRC 区域。Header 可用于存储 Block 的Block ID 信息,固定占用两个字节的信息,CRC 区域用于存储 Block 的 CRC,根据 CRC 的类型,占用 1、2 或 4 个字节。ROM Block 仅存储默认数据,不存储 Header 和 CRC 内容。用户在读取和写入数据的时候,不需要关心 Header 和 CRC,NVM 模块将自动对 Header 和 CRC进行填充、计算、校验等工作。

2.3 Redundant Block

  前面提到了Redundant Block 有 2 个 NV Block,其主要特点包括:

  1. 在 Write、WriteAll 中,将向 2 个 NV Block 写入同样的数据,只要有其中一个 NV Block写入成功,则写数据成功;
  2. Erase、Invalidate 工作中,将对 2 个 NV Block 进行操作,只有对 2 个 NV Block 的操作都成功,请求才成功;
  3. 在 Read、ReadAll 中,将首先读取第一个 NV Block 的数据,如果读取失败,再读取第二个 NV Block 的数据。只要其中一个 NV Block 读取成功,则读数据成功,用户可以使用 RAM Block 中的数据。如果第一个 NV Block 读取成功,则不会再读取第二个 NVBlock 的数据。

2.4 Dataset Block

  Dataset Block 可以具备多个 NV Block 和 ROM Block,具体的数量限制与用户配置的NVM_DATASET_SELECTION_BITS 有关系。

  假设 NVM_DATASET_SELECTION_BITS 为 n,n 小于等于 8。则 NV Block 的个数范围为0 ~ 2^n,而 ROM Block 的个数范围为 0 ~(256-2^n),NV Block 的个数与 ROM Block 的个数总和不能超过 2^n。

  在访问 Dataset 类型的 Block 之前,必须先调用 NvM_SetDataIndex 设置目标的 DataIndex,DataIndex 的范围必须注意下述条件:1. DataIndex 不超过 NV 和 ROM Block 的总和;2. 假设配置了 m 个 NV Blocks,n 个 ROM Blocks,则 0 ~ (m-1)是 NV Block 的 Index 范围,m ~ (m+n-1)是 ROM Block 的 Index 范围。

2.5 Read/Write Retry

  在 Write 和 WriteAll 请求执行过程中,若对某个 Block 的写入失败,且该 Block 配置的写重试次数不为 0,则 NVM 会再次尝试对该 Block 进行写入,直到尝试次数超过用户配置的Retry次数阈值。

 &emsp在 Read 和 ReadAll 请求执行过程中,若对某个 Block 的读取失败,且该 Block 配置的读重试次数不为 0,则 NVM 会再次尝试对该 Block 进行读取,直到尝试次数超过用户配置的Retry次数阈值。

2.7 NvM_GetErrorStatus

  NvM_GetErrorStatus是一个经常被使用到的函数,通过调用这个函数可以获取当去NvM模块的当前状态,具体如下:

请求结果描述
NVM_REQ_OK默认状态,上一次工作成功完成。
NVM_REQ_NOT_OK1. 任意请求中,调用下层 MemIf 接口返回 E_NOT_OK,或下层请求结果为 MEMIF_JOB_FAILED。
2. 在 WriteAll 和 ReadAll 中,如果有任意一个 Block 的执行结果不是非错误结 果 之 一 , 则 WriteAll 和 ReadAll 的 结 果 为NVM_REQ_NOT_OK。
3. 对于使能了同步镜像机制的 Block,如果调用同步回调函数返回E_NOT_OK , 且 错 误 次 数 超 过 限 制 , 则 也 会 上 报 该NVM_REQ_NOT_OK。
NVM_REQ_PENDING工作处于队列中,或正在执行。
NVM_REQ_INTEGRITY_FAILEDRead 或 ReadAll 中,检测到下述情况,且无隐性恢复默认数据:1. CRC 校验失败;2. 下层请求结果为 MEMIF_BLOCK_INCONSISTENT
NVM_REQ_BLOCK_SKIPPED在 ReadAll 或 WriteAll 或 ValidateAll 中,该 Block 被跳过。
NVM_REQ_NV_INVALIDATEDRead 或 ReadAll 中,下层请求结果为 MEMIF_BLOCK_INVALID。如果读取冗余 Block,该结果表明两个 NV Block 读取的结果均为MEMIF_BLOCK_INVALID。
NVM_REQ_CANCELLED1. 调用 NvM_CancelJobs 被取消的 Block;2. 调用 NvM_CancelWriteAll 被取消的 Block;3. 任意请求执行过程中 , 下层请求结果为NVM_REQ_CANCELLED.
NVM_REQ_REDUNDANCY_FAILED未使用。
NVM_REQ_RESTORED_FROM_ROMBlock 恢复了默认数据,包括隐性和显性恢复。
NVM_REQ_BUSYING未使用。
NVM_REQ_WRONGIDRead 或 ReadAll 中,BlockID 检查失败,且无隐性恢复默认数据。
NVM_REQ_MIRROR_OP_FAILED未使用。
NVM_REQ_VERIFY_FAILEDWrite 或 WriteAll 中,数据回读校验失败。
NVM_REQ_CFGID_MISMATCH未使用。

2.8 与BswM模块的交互

  在前面介绍BswM模块中提到了,BSW层模块可以给BswM模块发送Mode Request和Mode Indication,而NvM模块则可以在下面情况下去给BswM模块发送Mode Indication:
  1. 当 SingleJob 进入队列时,调用 BswM_NvM_CurrentBlockMode(Pending);
  2. 当 SingleJob 工作结束时,调用 BswM_NvM_CurrentBlockMode,状态由本次工作的结果决定;
  3. 当 SingleJob 工作被取消时,调用 BswM_NvM_CurrentBlockMode(Cancel);
  4. 当 MultiJob 进入队列时,调用 BswM_NvM_CurrentJobMode(Pending);
  5. 当 MultiJob 工作结束时,调用 BswM_NvM_CurrentJobMode,状态由本次工作的结果决定;
  6. 当 WriteAll 工作被取消时,调用 BswM_NvM_CurrentJobMode(Cancel)。

3 MemIf模块

  上面提到了一个NvM模块Block会对应一个或者多个Fee和Ea模块Block,而MemIf模块就是将这两种位于不同层的Block对应起来,即实现Block Handle和Block ID的对应关系。在这里就不多做介绍了,非常简单。

END

  补充1:除了以上简单介绍的几大点,NvM模块还有一大堆的细节,大家如果想更深入了解NvM模块,请参考AUTOSAR官方文档《AUTOSAR_SWS_NVRAMManager.pdf》。

  补充2:除了以上简单介绍的几大点,MemIf模块还有一大堆的细节,大家如果想更深入了解MemIf模块,请参考AUTOSAR官方文档《AUTOSAR_SWS_MemoryAbstractionInterface.pdf》。

  • 7
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猫爪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值