AUTOSAR NvM 同步机制

news/2025/1/16 0:08:26/

一、部分 NvM API 解释

(1)Std_ReturnType NvM_ReadBlock(NvM_BlockIdType BlockId,void* NvM_DstPtr)

把Nv Block中的数据copy到NvM_DstPtr指向的RAM中,NvM_DstPtr可以是临时RAM,也可以是永久RAM(永久RAM即配置工具中配置的RAM Block)。如果NvM_DstPtr是NULL_PTR,且配置了永久RAM,那么数据会被copy到永久RAM中。

(2)Std_ReturnType NvM_WriteBlock(NvM_BlockIdType BlockId,const void* NvM_SrcPtr)

把NvM_SrcPtr指向的RAM中的数据Copy到NvBlock中,NvM_SrcPtr可以是临时RAM,也可以是永久RAM。如果NvM_SrcPtr是NULL_PTR,且配置了永久RAM,那么数据会从永久RAM中copy到NvBlock。

(3)Std_ReturnType NvM_ReadPRAMBlock(NvM_BlockIdType BlockId)

等同于(1)的NvM_DstPtr = NULL_PTR时的作用,即把NvBlock中的数据copy到配置的永久RAM中。

(4)Std_ReturnType NvM_WritePRAMBlock(NvM_BlockIdType BlockId)

等同于(2)的NvM_SrcPtr = NULL_PTR时的作用,即把数据从永久RAM中copy到NvBlock。

二、隐式同步

一个NvBlock(下图蓝色块)对应一个RAM Block(下图橙色块),可以是临时RAM,也可以是永久RAM,这个RAM Block建议只被一个SWC(APP)使用。

在这里插入图片描述

APP在写入数据时的流程如下:

  • (1)SWC把新的数据写到RAM Block中
  • (2)APP调用 NvM_WriteBlock 或 NvM_WritePRAMBlock(仅当RAM Block是永久RAM时),请求把RAM Block中的数据写入 NvBlock。
  • (3)从发起请求开始,到NvM模块写入完成为止(不管成功还是失败)的这段时间内,APP不能再次更改RAM Block中的值,但可以读取。
  • (4)APP可以用轮询的方式周期性检查NvM写入操作是否完成,NvM也可以用回调函数的方式来通知APP操作完成。
  • (5)当NvM操作完成后,APP才可以重新更改RAM Block中的值。

APP在读取数据时的流程如下:

  • (1)APP提供一个RAM Block,用来装从NvBlock中读取的数据。
  • (2)APP调用NvM_ReadBlock,发起请求把数据从NvBlock读取到RAM Block。
  • (3)从发起请求到NvM操作完成的这段时间内,APP不能读取和写入RAM Block中的值。
  • (4)APP可以用轮询的方式周期性检查NvM写入操作是否完成,NvM也可以用回调函数的方式来通知APP操作完成。
  • (5)当NvM操作完成后,RAM Block中就是读取到的新的数据了,这个时候APP才可有使用。

在这种机制下,NvM不对RAM Block的数据一致性(数据一致性简单理解就是数据的正确性,比如我想要写什么数据,最终写入的就是什么数据)负责,使用RAM Block的APP负责确保RAM Block的数据一致性,也就是说在NvM写入和读取NvBlock期间,不能再更改RAM Block的值,以及在NvM读取数据期间,不访问RAM Block。

不推荐多个SWC共享一个RAM Block。因为如果多个SWC共享一个RAM Block,那么不仅要确保这些SWC在访问RAM Block的时候互相之间不冲突,还要确保在NvM写入期间所有的SWC都不能访问这个RAM Block。这套机制会很复杂,而且容易出问题,比如:APP用NvM回调函数的方式来判断NvM写入是否完成,APP1发起了一个NvM写入请求,然后等待写入完成的回调函数被触发,之后回调函数被触发了,但其实触发这个回调函数的写入操作不是这个APP1请求的,而是另一个APP2在之前请求的,此时APP1认为RAM Block中的数据已经被写入NvBlock了,但实际还没有。诸如此类,总之就是机制很复杂,且容易出问题,不推荐。但你要非得用隐式同步且多个APP共享一个RAM Block行不行呢,我觉得应该也行,但需要详细的去设计整套逻辑,确保使用时不冲突。

三、显式同步

显式同步与隐式同步相比较,多了一个RAM块——RAM Mirror:
在这里插入图片描述

首先我们来看一看达芬奇中和这个有关的几个配置项:
在这里插入图片描述
其中Use Synchronization Mechanism用来配置是否使用显式同步,下面两个回调函数我们在后文将会介绍怎么使用。如果勾选了使用显式同步,那么将不允许配置RAM Block Data,NvM协议栈会自动为其分配一个RAM Mirror,也就是上图中的RAM Mirror。

我们来看看显式同步的数据写入和读取流程:

写入流程:

  • APP把想要写入的数据存到RAM Block中。
  • APP调用NvM_WriteBlock或NvM_WritePRAMBlock,发起一个写入数据请求。如果调用NvM_WriteBlock这个API的话,需要输入一个SrcPtr的地址,但我理解这个地址现在是没用的,所以可能输入啥都行,这个未验证,存疑。这一步的目的就是发起一个写入数据的请求。
  • NvM模块之后会调用Write Ram Block To Nv Callback这里配置的回调函数,在调用这个回调函数之前APP都可以修改RAM Block中的值。
  • 当NvM模块调用Write Ram Block To Nv Callback这个回调函数时,会有一个输入参数,如下面的代码所示,即RAM Mirror的地址,APP应该在这个回调函数中把RAM Block中的数据copy到RAM Mirror中,这个时候APP要确保copy的数据的一致性,也就是在复制数据的过程中不能允许其他APP访问。这个回调函数可以返回E_OK或E_NOT_OK,如果复制过程中出现问题返回了E_NOT_OK,NvM协议栈会自动重复调用这个回调函数,重复次数最多为NvMRepeatMirrorOperations配置的次数。
typedef P2FUNC(Std_ReturnType, NVM_APPL_CODE, NvM_WriteRamToNvMCbkPtrType)(P2VAR(void, AUTOMATIC, NVM_APPL_DATA) NvMBuffer);
  • APP复制数据完成后,APP就可以再次读写RAM Block中的值了。
  • APP可以用轮询的方式获取NvM的操作结果,NvM也可以用回调函数的方式通知APP操作结果。

读取流程(与写入类似):

  • APP准备一个RAM Block用来存储从NvM Block读取的数据。
  • APP调用API NvM_ReadBlock 或 NvM_ReadPRAMBlock发起一个NvM读取数据请求。
  • NvM模块之后会调用Read Ram Block From Nv Callback这里配置的回调函数,在调用这个回调函数之前APP都可以读写RAM Block中的值。
  • 当NvM模块调用Read Ram Block From Nv Callback这个回调函数时,会有一个输入参数,如下面的代码所示,即RAM Mirror的地址,与上面的区别是这次是个常量指针,因为是APP在这个回调函数中把RAM Mirror中的数据copy到RAM Block中,这个时候APP也要确保copy的数据的一致性,也就是在复制数据的过程中不能允许其他APP访问RAM Block。这个回调函数可以返回E_OK或E_NOT_OK,如果复制过程中出现问题返回了E_NOT_OK,NvM协议栈会自动重复调用这个回调函数,重复次数最多为NvMRepeatMirrorOperations配置的次数。
typedef P2FUNC(Std_ReturnType, NVM_APPL_CODE, NvM_ReadRamFromNvMCbkPtrType)(P2CONST(void, AUTOMATIC, NVM_APPL_DATA) NvMBuffer);
  • APP复制数据完成后,APP就可以再次使用RAM Block中的值了。
  • APP可以用轮询的方式获取NvM的操作结果,NvM也可以用回调函数的方式通知APP操作结果。

我们对比隐式同步可以看到,APP在大部分时间都可以读写RAM Block中的数据,只有在两个回调函数中复制数据的极短时间内不能使用RAM Block,所以显式同步使得APP在使用RAM Block中的数据的时候更加方便灵活。缺点就是多占用一块RAM 空间,且多了一步copy的操作。

显式同步与隐式同步最根本的区别就是,显式同步APP是知道NvM使用RAM Block的起始时间点和结束时间点的,而且这两个时间点是APP自己来控制的,即两个回调函数中的复制操作起始和结束的时间点。APP不需要通过读取NvM的操作状态来判断当前是否可以使用RAM Block。

显式同步是支持多个APP共享一个RAM Block的,机制也比较简单,设置一个互斥量或AUTOSAR OS中的Resource来保护一下,哪个APP或上面的两个回调函数使用RAM Block前申请一下互斥量,使用完了再释放就可以了。

注意一点:如果APP1先发起了一个写入或读取的请求,但NvM还没有处理,回调函数也还没有调,APP2有发起了一个相同类型(指写入或读取)的请求,那么这两个(或多个)请求会被合并,NvM只会处理一次,回调函数只会调一次。


http://www.ppmy.cn/news/71305.html

相关文章

森海塞尔及诺音曼携重磅新品亮相2023广州国际专业灯光、音响展览会

森海塞尔及诺音曼携重磅新品亮相2023广州国际专业灯光、音响展览会 以卓越产品和创新技术引领专业音频行业发展 广州,2023年5月16日——森海塞尔和诺音曼将于2023年5月22日至25日,携重磅新品及全新音频技术亮相第21届广州国际专业灯光、音响展览会。森海…

「聊天机器人构建、智能文档问答」大模型应用开发实操课程来了

此刻,生成式 AI 正以惊人的势头改变着我们的世界,无论是在科技、商业还是日常生活中,新的浪潮席卷着全球各个行业和领域。 跟过去十几年中“有多少人工就有多少智能”的智障 AI 比起来,大模型如 OpenAI 的 GPT-4 、百度的文心一言…

Cesium源码分享--标绘

Cesium标绘插件 在线api文档说明 在线体验地址1(三维框架内) 在线体验地址2 更多案例地址 免费gis数据 ps:如果可以的话,希望大家能给我个star,好让我有更新下去的动力; 实现原理: 其中实…

Oracle 21c部署 in Docker

目录 # 热分配新硬盘 # 拉取镜像 # 启动数据库 访问Oracle数据库 本环境的用途为开发测试环境;所以,分配给Oracle的资源相对较低;如果在生产环境下,请提前规范分配的CPU、内存、IO、磁盘(本地磁盘 or 网络存储、磁…

Day01 关系型数据MySQL简介与多平台安装配置

在大数据的课程中,我们需要处理的数据来自不同的渠道,其中有一个很重要的渠道就是关系型数据库中存储的数据。在企业中,会把业务数据存储在关系型数据库中,一般以MySQL居多。另外,我们在后续的课程中需要学习Hive、Spa…

阿里云ICP备案服务码在哪里申请查看?教程来了

阿里云备案服务码是什么?ICP备案服务码怎么获取?阿里云备案服务码分为免费和付费两种,申请备案服务码是有限制条件的,需要你的阿里云账号下有可用于申请备案服务码的云产品,如云服务器、建站产品、虚拟主机等&#xff…

【JOSE约瑟 JZS-7E14/11静态可调延时中间继电器 自动控制电路 接通、分断电路】

JZS-7E14/11静态可调延时中间继电器品牌:JOSEF约瑟名称:静态可调延时中间继电器型号:JZS-7E14/11额定电压:6220VDC;6380VAC触点容量:10A/250V10A/220VDC功率消耗:≤6W 一 用途 JZS-7E系列中间继电器用于各种保护和自动控制装置中,以增加保护和控制回路的触点容量. …

Apollo与SpringBoot整合原理深度剖析

Apollo与SpringBoot整合原理深度剖析 Spring环境上下文模块Value注解如何完成属性注入application.yml等配置文件加载时机监听环境上下文prepared事件Loader加载配置文件 Apollo与SpringBoot整合原理Value注解的热更新原理 Spring环境上下文模块 Spring Envionment设计如下: 需…