参考:AUTOSAR standard spec_v4.4 ——《AUTOSAR_EXP_NVDataHandling.pdf》

总结

应用方式推荐

  • 如果有并发访问,只能选case3;

  • 如果没有并发访问,建议优先选case2,相对于case3少了一个SWC,且不用回调函数,配置相对简单很多;

  • case1a不支持NvM_ReadAll​ 及NvM_WriteAll,一般难以满足需求,不建议选用;

  • case1b 相对于case2需要定义更多回调函数,用起来相对麻烦。

case1

NvM 都是以 ServiceSwComponent 的形式配置的。任何想要向 NVRAM 读/写数据的应用程序 SW-C 都需要使用C/S(Client/Service)接口来利用标准NvM 服务。

根据所使用的 NvM 块同步类型,上述用例可进一步分为两种情况:

case 1a

应用SWC访问没有永久RAM块的NVRAM块,且使用隐式同步:

​​

SWC直接与NV Block交互,比如读取时,直接读取物理存储中的NV Block值,并赋值给SWC中定义的变量。

在读写时需要传入变量地址,应用形式:

NvM_ReadBlock(BlockId, NvM_DstPtr);
NvM_WriteBlock(BlockId, NvM_DstPtr);

由于没有固定分配RAM,无法使用NvM_ReadAll​​ 及​NvM_WriteAll​​

注意:图上ROM Block存储的是默认数据(在本篇中均不涉及,看图时可以忽略),NV Block对应FLS Block为实际物理存储。

配置

case 1b

应用SWC访问没有永久RAM块的NVRAM块,使用显式同步:

没有为RAM Block固定分配RAM,但是在NvM中定义了RAM Mirror,SWC通过RAM Mirror与 NV Block交互。

应用方式与case 1a一样,也是SWC中定义变量(RAM)用于读写MvM,在读写时也需要传入变量地址。

不同之处在于case1b是可以使用NvM_ReadAll​ 及NvM_WriteAll​的,在使用时会调用配置的回调函数,在回调函数中进行与SWC中定义变量的数据交换。比如NvM_ReadAll​时,依次次触发所有block的读取回调,在回调中实现将数据复制给SWC中变量。

配置

cfg中配置显式同步回调函数:

case 2

同case1,NvM 也是以 ServiceSwComponent 的形式配置的。

不同的是,应用SWC访问具有永久RAM块的NVRAM块,永久RAM块定义在RTE中。这种方式只能使用隐式同步。

代码应用方式有所不同,由于配置了永久RAM块,因此读写操作不再需要传入地址:

NvM_ReadPRAMBlock(BlockId);
NvM_WritePRAMBlock(BlockId);

此外,如果用户需要提供临时RAM 块,即使系统中已配置永久RAM 块 , 也可使用NvM_ReadBlock/NvM_WriteBlock​​ API 来提供临时 RAM 块地址。此类 API 优先于 NvM_ReadPRAMBlock/NvM_WritePRAMBlock​​。

可以使用NvM_ReadAll​​ 及NvM_WriteAll​​,其进行的是RAM Block与NV Block直接的数据交换。比如NvM_ReadAll​​,是将NV Block数据读到RAM Block中。

配置

写策略示例

uint8 CheckNvBlockReadySts(NvM_BlockIdType BlockId)
{
    uint8 res = E_NOT_OK;
    NvM_RequestResultType RequestResultPtr;
    if(NvM_GetErrorStatus(BlockId, &RequestResultPtr) == E_OK)
    {
        if(RequestResultPtr != NVM_REQ_PENDING)
        {
            res = E_OK;
        }
    }
    return res;
}

void CDD_E2_HzrdSts_CheckWrite(UInt8 data)
{
    if(Rte_CDD_E2_HzrdSts_MirrorBlock != data && !CheckNvBlockReadySts(NvMConf_NvMBlockDescriptor_CDD_E2HzrdSts))
    {
        Rte_CDD_E2_HzrdSts_MirrorBlock = data;
        NvM_WritePRAMBlock(NvMConf_NvMBlockDescriptor_CDD_E2HzrdSts);
        // 或 Rte_Call_NvMService_AC2_SRBS_HzrdSts_WriteBlock(NULL_PTR);
    }
}
  • 本例中Rte_CDD_E2_HzrdSts_MirrorBlock​为定义在在Rte中的固定ram block

  • BswM初始化阶段BswM_INIT_NvMReadAllRte_CDD_E2_HzrdSts_MirrorBlock​被赋值

  • 需要写时先复制给Rte_CDD_E2_HzrdSts_MirrorBlock​,然后调用NvM_WritePRAMBlock,实现将Rte_CDD_E2_HzrdSts_MirrorBlock​写入NvBlock

  • 这里通过NvM_GetErrorStatus​判断是否操作完成,以避免在Pending状态再次请求导致出错,也可用jobEnd回调实现

注意:

理论上按照AutoSAR文档,读写操作应调用NvM_ReadPRAMBlock/NvM_WritePRAMBlock,但Vector工具链实际生成的RTE接口为直接调用NvM_ReadBlock/NvM_WriteBlock​。各家工具链与AutoSAR标准都会存在一定偏差,可以理解。

据官方解释,这里调用RTE接口时传入参数为空即可:

Rte_Call_NvMService_AC2_SRBS_HzrdSts_WriteBlock(NULL_PTR);

关于ServiceSwComponent

根据AutoSAR文档介绍,SWC可通过ServiceSwComponent及NvBlockSwComponent 两种方式与NvM交互。对于上述介绍的case1/2 ,均是采用ServiceSwComponent。

如下case2框图,框图中体现了一个ServiceSwComponentType类型的模块,但在Davinci实际应用中,NvMSWC并不是一个需要额外定义的SWC,而是配置了NvM后,Developer中会对应自动生成的一个SWC,并且改SWC不需要手动配置,是可以忽略的存在,应用时在SWC1/2 中配置NvM Service Need即可。

这里NvMSWC应该就是:

S/C接口的连接状态(这里CDD_E2就是框图中SWC1/2的角色,其与NvM Service连接):

case 3

即上一节提到的采用NvBlockSwComponent 的应用方式。

在这种情况下,RTE 中的NvBlockSwComponent 用于创建RAM 块 , 作为其NvBlockDescriptor 的一部分,可由单个或多个 SW-C 使用NV-Data 接口部分或全部写入/读取。这些 RAM 块可通过 NvM 中的镜像进行访问。

NvM 块描述符已配置为针对此用例的显式同步。每当 NvM 被触发从 NVRAM 中写入或读取数据时,它都会通过回调(Rte_GetMirror/Rte_SetMirror​​)获取/更新 RAM 块,回调在 RTE 中实现。

如果进行了配置,Rte 还可以使用 NvBlockSwComponent 在内部触发数据写入NvM,这样SWC就不必明确利用C/S(Client/Service)接口进行写入。

注意: 在使用 NvBlockSwComponentType 时,不建议使用隐式同步。

此外,与case2类似,如果用户需要提供临时RAM 块,即使系统中已配置镜像 , 也可使用NvM_ReadBlock/NvM_WriteBlock API 来提供临时 RAM 块地址,在这种情况下, NvM 会使用 RAM 块参数而不是镜像。此类 API 优先于 NvM_ReadPRAMBlock/NvM_WritePRAMBlock

总结与case2差异:

  • case3最大的优势在于其支持多个SWC对同一个NV_Block的并发访问。

  • NvBlockSwComponent 可以通过S/R(Send/Receive)向上与应用SWC连接。

下图显示了用于用户访问 NvM 接口的端口配置(SWC1 /SWC2 /SWC3),此处 NvM 被配置为 NvBlockSwComponent。

根据应用软件访问 RAM 块所使用的发送方-接收方通信类型和各自的写入策略,这种情况可进一步分类:

  • case 3a:使用Rte 显式S/R 通信(即 Rte_Write/Rte_Read/Rte_DRead

  • case 3b:使用Rte 隐式S/R 通信(即 Rte_IWrite/Rte_IWriteRef/Rte_IRead

配置

这里只简单介绍思路。

创建一个NvBlockSwComponentType类型的SWC。

SWC中,向上实现与应用SWC的S/P接口及连接,向下实现与NvM C/S接口及连接。