文章包含了AUTOSAR基础软件(BSW)中存储栈(NvM、MemIf、Fee)相关的内容详解(未涉及EA等模块)。本文从AUTOSAR规范,ISOLAR-AB配置以及模块相关代码分析四个维度来帮读者清晰的认识和了解存储栈这一基础软件栈。文中涉及的ISOLAR-AB配置以及模块相关代码都是依托于ETAS提供的工具链来配置与生成的,与AUTOSAR规范之间可能会有些许的出入,但总体的功能要点与处理流程都应该是一致的。
AUTOSAR的存储栈主要是用于管理需要保存在非易失性存储器(Flash/EEPROM)中的数据,并基于汽车的运行环境保证数据能够有效的更改并持续完整的保存数据。本文涉及的例程是基于英飞凌27x系列芯片,并无外挂EEPROM,所以存储栈涉及的模块包括NvM、MemIf、Fee(Rba_FeeFs1)。因为非易失性存储器不仅具有擦写周期限制(一般为10万次),并且写入时间也较长,不能做到像RAM一样根据地址来随机读写任意大小的数据,所以为了让应用程序能够更方便使用非易失性存储器,存储栈做了很多的抽象与管理工作。
文章在具体介绍每个模块规范之前,先介绍了AUTOSAR规范中对于需要存储在非易失性存储器的NV数据处理指南,这部分理解需要有AUTOSAR系统开发知识,如果您读起来觉得很混乱则可以先读博主《【ETAS CP AUTOSAR工具链】基本概念与开发流程》以及《【ETAS CP AUTOSAR工具链】RTE运行时环境详解》等前面发布的AUTOSAR相关文章。
目录
实例1:SW-C中应用程序访问没有永久RAM块的NVRAM块
实例2:SW-C中应用程序访问具有永久RAM块的NVRAM块
实例3:SW-C中应用程序访问使用NvBlockSwComponentType配置的NVRAM块
AUTOSAR规范解析
NV数据处理指南
本章介绍AUTOSAR规范中对非易失性存储器相关的基本概念,以及应用软件组件可用的各种存取机制。我们首先从一些基本概念入手进行介绍,然后提供了所有从应用程序(最终用户)访问非易失性存储器的实际用例,帮助您更好的理解存储栈的使用。
缩略语
- NV:Non-volatile为非易失。
- NvM:NVRAM Manager为非易失性存储器管理。
- NVRAM Block:NVRAM块是管理和存储NV数据所需的结构体。
- NV Block:NV块是一个基本存储对象。它表示“NVRAM Block”中驻留在NV存储器中的部分。
- RAM Block:RAM块是一个基本存储对象。它表示驻留在RAM中的“NVRAM Block”的部分。
- RAM Mirror:RAM镜像是NvM内部缓冲区,用于在NMBlockUseSyncMechanism设置为
True时缓存读取和写入NVRAM块的RAM块中的数据。 - ROM Block:ROM块是一个基本存储对象。它表示驻留在ROM中的“NVRAM Block”部分。
- ROM:Read-Only Memory 只读存储器。
- RTE:Runtime Environment 运行时环境。
- SW-C:Software Component 软件组件。
NvM及其特点
可更改性和持久性是与ECU内部数据相关联的重要属性。数据参数首先如果是可更改的,而且需要在上\下电循环中使用,那么数据就必须存储在非易失性存储器中。在AUTOSAR中,NV Data指代存储在非易失性存储器内的数据,应用程序应该只能通过NVRAM Manager(NvM)访问非易失性存储器。该模块提供数据管理和维护所需的所有服务(同步/异步)。
下图显示了应用程序和内存堆栈之间的交互以及所涉及的模块。
下面我们简要介绍一下NvM模块提供的不同概念和特性,有关更多细节,请参见《AUTOSAR_SWS_NVRAMManager.pdf》
“基本存储对象”是“NVRAM Block”的最小实体。多个“基本存储对象”可用于构建NVRAM块。“基本存储对象”可以驻留在不同的存储器位置(RAM/ROM/NV存储器)中。下面介绍这些基本的存储对象:
- RAM Block:它表示在“NVRAM Block”中驻留在RAM中的部分。它由用户数据和(可选的)CRC值和(可选的)NV块头组成。它用于保存实时数据。这是“NVRAM Block”的可选部分。
- ROM Block:“ROM块”是“NVRAM Block”的可选部分,它驻留在ROM中。ROM块的内容具有持久性,在程序执行过程中不能被修改,并且驻留在ROM/Flash中。它被用于在“NV Block”空白或损坏的情况下提供默认数据。
- NV Block:它表示“NVRAM Block”中驻留在NV存储器中的部分。“NV块”是“NVRAM Block”的强制性部分。NV块的内容具有持久性,可以在程序执行期间修改,并且驻留在Flash中。它由CRC值和(可选地)NV块头组成。它用于保存跨上\下电周期的数据参数。
- Administrative Block:“管理块”是“NVRAM Block”的强制性部分。管理块的内容具有非持久性,并且驻留在RAM中。它用于保存对应NVRAM块的属性/错误/状态信息以及特定于NVRAM管理类型为“数据集”的块索引。
NvM支持以下NVRAM块管理类型:
- Native NVRAM block:原生NVRAM块是最简单的块管理类型,它允许以最小的开销从NV内存中进行存储/检索。它包含一个NV Block,一个RAM Block,以及零到一个ROM Block以及一个Administrative Block。
- Redundant NVRAM block:相比原生NVRAM块,冗余NVRAM块提供了增强的容错性、可靠性和可用性。它增加了对数据破坏的抵抗力。冗余NVRAM块包含两个NV块,一个RAM块和一个管理块。如果与冗余NVRAM块关联的NV块被视为无效(例如在读取过程中),将尝试使用来自未损坏NV块的数据恢复NV块。它包含两个NV Block,一个RAM Block,以及零到一个ROM Block以及一个Administrative Block。
- Dataset NVRAM block:它可以表示大小相等数据块的数组。应用程序可以一次性访问该数据块中的一个。它包含一个到NvMNvBlockNum个NV Block,一个RAM Block,零个到NvMNvBlockNum个ROM Block以及一个Administrative Block。数据集(NV+ROM块)的总数必须小于255。用户通过使用 NvM_SetDatalndex()设置相应的索引来访问特定数据集元素。索引从0到NvMNvBlockNum-1的元素表示NV块,而索引从NvMNvblockNum到NVMNVBlockNum+NvMRomBlockNum-1中的元素表示 ROM 块。NVRAM 块用户必须在访问数据元素之前确保已经选择有效的数据集索引。
在使用NvM模块时,支持两种类型的RAM同步机制(隐式/显式)。
在隐式同步中,应用程序和NvM可以并发访问一个公共RAM块(由应用程序提供)。应用程序通过调用NvM提供的API可以读取/写入NVRAM到/从公共RAM块。
在这种情况下,RAM块从属于一个SW-C,并且不建议多个SW-C共享RAM块。每当SW-C使用RAM块访问NVRAM Block时,它必须确保RAM块的数据一致性,直到NvM完成正在进行的操作。 隐式同步单Block的写入过程如下:
- 应用程序首先需要将写入的数据填充到准备好的RAM块。
- 应用程序调用NVM_WriteBlock或NvM_WritePRAMBlock,将RAM指针传递给NvM,并将控制转移到NVM模块。
- 从现在开始,应用程序不得修改RAM块,直到通过轮询来查询到请求的成功或失败。在此期间,RAM块的内容可以被读取。
- 应用程序可以轮询来获取请求的状态,也可以通过回调函数异步通知。
- 在完成NvM模块操作之后,RAM块可进行修改以重复使用。
多Block的写入过程如下(NvM_WriteAll):
- EcuM或BswM发出NvM_WriteAll请求,该请求将控制转移到NvM模块。
- EcuM或BswM可以使用轮询来获取请求的状态,或者可以通过回调函数得到通知。
在显式同步中,NvM中定义了一个RAM镜像,用于与SW-C的RAM块交换数据。NvM回调API将SW-C提供的RAM数据写入RAM镜像,最后NvM将RAM镜像中的数据写入到NV块。应用程序通过NvM模块的回调程序来双向传输数据。
这种方式的优点是应用程序可以有效地控制其RAM块。NvM负责使用ReadRamBlockFromNvM/WriteRamBlockToNvM配置的两个回调函数将一致的数据复制到NvM模块的RAM镜像中,由NvM负责确保整个读取/写入过程中RAM镜像的一致性问题。缺点是针对每种类型的操作都需要额外的RAM,且镜像RAM的大小与使用此机制的最大NVRAM块的大小相同。
如果有一个模块(例如NvBlockSwComponentType,或者用户自己建立的一个NvM_SWC),它从NvM模块的角度来看是NVRAM块的所有者,来同步不同的SW-C,则可以允许不同SW-C间共享NVRAM块。
下面是使用显式同步单Block的写入过程:
- 应用程序首先需要将写入的数据填充到准备好的RAM块。
- 应用程序发出NvM_WriteBlock或NvM_WritePRAMBlock请求。
- 应用程序可以在此期间修改RAM块,直到NvM模块调用NvMWriteRamBlockToNvM。
- 如果 NvM 模块调用NvMWriteRamBlockToNvM,则应用程序必须为NvM模块请求的目的地拷贝与特定RAM一致的RAM块副本。应用程序可以使用返回值E_NOT_OK 来表示数据不一致。NvM 模块将接受否定返回值NvMRepeatMirrorOperations次,然后推迟请求并继续其下一个请求,直到拷贝成功。
- 拷贝成功之后,SW-C可以再次操作之前准备好的特定RAM块。
- SW-C可以使用轮询来获取请求的结果状态,也可以通过回调函数异步得到通知。
NvM模块内部使用CRC生成例程(8/16/32位)来生成并检查NVRAM块的CRC,这是可配置选项。NvM模块通过实现基于CRC的比较机制来提供跳过未更改数据的写入。可以通过设置配置参数NvMBlockUseCRCCompMechanism来启用基于CRC比较机制。
NvM模块在读取管理类型为“NATIVE”和REDUNDANT”的NVRAM块时通过加载默认值(如果通过参数NvMRomBlockDataAddress 或参数NvMInitBlockCallback配置)提供隐式错误恢复。通过调用 NvM_RestoreBlockDefaults,所有块管理类型都可以明确的检索ROM数据,对于DATASET管理类型必须在调用此API之前设置相关索引(指向ROM 块)。NvM模块写入NVRAM块时提供的错误恢复机制是通过执行写入重试(不管NVRAM块管理类型如何)。
在写验证的情况下,当RAM块被写入NV存储器时,NV块会立即被读回并与RAM块中的原始内容进行比较。如果RAM块中的原始内容与读回内容不相同,则执行写重试,如果生产错误报告使能,则向DEM报告生产代码错误NVM_E_VERIFY_FAILED。如果回读操作失败,则不执行读取重试。
对于某些NVRAM块,可能需要在NvM_ReadAll期间保留相应RAM块的数据内容不被重写,以防存储在相应NV块中的数据比存储在RAM块中的数据更旧(例如,在RAM中的数据尚未写入NV存储器时的热重置)。在这种情况下,RAM块必须保存在重置安全的RAM区域,并且配置参数CalcRamBlockCrc必须设置为TRUE(这意味着相应的NV块也具有配置的CRC),并且参数NvMSetRamBlockStatusApi必须设置为TRUE。在每次改变RAM块数据内容后,必须为相应的NVRAM块调用NvMSetRamBlockStatus,入参BlockChanged设置为TRUE。NVRAM管理器随后将重新计算此RAM块的CRC并将结果存储在分配在重置安全RAM区域的内部变量中。当然,这种NVRAM块必须配置有效的永久RAM块(NvMRamBlockDataAddress)或使用显式同步回调函数(NvMReadRamBlockFromNvM)。
如果配置参数NvMSetRamBlockStatusApi被设置为FALSE的值,则NVRAM管理器在NvM_WriteAll过程中将RAM块的数据内容复制到所有配置为WriteAll(配置参数NvMSelectBlockForWriteAll被设置为TRUE的值)且具有永久RAM块(NvMRamBlockDataAddress)或显式同步回调函数(NvMReadRamBlockFromNvM)的相应NV块。为了最大程度地减少NV存储器的写入次数,最好只将那些RAM块与NV块内容不一致的RAM块复制到相应的NV块。为了在NvM_WriteAll过程中启用此功能,必须将配置参数NvMSetRamBlockStatusApi设置为TRUE。在这种情况下,NVRAM块用户在每次对RAM块数据进行更改后通过调用对应NVRAM块的NvM_SetRamBlockStatus来通知NVRAM Manager参数已经被修改。这样,在NVM_WriteAll执行期间只有BlockChanged为TRUE的Block才会被处理。
NvM模块在启动期间(即在处理请求NvM_ReadAIl时),可能会因为程序升级,导致新程序对存储的参数布局与旧程序存在差异,那么此时的参数获取行为将受到两个配置参数NvMDynamicConfiguration和NvMResistantToChangedSw的影响。对于配置参数NvMCalcRamBlockCrc设置为TRUE的NVRAM块,NvM在执行读取等操作时首先会检查对应RAM块数据的有效性。如果检测到RAM块内容无效,或者参数NvMCalcRamBlockCrc设置为FALSE,则会进一步检查NV Block的有效性。检测到有效的NV块将复制到其对应的RAM块。如果检测到无效NV Block,则将加载默认数据(如果通过参数NvMRomBlockDataAddress或参数NvMInitBlockCallback进行了配置)。在ECU项目中,当程序不需要对存储布局不一致做出反应时,需将参数NvMDynamicConfiguration设置为FALSE。如果NVRAM块的布局已更改,而已存储在NV Memory中的NV块仍与旧布局相对应则在NvM_ReadAll过程中可能出现严重问题。这方面的一个例子是,当添加一个新的NVRAM块时,许多其他块的标识符可能隐式地被更改,这可能导致从NV存储器读取错误的数据。对于这种情况,可以配置NvM模块,使其不会尝试使用NV存储器的数据初始化RAM块。这必须通过将配置参数NvMDynamicConfiguration的值设置为TRUE来完成,还需通过集成器修改配置参数NvmCompiledConfigurlD向NvM模块指示NVRAM配置已经发生变化。NvM模块使用单独的NVRAM块将该值存储在NV内存中。每次执行启动过程(NvM ReadAll)时,NvM模块将NV存储器中存储的值与配置参数 NvmCompiledConfigurlD的值进行比较。在这种情况下,根据相应配置参数NvMResistantToChangedSw的值,NvM模块在处理NvM_ReadAll期间有两种不同的方法初始化NVRAM块。
- 如果需要忽略相应NV块的数据,而是默认数据(如果通过参数NvMRomBlockDataAddress或 NvMlnitBlockCallback)应被加载,参数 NvMResistantToChangedSw的值应该设置为FALSE。
- 即使在配置更改的情况下,仍然需要用来自NV块的数据初始化RAM块,配置参数NvMResistantToChangedSw应设置为TRUE。行为将与没有发生配置更改时相同。
对于将 NvMResistantToChangedSw设置为TRUE的块,集成器必须确保在ECU 的剩余生命周期内不得更改以下配置参数,否则将无法从NV内存中成功检索数据:
- NvMResistantToChangedSw(必须不能从TRUE改成FALSE)
- ShortName
- NvMBlockUseCrc
- NvmBlockCrcType(如果NvMBlockUseCrc设置为真)
- NvMStaticBlockIDCheck
- NvmNvramDeviceId
- NvmBlockManagementType
- NvmNvBlockLength
- NvmNvBlockBaseNumber
NvM模块在处理NvM_WriteAll期间,NV存储器中的值将被对应RAM中的值所覆盖。根据所用模块NvM、Fee和Ea的实施情况,可能会有其他限制。请参阅相应的用户手册。
通过RTE访问NvM
涉及的Interfaces有以下两种:
- Client-server interface:客户端/服务器interface提供了一些可以在NvMService上由客户端调用的操作。如果是由NvM为SW-C提供的服务,则NvM充当服务器,SW-C充当客户端。此外,NvM可以使用此类接口向应用程序提供通知,在这种情况下,客户端和服务器的角色被交换。
- NvDataInterface:非易失性数据interface定义了要在非易失性的块组件和软件组件之间交换的多个VariableDataPrototype。这些VariableDataPrototype可以映射为在非易失性块组件中实现的完整RAM块或RAM块的元素。
若通过服务组件访问NV Data,则NvM配置为ServiceSwComponent。在这里,想要读/写数据到NVRAM的SW-C需要使用客户端/服务器接口提供的标准的NvM服务。读者可以在后边的实例介绍中涉及的实例1和实例2看到具体的实现。使用这种方法的好处有以下几种:
- 使用SW-C模板实现基本的通用配置以容纳NvM服务和回调。
- 每个区块可以配置独立的端口操作集。
- SW-C中的应用程序是从NvM分配的NVRAM块标识符中抽象出来的。
如果SW-C中的应用程序正在维护RAM块,它可以使用 PerlnstanceParameter或ConstantMemory将其配置在SW-C本地定义ParameterDataPrototypes,SW-C可以使用它来恢复 RAM 块,NvM也可以使用它来恢复NV块。
在NvM充当客户端和NvBlock的用户充当服务器的场景中,RTE使用客户端服务器接口实现从NvM到应用程序的通知。如果通过ServiceSwComponent使用NvM,则NvM使用映射到 NvMServiceSwComponent的R端口的通用客户端/服务器API,它通过RTE连接到NvBlock(SW-C)的用户P端囗对应的Rte_Call()。
若通过NvBlockSwComponent访问NV Data,NvM需在RTE中被配置为NvBlockSwComponent,它可以创建自己的 RAM 块(镜像),这些块(镜像)可以由使用 NV数据接口的单个或多个SW-C部分或全部写入/读取。同时,客户端/服务器接口用于NvM服务和通知。读者可以在后边的实例介绍中涉及的实例3看到具体的实现。使用这种方法的好处有以下几种:
- 每个块被标识,并具有由RTE分配的专用RAM块。
- 应用程序SW-C实现与RAM块的名称和类型无关。
- 通过RTE(PortInterfaceMapping,NvDataMapping)提供的局部数据映射机制,RAM块可以在多个SW-C之间共享。
- 使用较少的内存来实现RAM块。
- SW-C中的应用程序总是通过端口接口访问RAM块,从而形成更模块化的方法。
- 用户可以使用dirtyFlag机制在NvBlockSwComponent中启用写入策略,而不是在应用程序软件中实现写入策略。
NvBlockSwComponent中的NvBlockDescriptor允许使用ParameterDataPrototype配置可选ROM块。此ROM块常量被用作initValue,可以在RTE或分区初始化后将RAM块还原到该initValue。
在NvM充当客户端和NvBlock的用户充当服务器的场景中,RTE使用客户端-服务器接口实现从NvM到应用程序的通知。如果通过NvBlockSwComponent使用NvM,则NvM使用RTE为每个NvBlockDescriptor分配客户端Interface端口(R-Port),并提供标准回调API,即具有 NvMNotifyJobFinished或NvMNotifyinitBlock回调通知的SW-C。例如NvMNotifyInitBlock()和NvMNotifyJobFinished()。
AUTOSAR 中有不同的策略可将RAM块恢复到以前的值,即上次关机前保持的值。可以使用NvM_ReadBlock/NvM_ReadPRAMBlock从RteInit()期间使用InitEvent调用的Initialization runnables中逐个显式地读取单个块。更优化的方法是使用单个NvM请求,ReadAIl来读取所有需要数据持久性的此类块。所有这些NvM块都配置为适用于NvM_ReadAll。在NvM_ReadAll期间要读取的任何块都必须具有显式同步或永久RAM块。下图显示了使用NvM_ReadAll恢复RAM块的过程。
实例1:SW-C中应用程序访问没有永久RAM块的NVRAM块
在用例所涵盖的所有场景中,NvM都是以ServiceSwComponent的形式配置的。任何想要读/写数据到NVRAM的SW-C中的应用程序需要使用客户端/服务器接口来访问标准的NvM服务。
SW-C中的应用程序可以使用每个端口对应不同Block的Interface来唯一地映射到NvMBlock。
根据使用的NvM块同步类型,上述用例进一步分为两个场景:
- 应用程序提供数据RAM。
- NvM通过回调函数(NvM显式同步)取得数据RAM值。
我们首先介绍第一种,隐式同步是针对此用例的特定NvMBlockDescriptor配置的(NvMBlocUseSyncMechanism参数设置为false)。这种机制也被称为“NvM使用临时RAM块”。在该方案中,应用程序提供RAM数据区域的指针作为参数,作为NvM_ReadBlock/NvM_WriteBlockAPI的一部分。因此,用户(SW-C)有责任确保RAM数据的数据一致性(例如,在NvM使用RAM数据时,其余的组件不应访问RAM数据)。下图提供了Application和NvM中内存分配的概述。
显示了用于用户访问NvM接口的端口配置(SWC1/SWC2),这里NvM配置为ServiceSwComponentType。
需要配置以下端口:
- 建立基于NvMService interface的端口,NvMService接口用于向NvM发送命令。支持的一些基本操作有:
- EraseBlock
- GetDataIndex
- GetErrorStatus
- InvalidateNvBlock
- ReadBlock
- RestoreBlockDefaults
- SetDataIndex
- SetRamBlockStatus
- WriteBlock
- 建立基于NvMAdmin interface的端口,NvMAdmin接口用于对NvM进行一些管理操作。支持以下操作:
- SetBlockProtection
- 建立基于NvM_NotifyInitBlock的端口,NvM_NotifylnitBlock接口由NvM使用来请求用户提供默认值,需要用户支持的操作为:
- InitBlock
- 建立基于NvM_NotifyJobFinished的端口,NvM NotifyJobFinished接口用于通知作业结束,需要用户支持的操作为:
- JobFinished。
下图显示了应用程序如何在此场景中访问NvM。
在此用例中,RAM块不存在,因此用户(SW-C)必须同步,以保证NVRAM操作期间不发生对RAM数据的不适当访问。此用例适用于映射到NvMBlock的数据未在不同SW-C之间共享的场景。
如果不同的应用程序在需要同时访问RAM数据区域,那么必须确保数据在NvM使用时不会产生变化,应用程序在调用NvM_ReadBlock/NvM_WriteBlock后不应提供给任何应用程序访问RAM数据,直到它通过JobFinished回调被通知工作成功为止。
我们下边介绍第二种,NvM通过回调函数(NvM显式同步)取得数据RAM值。NvMBlock描述符需要配置为使用显式同步(NvMBlockUseSyncMechanism参数设置为true)。在此方案中,数据由应用程序SW-C在本地提供,调用NvM_WriteBlock后数据依然可以修改,直到配置参数NvMWriteRamBlockToNvCallback配置的回调函数发生时。作为此回调的一部分功能,数据将从应用程序数据区复制到NvM中的RAM镜像。同样,在读取操作期间,应用程序数据区域通过使用 NvMReadRamBlockFromNvCallback参数配置的回调函数得以从NvM模块的镜像中更新。下图根据这个用例提供了Application和NvM中内存分配的概述。
下图显示了用于按用户访问NvM接口(SWC1/SWC2)的端口配置,这里NvM配置为
ServiceSwComponentType。
与前例相比,需要增加的端口定义为:
- 建立基于NvM_Mirror interface的端口,NvM_Mirror接口用于将数据从NvM Mirror更新到应用RAM数据,或从应用RAM数据更新到NvM镜像。需要用户实现以下操作。
- ReadRamBlockFromNvM
- WriteRamBlockToNvM
下图显示了应用程序如何在此场景中访问NvM:
在本用例中,NvM用户(SW-C)可以更有效地控制其数据,因为他们负责将一致的数据复制到RAM镜像和从RAM镜像中获取。可以在写入RAM镜像之前修改应用程序数据。缺点是在NvM模块中需要额外的RAM,该RAM的大小需要与NVRAM块相同,并且需要额外的副本用于读/写等操作。
实例2:SW-C中应用程序访问具有永久RAM块的NVRAM块
在这个场景中,RAM块以RTE中的每个实例内存的形式进行配置。在NvMBlockDescriptor配置中使用NvMRamBlockDataAddress参数给出了对创建的每个实例内存的引用。此例中NvMBlock描述符被配置为隐式同步(NvMBlockUseSyncMechanism参数设置为false)。对于在NvM中配置的永久RAM块,NvM提供专用API来请求与永久RAM块有关的服务,即NvM_ReadPRAMBlock/NvM_WritePRAMBlock(ETAS提供的NvM代码不包含这两个API,而是通过NvM_ReadBlock/NvM_WriteBlock中NvM_SrcPtr为空来表示使用永久内存)。此外,如果用户需要提供临时RAM块,即使系统中配置了永久RAM块,那么可以使用NvM_ReadBlock/NvM_WriteBlock两个API来提供临时RAM区块地址,它会优先于NvM_ReadPRAMBlock/NvM_WritePRAMBlock。
(ArTyped)PerinstanceMemory在RTE中被分配为RAM块,应用程序SW-C可以使用Rte_Pim的API访问该内存。在这种情况下,两个SW-C将RAM块用于它们的目的是无效的。总的来说,有两种不同类型的实例内存,它们在类型化机制上有所不同。C型实例内存由“C”类型定义的描述进行类型化,而AR型实例内存(AUTOSAR型实例内存)则由AutosarDataType进行类型化。然而,两种类型的实例内存都是通过Rte_Pimde的API访问的。下图提供了这个用例下的Application和NvM中内存分配的概述。
下图显示了用于用户访问NvM接口(SWC1/SWC2)的端口配置,这里NvM配置为ServiceSwComponentType。
下图显示了应用程序如何在此场景中访问NvM:
RTE不能确保每个实例内存访问的数据一致性。应用程序负责访问数据的一致性。为确保数据一致性,应用程序在调用NvM_ReadBlock/NvM_WriteBlock后不应访问永久RAM中的数据,直到通过JobFinished回调得到作业成功的通知后方可更改数据。PerinstanceMemory在RTE中被分配为RAM块,并且只能由该SW-C访问。因此,相同的数据不能在两个或多个SW-C之间共享。在这个用例中,“访问NVRAM块”不应该在多核环境中使用。
实例3:SW-C中应用程序访问使用NvBlockSwComponentType配置的NVRAM块
在这个场景中,RTE中的NvBlockSwComponent被用来创建RAM块作为其NvBlockDescriptor的一部分,它可以被单个或多个SW-C使用NV Data接口部分或全部写入/读取。这些这些RAM块最后会被NvM使用RAM镜像访问。用户可选择将ROM块创建为NvBlockDescriptor的一部分,同时,客户端/服务器接口用于NvM服务和通知。
NvMBlock描述符需配置为显式同步(NvMBlockUseSyncMechanism参数设置为true)。此外,如果配置为可选,Rte可以触发使用NvBlockSwComponent向NvM内部写入数据,这样应用程序就不必显式地使用客户端服务器接口进行写入(如果dirtyFlag=TRUE,则应用程序不需要使用客户端/服务器接口请求 NvM_WriteBlock/NvM_SetRamBlockStatus。如果 dirtyFlag=FALSE,则通过客户端服务器接口请求所有服务)。每当NvM被触发从NVRAM写入或读取数据时,它通过在RTE中实现的回调(Rte_GetMirror/Rte_SetMirror)来获取/更新RAM块。此外,如果用户需要提供临时RAM块,即使在系统中配置了显式同步,则使用NvM_ReadBlock/NvM_WriteBlock提供临时RAM地址即可。在这种情况下,NvM使用RAM块参数而不是镜像。但我们不推荐这样做。
下图根据这个用例提供了Application和NvM中内存分配的概述。
下图显示了用于按用户访问NvM接口的端口配置(SWC1、SWC2、SWC3),这里NM配置为
NvBlockSwComponent。
这个用例比其他用例具有很明显的优势,因为一个RAM块可以在多个SW-C或BSW之间完全或部分共享,从而减少资源开销。数据映射还允许访问NV数据,而不需要额外的缓冲区。用户还可以使用不同的写入策略来定义向NV存储器写入NV数据的频率,RTE负责处理此写入操作,在访问NV数据时,RTE来确保数据的一致性。
根据应用程序软件用于访问RAM块的发送方/接收方通信类型和相应的写入策略,对该场景进行了进一步分类。
首先是使用显式的S/R通信,在这种情况下,Rte显式APl诸如Rte_Write/Rte_Read/Rte_DRead用于更新或读取RAM块或RAM块的元素。Rte显式APl通常在Rte请求返回之前执行写入或读取操作。关于RTE和NvM之间的写策略,有四种可能的情况,首先是DirtyFlag为disable,RTE不会隐式地触发NvM进行写入操作。用户SW-C必须使用客户端/服务器端口接口发起请求。RTE来保证数据的一致性。
当DirtyFlag使能的时候,那么就会RTE就会根据存储的时机分为三种不同的写入策略,首先可以采取周期的存储。对于dirtyFlagSupport设置为true且NvBlockNeeds.storeCyclic设置为true的RAM块,RTE用一个定时事件周期性地触发NvM将RAM块写入NVRAM。定时事件的周期性配置为NvBlockDescriptor的一部分。下图显示了应用程序如何在此场景中访问NvM。
NvBlockNeeds的配置容器中,storeCyclic配置为True,writingFrequency配置循环周期,storeAtShutdown与storeImmediate为FALSE。
在Shutdown时存储,需要将dirtyFlagSupport设置为true且NvBlockNeeds.storeAtShutdown设置为true,则RTE调用NvM模块的NvMSetRamBlockStatus函数,并将BlockChanged参数设置为true。BswM负责在关机期间写入这些已更改的块。用户需要为该NvBlockDescriptor的NvBlockNeeds配置一个DataReceivedEvent。如果此DataReceivedEvent未映射到任何任务,则RTE在Rte_Write的语境中调用NvM _SetRamBlockStatus完成NVRAM Block状态配置。下图显示了应用程序如何在此场景中访问NvM。
NvBlockNeeds的配置容器中,storeAtShutdown配置为True,storeCyclic与storeImmediate为FALSE,writingFrequency无需配置。
最后还有立刻存储。dirtyFlagSupport设置为true且NvBlockNeeds.storeImmediate设置为true,则RTE直接调用NvM模块的NvM_WriteBlock函数,使用RteNvRamAllocation映射Blockld。
NvM_WriteBlock可以在两种情况下调用:
- 使用任务激活,将此NvBlockDescriptor的NvBlockNeeds配置DataReceivedEvent。这个DataReceivedEvent映射到一个任务,然后RTE从Rte_Write上下文中激活该任务。映射到DataReceivedEvent的可运行对象由RTE实现,以调用NvM_WriteBlockAPI。
- 在用户请求上下文中执行,为这个NvBlockDescriptor的NvBlockNeeds配置了DataReceivedEvent,但是此DataReceivedEvent未映射到任何任务,则RTE从Rte_Write上下文中调用NvM_WriteBlock。
下图显示了应用程序如何在此场景中访问NvM。
NvBlockNeeds的配置容器中,storeImmediate配置为True,storeCyclic与storeAtShutdown为FALSE,writingFrequency无需配置。
前边讲完了使用显式的S/R通信的例子,下面我们讲使用RTE隐式S/R通信。
在这种情况下,Rte隐式APl,即Rte_IDread/Rte_IWriteRef/Rte_IRead用于更新或读取RAM块或RAM块的元素。Rte隐含API通常会缓冲要写入的数据,直到调用Rte隐含写入请求的运行程序才最终写入。即在运行程序终止后,由RTE维护的全局RAM块将以最后的写入值更新。在隐式读取请求的情况下,在激活对数据具有读取访问权限的可运行实体之前,RTE从RAM块中获取数据。
跟刚才使用显式的S/R通信的例子一样,它也有四种可能的用例。首先是DirtyFlag为disable,RTE不会隐式地触发NvM进行写入操作,用户SW-C必须使用客户端/服务器端口接口发起请求。下图显示了应用程序如何在此场景中访问NvM。
针对周期存储时机,对于需要将dirtyFlagsupport设置为true且NvBlockNeeds.storeCyclic设置为true的RAM块,由RTE处理的计时事件周期性地触发NvM将RAM块写入NVRAM。定时事件的周期性配置为NvBlockDescriptor的一部分。下图显示了应用程序如何在此场景中访问NvM。
NvBlockNeeds的配置容器中,storeCyclic配置为True,writingFrequency配置循环周期,storeAtShutdown与storeImmediate为FALSE。
针对在Shutdown时机存储实例,对于dirtyFlagSupport设置为true且NvBlockNeeds.storeAtShutdown设置为true的RAM块,则RTE调用NvM模块的NvM_SetRamBlockStatus函数,并将BlockChanged参数设置为true。需为此NvBlockDescriptor的NvBlock配置DataReceivedEvent。如果此 DataReceivedEvent未映射到任何任务,则RTE将在映射到具有写访问权限的可运行任务的上下文中调用NvM_SetRamBlockStatus。下图显示了应用程序如何在这个场景中访问NvM。
NvBlockNeeds的配置容器中,storeAtShutdown配置为True,storeCyclic与storeImmediate为FALSE,writingFrequency无需配置。
当将dirtyFlagSupport设置为true目NvBlockNeeds.storeImmediate设置为true的RAM块更新时,RTE调用NvM模块的NvM_WriteBlock函数,使用RteNvRamAllocation映射Blockld。与使用显式的S/R通信下的使能DirtyFlag中的立刻存储实例一样,也有有两个方案可以实现这一点,都是Autosar中通过RTE调用的一些通用方法,就不赘述了。
NvBlockNeeds的配置容器中,storeImmediate配置为True,storeCyclic与storeAtShutdown为FALSE,writingFrequency无需配置。
NvM
AUTOSAR基本软件模块NVRAMManager(NvM)规范描述了其功能、API和配置。NvM模块应提供服务,以确保根据汽车环境中的个人要求进行NV(非易失性)数据的数据存储和维护。NvM模块应该能够管理一个EEPROM和/或FLASH EEPROM仿真设备的NV数据。NvM模块应为NV数据的管理和维护(init/read/write/control)提供所需的同步/异步服务。因为前面的NV Data Handling Guideline章节已经概括的介绍了NvM及其特点,我们这里就不对NvM规范逐条介绍了,后边的内容仅挑选一些在配置过程中常用的进行介绍。
不同块之间的关系可以在下面的图片中可视化:
基本架构指南
下图显示了模块NvM与其他模块的通信交互。
MemIf、Fee为NvM模块提供了一个由16位块号和16位块地址偏移量组成的虚拟线性32位地址空间。NvM模块应进一步将16位Fee/Ea块号细分为以下部分:
- 位宽为(NVM_DATASET_SELECTION_BITS)的数据索引。
- 位宽度为(16-NVM_DATASET_SELECTION_BITS)的NV块基号。
配置参数NvMDatasetSelectionBits配置为4。这导致12位可用作配置参数NvMNvBlockBaseNumber的范围。NvMDatasetSelectionBits用于表示属于单个Block中的不同data index下的数据。
NvM模块应该支持通过NvMJobPrioritization配置参数使能基于优先级的作业处理。对于基于优先级的作业处理顺序,NvM模块将使用两个队列,一个用于立即写作业,另一个用于所有其他作业(包括立即读/擦除作业)。NvM模块在处理完立即写作业之后应随后恢复/重新启动被抢占的作业。这种行为既适用于单块请求,也适用于多块请求。如果通过配置禁用了基于优先级的作业处理,NvM模块将不支持立即写作业。在这种情况下,NvM模块按先来先处理原则处理所有作业。可以通过调用NvM_CancelWriteAll来中止NvM_WriteAll 请求。在这种情况下,当前块将被完全处理,但不会再写入其他块。
为了能够使NvM模块适应有限的硬件资源,应定义三种不同的API配置,具体不同等级包含的API列表详见《AUTOSAR_SWS_NVRAMManager.pdf》:
- API configuration class 3:所有NvM涉及的API调用都可用。支持最大限度的功能。
- API configuration class 2:可使用API调用的中间集。
- API configuration class 1:对于硬件资源非常有限的系统,此API配置类型仅提供最低限度的
AP集合,这些API的使用在任何情况下都是必需的。
设计说明
下图描述了RAM块在面对不同API调用结果的状态转换。
初始化后,RAM块处于INVALID/UNCHANGED状态,直到通过NvM_ReadAll对其进行更新,这将导致转换到VALID/UNCHANGED的状态。在此状态下不允许WriteAll。如果调用了NvM_SetRamBlockStatus,更改RamBlockStatus,则进入VALID/CHANDGE。如果发生CRC错误(数据算出来的CRC与块内保存的CRC不一致),RAM块将再次更改为INVALID,这可以通过隐式或显式错误恢复机制来恢复。错误恢复后,由于RAM的内容不同于NVRAM的内容,块处于VALID/CHANDGE状态。
NVRAM管理器每次写入NV存储器时,都会在NV块中存储包括静态块ID在内的NV块头文件,与可选的CRC等信息。读取块时,将其静态块ID与请求的块ID进行比较。这允许检测导致错误块被读取的硬件故障。
RAM块可以通过从ROM中恢复RAM到默认值来进行错误恢复,如果用户在NvM_ReadAl/NvM_ReadBlock/NvM_ReadPRAMBlock请求过程中CRC错误(可选)或读取NV Block失败,并且用户配置了NvMRomBlockDataAddress或者NvMInitBlockCallback,Block会进行隐式恢复,用户也可使用NvM_RestoreBlockDefaults或者NvM_RestorePRAMBlockDefaults来显式恢复。
NvMWriteBlockOnce配置为真时,NvM只应对相应NV Block写入一次,NvM_WriteRAMBlock与NvM_WritePRAMBlock在成功写入之后应该立刻将administrative block中的write protection flag置位。
如果NVRAM管理器在从NV存储器读取操作期间检测到故障,CRC错误,然后在继续读取冗余NV块之前,应根据NVMMAXREADRETRIES配置进行一次或多次额外的读取尝试。如果使能NV_WRITE VERIFICATION,当RAM块被写入NV存储器时,NV块应立即读回,并与RAM块中的原始内容进行比较。为了避免NV存储器中不必要的写操作,如果特定RAM块的NV数据在运行时没有更新,NvM模块提供了基于CRC的比较机制,可以在处理写作业时应用。
NvM提供了NvM_SetBlockLockStatus给基础软件组件(主要是DEM),如果调用API时参数锁定为TRUE,NvM应保证与Blockld标识的NVRAM块关联的NV内容不会被任何请求修改。
BswM交互
下图显示了NvM和BswM在单块操作时的交互。
下图显示了NvM和BswM在多块操作时的交互。
下图显示了NvM和BswM在WriteAll取消时的交互。
下图显示了NvM和BswM在单块操作取消时的交互。
MemIf
AUTOSAR基本软件模块“Memory Abstraction Interface”(Memlf)规范介绍了其的功能、API和配置。该模块允许NvM访问多个内存抽象模块(FEE或EA模块)。
缩略语
- Fast Mode:在启动/关闭期间,底层驱动程序可以切换到快速模式,以便在这些阶段实现快速读/写。这种模式是否可行取决于驱动程序的实现和底层设备的能力,是否完成取决于NVRAM管理器的配置,因此取决于特定项目的需要。
- Slow Mode:在正常运行期间,底层驱动程序可以以慢速模式使用,以便减少底层设备/通信介质的运行时或阻塞时间的资源使用。这种模式是否可行取决于驱动程序的实现和底层设备的能力,是否完成取决于NVRAM管理器的配置,因此取决于特定项目的需要。
- Vendor specific library:供应商专用库是FEE/FLS和EA/EEP模块的ICC-2实现。它提供了与相应的ICC-3实现相同的上层接口(API)和功能。
开发类错误
下面的错误和异常可有MemIf模块报告,取决于程序配置(开发/生产)。
Type or error | Relevance | Related error code | Value [hex] |
API service called with wrong device index parameter | Development | MEMIF_E_PARAM_DEVICE | 0x01 |
API service called with NULL pointer argument | Development | MEMIF_E_PARAM_POINTER | 0x02 |
Fee
AUTOSAR规范描述了Flash EEPROM模拟模块的功能、API和配置。FlashEEPROM Emulation(FEE)应从设备特定的寻址方案和存储分割抽象出来,并为上层提供虚拟的寻址机制和存储分割以及“虚拟”的无限数量的擦除循环。
这里我们补充以下规范里没有的关于EEPROM和Flash读写操作的一些限制。
- EEPROM
- 写:常见的EEPROM芯片提供按字节或者页(一般为8字节)来写入,不需要提前执行擦除操作。
- 读:可以随机读取任意地址下任意长度的数据,没有页的限制。
- Flash
- 写:在写入之前需要执行擦除操作,擦除的对象有扇区(针对芯片W25Q64,4KB),块(针对芯片W25Q64,64KB)或者整片Flash。Flash也支持页(针对芯片W25Q64,256个字节)写的功能,一次写入一页大小数据。
- 读:Flash的也可以随机读取任意地址下任意长度的数据,没有页的限制。
缩略语
- EEPROM:电可擦可编程ROM
- EA:EEPROM Abstraction EEPROM抽象
- FEE:Flash EEPROM Emulation
- LSB:最低有效位
- MemIf:Memory Abstraction Interface
- MSB:最高有效位
- (Logical) block:FEE模块用户看到的最小的可写/可擦单元。由一个或多个虚拟页面组成。
- Virtual page:可由一个或多个物理页面组成,以便于逻辑块的处理和地址计算。
- Internal residue:如果配置的块大小不是虚拟页面大小的整数倍,则在最后一个虚拟页面的末尾处保留未使用的空间。
- Virtual address:由16位块号和逻辑块内部16位偏移组成。
- Physical address:以设备特定格式(取决于底层EEPROM驱动程序和设备)地址用于访问逻辑块的信息。
- Dataset:它是NVRAM管理器的概念,用户可寻址的相同大小的块数组。例如,可以为CAN驱动程序提供不同的配置设置(CANID、过滤器设置等)。
- Redundant copy:它是NVRAM管理器的概念,将相同的信息存储两次,以提高数据存储的可靠性。
寻址方案和存储分割
FEE模块为上层提供了32位虚拟线性地址空间和统一的存储分割方案。这个虚拟的32位地址应该包括16位块号(理论上允许65536个逻辑块),16位块偏移(理论上允许每个块的块大小64KByte)。16位的块号表示一个可配置的(虚拟)分页机制。此地址对齐的值可以从底层闪存驱动程序和设备的值中导出。这个虚拟分页应该通过参数FeeVirtualPageSize来配置。
下面描述了一个例子,通过相应设置FeeVirtualPageSize 参数,地址对齐/虚拟分页被配置为8个字节,逻辑块号1被配置为具有32字节的大小,这个逻辑块将使用正好4个虚拟页面。因此,下一个逻辑块将得到第5页。第二块的大小被配置为100字节,占用13个虚拟页,最后一个页的4个字节未使用。下一个可用的逻辑块的其实地址因此将是第17个虚拟页。
地址计算
根据FEE模块的实现和所使用的确切地址格式,FEE模块的功能应结合16位块号和16位地址偏移,以得出底层闪存驱动程序所需的物理闪存地址。
Dataset信息被配置为编码在四个LSB的16位块数(允许每个NVRAM块的最大数据集元素为16和总共4094NVRAM块)。实现者可以利用Dataset的index值和块大小来访问到Dataset中具体的块。
擦写次数限制
FEE模块应在配置参数FeeNumberOfWriteCycles中定义每个逻辑块的预期擦除/写入周期数。如果底层的闪存设备或设备驱动程序没有为每个物理存储单元提供至少配置的擦除/写周期,FEE模块应该提供机制来扩展写访问,这样物理设备就不会承受过大的压力。这也适用于FEE模块内部使用的所有管理数据。下面的例子说明了如何提高底层的擦写次数限制。
逻辑块1被配置为预期的500.000写入周期,底层闪存设备和设备驱动程序仅被指定为100.000擦除周期。在这种情况下,FEE模块必须提供(至少)五个独立的存储区域,并且在内部交替地在这些区域之间访问,以便每个物理存储位置只在指定的100.000个周期的最大范围内被擦除。
处理“立即数据”
针对必须立即写入包含即时数据的块,FEE模块必须确保可以写入此类块而不需要擦除相应的存储器区域(例如,通过使用预擦除内存)并且写请求不会因当前正在运行的模块内部管理操作而延迟。在立即写入数据之前,NVRAM管理器应取消正在进行的较低优先级的读擦除/写入或比较作业。FEE模块只需确保可以立即执行此写入请求。硬上正在运行的操作(例如写入一个页面或擦除一个扇区)一旦启动通常就不能中止。因此,即使对于即时数据,最长硬件操作的最大时间也必须被接受为延迟。
假设我们已为即时数据配置了三个各有10个字节的块。FEE模块保留一个存储器擦写最小单元(Bank)给这30个字节(如果需要则加上每个块/页的实现特定开销)使用。也就是说,这个存储单元不得用于存储其他数据块。现在,NVRAM管理器请求FEE模块写入一个100字节的数据块。在写入此块时,会出现需要写入一个(或多个)即时数据块的情况。因此,NVRAM管理器取消正在进行的写入请求,随后对包含即时数据的(第一个)块发出写入请求。正在进行的写请求的取消由FEE模块和底层闪存驱动程序同步执行(即立即数据写入请求)可以立即开始,而无需进一步延迟。但是,在立即数据的第一字节可以写入之前,FEE模块或底层闪存驱动器必须等待先前写入请求(例如,页面写入、扇区擦除、通过 SPI传输等)的硬件访问结束。
管理存储块的正确性信息
FEE模块应为每个块提供管理信息,无论该块从FEE模块的角度来看是否正确(即“未损坏”)。这些信息只涉及区块的内部处理,不涉及区块的内容。当开始块写操作时,FEE模块应将对应的块标记为“已损坏”。在块写入操作成功结束时,块应再次被标记为“未损坏”。注意:此内部管理信息不应与可通过使用Fee_InvalidateBlock服务操作的块的有效性信息混淆,即FEE应能够区分损坏的块与上层故意使其无效的块。
开发类错误
下面的错误和异常可有FEE模块报告,取决于程序配置(开发/生产)。
Type or error | Relevance | Related error code | Value [hex] |
API service called when module was not initialized | Development | FEE_E_UNINIT | 0x01 |
API service called with invalid block number | Development | FEE_E_INVALID_BLOCK_NO | 0x02 |
API service called with invalid block offset | Development | FEE_E_INVALID_BLOCK_OFS | 0x03 |
API service called with invalid data pointer | Development | FEE_E_PARAM_POINTER | 0x04 |
API service called with invalid length information | Development | FEE_E_INVALID_BLOCK_LEN | 0x05 |
Fee_Init failed | Development | FEE_E_INIT_FAILED | 0x09 |
运行时错误
Type or error | Relevance | Related error code | Value [hex] |
API service called while module is busy processing a user request | Runtime | FEE_E_BUSY | 0x06 |
Fee_Cancel called while no job was pending | Runtime | FEE_E_INVALID_CANCEL | 0x08 |
ISOLAR-AB配置
NvM
NvM模块的配置主要由NvMCommon与NvMBlockDescriptors两部分构成,NvMCommon包含一些NvM模块通用的配置,NvMBlockDescriptors则是针对不同的NvMBlock的独立配置。
NvMCommon
我们下面对NvMCommon容器中的主要配置项进行说明:
- NvMApiConfigClass:NvM模块API库等级,越高则提供的API越全,但是资源消耗越大。
- NvMBswMMultiBlockJobStatusInformation:如果使能,NvM模块使用BswM_NvM_CurrentlobMode来告知多块作业的当前状态。
- NvMCompiledConfigId:参数用于指示NV存储的布局信息,此ID用于在NvM启动期间(NvM_ReadAll)进行兼容性决策(如果启NvMDynamicConfiguration或者NvMRbInitAtLayoutChange使能),在启动期间如果比较当前的NV存储的ID与当前程序配置ID不一致,则会根据NV Block的配置进行选择性读取。
- NvMCrcNumOfBytes:对配置了CRC校验的块,最小的校验和计算字节数。
- NvMDevErrorDetect:启用Det监测和通知功能。
- NvMDrvModeSwitch:是否使能在ReadAll/WriteAll期间切换内存驱动到快速模式。
- NvMDynamicConfiguration:如果使能此配置,NvM在NvM_ReadAll期间会比较程序当前的NV存储的ID与当前程序配置ID,如果不一致的话,只有NvMResistantTochangedSw配置为Ture的存储块会被读取出来。
- NvMJobPrioritization:使能/失能作业优先级处理。
- NvMMainFunctionCycleTime:NvM主函数调用周期,单位s。
- NvMMultiBlockCallback:每个异步多块请求终止时调用的回调函数名称。如果明确希望指定不调用此类回调程序,请在此处输入NULL PTR.
- NvMPollingMode:定义了 NvM 如何与内存驱动器通信的方式。如果设置为true,则NvM MainFunction 将从这些驱动器中获取正在进行的操作的状态。如果设置为false则驱动程序将通过NvM提供的专用回调函数异步报告操作状态的任何更改。NvM不支持来自内存驱动程序的异步通知,因此此参数当前始终应设置为true。
- NvMRbSetWriteAllTriggerApi:是否使能NvMRbSetWriteAllTrigger这个API,这个API允许独立于RAM触发WriteAll。
- NvMSetRamBlockStatusApi:是否使能NvM_SetRamBlockStatus这个API,如果使能,则NvM_WriteAll只将标记为changed的块写入存储器,否则无论是否更改均写入存储器。我们这边例程当前的NvM版本此项必须配置为Ture。
- NvMSizeStandardJobQueue:定义标准工作队列的条目数量。
- NvMVersioninfoApi:是否启用NvM_VersioninfoApi。
下面是这边测试例程的配置截图。
NvMBlockDescriptors
这个容器包含了NVRAM Block的各种配置信息,主要的配置如下:
- NvMBlockCrcType:NVRAM Block的CRC算法输入数据宽度配置。
- NvMBlockJobPriority:定义NVRAM Block的作业优先级,值越小表示优先级越高。当前例程版本的NvM模块支持2种优先级,0表示立即优先级,1表示标准优先级。
- NvMBlockManagementType:定义NVRAM Block的管理类型为标准、冗余或数据集。
- NvMBlockUseAutoValidation:定义NVRAM Block是否在NvM_ValidateAll中被处理。
- NvMBlockUseCrc:是否启用NVRAM Block的CRC校验功能。
- NvMBlockUseSyncMechanism:是否使用显式同步机制,使用显式同步机制之后需要定义NvMReadRamBlockFromNvCallback与NvMWriteRamBlockToNvCallback。
- NvMBlockWriteProt:是否启用对NVRAM Block的写保护。
- NvMCalcRamBlockCrc:是否启用永久RAM块的CRC计算。
- NvMInitBlockCallback:如果没有用于初始化NVRAM Block的ROM数据,用户可通过此配置回调函数来初始化NVRAM Block数据。
- NvMMaxNumOfReadRetries:读取重试次数的最大值。
- NvMMaxNumOfWriteRetries:写入充实次数的最大值。
- NvMNvBlockLength:定义当前NVRAM Block所包含的数据长度,以字节为单位。
- NvMNvBlockNum:根据块管理类型定义其连接区域多个NV块的数量(标准类型为1,冗余类型为2,数据集类型为1-255,且NV块与ROM块之和应小于或等于255)。
- NvMNvramDeviceld:NVRAM块存储设备的标志符,0表示FEE,1表示EEPROM。
- NvMRamBlockDataAddress:配置永久块数据的变量名称。
- NvMRbFirstReadDataMigration:功能启用首次读取数据迁移时,当配置NV块长度与介质(EEPROM)上的块长度不匹配时,也会执行读取作业。在NV块长度小于介质上的块的情况下,剩余的数据被丢弃。在NV块长度大于介质上的块的情况下,剩余的数据被填充为零。如果该功能被禁用并且发生长度不匹配,则不执行读取作业。
- NvMRbGenRteAdminPort:配置是否为该块生成管理端口,如果需要通过RTE访问针对此块的管理API(诸如SetBlockProtection),则应设置为True。
- NvMRbGenRteServicePort:配置是否为该块生成服务端口,,如果需要通过RTE访问针对此块的服务API(诸如ReadBlock或者WriteBlock),则应设置为True。
- NvMRblnitBlockAtLayoutchange:如果检测出存储布局变化(NVRAM Block增加/重新配置),定义是否重新将初始化的数据写入存储介质。
- NvMRbNoFallback:此标签用于激活或停用相同块的旧版本的回退机制。它仅对位于Fee 上的块进行评估,对位于 Ea上的块忽略不计。
- NvMRbResistantToLayoutRemoval:配置定义NVRAM Block是否抵抗布局移除。如果使能,下层会将此块永久保存在持久媒体上,即使此块不再是布局的一部分即当配置更改且此块从布局中删除时)。
- NvMRbSelectBlockForFirstInitAll:配置定义NVRAM Block在NvM_Rb_FirstInitAll中是否被处理。
- NvMReadRamBlockFromNvCallback:用于将数据从NvM模块RAM镜像拷贝至用户特定RAM块的回调函数名称。
- NvMResistantTochangedSw:定义NVRAM Block是否应被视为对配置更改具有抗性。
- NvMRomBlockNum:根据块管理类型定义其连接区域多个ROM块的数量(标准类型和冗余类型为0-1,数据集类型为0-254,且NV块与ROM块之和应小于或等于255)。
- NvMSelectBlockForReadAll:配置定义NVRAM Block是否在NvM_ReadAll中被处理。
- NvMSelectBlockForWriteAll:配置定义NVRAM Block是否在NvM_WriteAll中被处理。
- NvMSingleBlockCallback:在每次访问实际存储介质终止时调用的块特定回调函数的名称。如果您明确指定不调用此类回调例程,请在此处输入NULLPTR。
- NvMStaticBlockIDCheck:使能或禁用静态块ID检查(例程当前版本的NvM模块不支持,该配置项永远为false)。
- NvMWriteBlockOnce:如果配置为真,则一旦该块成功地从存储介质读取或写入到存储介质,启用/禁用该块的自动写入保护。
- NvMWriteRamBlockToNvCallback:应用程序将数据从特定RAM块复制到NvM模块镜像RAM的回调函数名称。
- NvMWriteVerification:使能或禁用写验证(例程当前版本的NvM模块不支持,该配置项永远为false)。
- NvMWriteVerificationDataSize:定义写验证期间比较RAM块和回读块内容时在每个步骤要比较的字节数。例程版本暂不支持写验证。
NvMBlockDescriptors一般分为三类,如下图所示,根据不同的类别需要,需要配置的配置项也略有不同。
下面分别介绍一个各种类别需要的配置信息。
- 第一类:根据AUTOSAR规范【SWS_NVM 00244】等条目可知,Block ID为0保留为多块请求结果,Block ID 为1的是当前存储布局的ID,它可以被用作与NvmCompiledConfigurlD比较来判断存储布局是否改动。他们都为NvM模块自己使用。
- Block ID为0的块名必须名为NvM_MultiBlock,因为示例中没有使用MultiBlock,则配置最基本的即可。
- Block ID为1的块名必须为NvM_ConfigId,因为NvM需要将存储器中的ConfigId读取到实现定义好的变量中,所以需要额外配置NvMRamBlockDataAddress为提前定义好的变量名,并将NvMSelectBlockForReadAll与NvMSelectBlockForWriteAll设置为True。
- Block ID为0的块名必须名为NvM_MultiBlock,因为示例中没有使用MultiBlock,则配置最基本的即可。
- 第二类:第二类NVRAM Block为DEM使用的块,它需要配置的就变得很多了,比较重要的是需要把NvMBlockUseSyncMechanism配置为真,并根据DEM生成代码配置NvMReadRamBlockFromNvCallback与NvMWriteRamBlockToNvCallback的回调函数用于DEM中的RAM与NvM中的镜像RAM交换数据。
- 第三类:是用户应用程序需要使用的NVRAM Block,因为应用程序需要通过RTE访问NVRAM Block,所以需要将NvMRbGenRteServicePort设置为真,为了提高应用程序启动速度,将应用程序涉及的参数的NvMSelectBlockForReadAll与NvMSelectBlockForWriteAll也设置为True,并设置永久的RAM地址NvMRamBlockDataAddress。
MemIf
因为示例程序使用的是rba_FeeFs1,所以这部分的配置更显得很少,如下图所示,配置项都是不同模块通用,这里就不介绍了。
Fee
虽然我们使用的是rba_FeeFs1(这代表没有用到Fee的静态代码),但是它的配置却被rba_FeeFs1使用,我们这里分为FeeGeneral和FeeRbSectorTable两个容器介绍。
FeeGeneral
这个容器包含了Fee模块的一些通用配置,主要的配置项如下:
- FeePollingMode:配置用于启用和禁用模块预处理部分的轮询模式。true:轮询模式使能,回调函数禁用;false:轮询模式禁用,回调函数使能。
- FeeRbMachineType:在没有MCU模块的情况下要配置的控制器类型。
- FeeSetModeSupported:使能或禁用FEE模块的设定模式功能。
- FeeVirtualPageSize:这个是最重要的参数,需要是实际的EEPROM页大小的整数倍。
下图是示例工程的截图。
FeeRbSectorTable
这个容器包含了存储器物理分区的一些配置,我们首先介绍FeeRbSectorTable下的直接配置:
- FlsRbPagesize:存储器中扇区页物理大小。
- FeeRbFastCacheInitActive:使能或禁止快速缓存初始化。
- FeeRbHeaderRecheckActive:使能或禁止扇区头重新检查,仅对于未定义擦除模式的FLASH类型,需要配置为true。
- FlsRbErasedValue:定义DFLASH的擦除值(擦除之后的值)。
示例配置如下:
他其中还包含了存储器不同扇区的大小定义,示例用开发板芯片为英飞凌的TC27x, 它的DF0为384KBytes,又因为英飞凌使用双扇区算法来模拟EEPROM,所以我们必须使用所有逻辑扇区循环,以防止静态扇区擦除干扰的累计,则每个扇区应配置192KBytes。配置如下图所示。
SW-C
我们使用Test2作为例子,新建一个使用NvM提供的NvMService接口在组件Test2建立一个Rport,如下图所示。
然后我们在Functions中添加Runnables,并添加对NvMService接口提供的ReadBlock和WriteBlock的访问。
我们可以把Runnable添加为周期事件,如下图所示。
然后,我们建立一个PerinstanceMemory,为之前建立的名为NvM_UserData0的NVRAM Block提供永久RAM。
最后,我们可以看到Runnable生成的代码如下。
/* *****************************************************************************
* BEGIN: Banner
*-----------------------------------------------------------------------------
* ETAS GmbH
* D-70469 Stuttgart, Borsigstr. 14
*-----------------------------------------------------------------------------
* Administrative Information (automatically filled in by ISOLAR)
*-----------------------------------------------------------------------------
* Name:
* Description:
* Version: 1.0
*-----------------------------------------------------------------------------
* END: Banner
******************************************************************************
* Project : TestCsdn
* Component: /CDD_SWC/Test2
* Runnable : RunnableEntity1_1
*****************************************************************************
* Tool Version: ISOLAR-AB 4.0.2
* Author: geekl
* Date : 星期二 七月 23 10:07:05 2024
****************************************************************************/
#include "Rte_Test2.h"
/*PROTECTED REGION ID(FileHeaderUserDefinedIncludes :RunnableEntity2) ENABLED START */
/* Start of user defined includes - Do not remove this comment */
/* End of user defined includes - Do not remove this comment */
/*PROTECTED REGION END */
/*PROTECTED REGION ID(FileHeaderUserDefinedConstants :RunnableEntity2) ENABLED START */
/* Start of user defined constant definitions - Do not remove this comment */
/* End of user defined constant definitions - Do not remove this comment */
/*PROTECTED REGION END */
/*PROTECTED REGION ID(FileHeaderUserDefinedVariables :RunnableEntity2) ENABLED START */
/* Start of user variable defintions - Do not remove this comment */
/* End of user variable defintions - Do not remove this comment */
/*PROTECTED REGION END */
#define Test2_START_SEC_CODE
#include "Test2_MemMap.h"
FUNC (void, Test2_CODE) RunnableEntity2/* return value & FctID */
(
void
)
{
NvM_Rb_VoidPtr DstPtr1;
Std_ReturnType syncCall1;
NvM_Rb_ConstVoidPtr SrcPtr2;
Std_ReturnType syncCall2;
uint8 *val3;
/* Local Data Declaration */
/*PROTECTED REGION ID(UserVariables :RunnableEntity2) ENABLED START */
/* Start of user variable defintions - Do not remove this comment */
/* End of user variable defintions - Do not remove this comment */
/*PROTECTED REGION END */
Std_ReturnType retValue = RTE_E_OK;
/* -------------------------------------- Data Read ----------------------------------------- */
/* -------------------------------------- Server Call Point -------------------------------- */
syncCall1 = Rte_Call_RPortPrototype_1_ReadBlock(DstPtr1);
syncCall2 = Rte_Call_RPortPrototype_1_WriteBlock(SrcPtr2);
/* -------------------------------------- CDATA --------------------------------------------- */
/* -------------------------------------- Data Write ---------------------------------------- */
/* -------------------------------------- Trigger Interface --------------------------------- */
/* -------------------------------------- Mode Management ----------------------------------- */
/* -------------------------------------- Port Handling ------------------------------------- */
/* -------------------------------------- Exclusive Area ------------------------------------ */
/* -------------------------------------- Multiple Instantiation ---------------------------- */
*val3 = Rte_Pim_PIM_UserData0();
/*PROTECTED REGION ID(User Logic :RunnableEntity2) ENABLED START */
/* Start of user code - Do not remove this comment */
/* End of user code - Do not remove this comment */
/*PROTECTED REGION END */
}
#define Test2_STOP_SEC_CODE
#include "Test2_MemMap.h"
System
完成Test2与NvM组件间针对NvM_UserData0的连接。
RTE
添加运行实体到周期调度任务中。
最后成功生成RTE。
代码解析
下图显示了NVRAM管理器和Watchdog管理器如何在假定的硬件配置下与驱动程序交互:
- ECU硬件包括一个外部EEPROM和一个外部看门狗,该看门狗通过相同的SPI连接到微控制器。
- SPlHandlerDriver控制对SPI硬件的并发访问,并且必须给予看门狗访问高于EEPROM访问的优先级。
- 微控制器还包括一个与外部EEPROM并行使用的基于内部Flash封装为EEPROM操作API供上层使用的存储器。
NvM
动态配置代码
NvM的动态配置代码包含如下图所示文件。
我们下面说明以下两个文件的内容。
- NvM_Cfg.c:包含了NVRAM Block的描述结构体NvM_Prv_BlockDescriptors_acst,以及块长度NvM_Prv_BlockLengths_acu16和永久RAM地址NvM_Prv_RamBlockAdr_acpv。下面代码展示了NVRAM Block的描述结构体都包含的内容。
/** * Definition of the structure for a NVRAM block descriptor. * A NVRAM block descriptor contains all information about a single NVRAM block needed during the runtime. * The NVRAM block descriptors are condensed in the NVRAM block descriptor table. * TRACE[NVM061_Conf] */ typedef struct { /** * Block ID to be passed to the MemIf. * Do not confuse this ID with NVRAM block ID used within NvM. */ uint16 idBlockMemIf_u16; /** * Pointer to the block legth in bytes. * If runtime calculation of block lengths is enabled by the NvM configuration then block lengths will be located * in RAM so pointer points to a variable with block length calculated during runtime. * Otherwise if runtime calculation is disabled by the NvM configuration then block legths will be located * in ROM so pointer points to a constant with block length configured during compile time. * TRACE[NVM479_Conf] Parameter NvMBlockDescriptor:NvMNvBlockLength * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3028] Parameter NvMCommon:NvMRbRuntimeRamBlockConfiguration * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2996] Parameter NvMBlockDescriptor:NvMRbNvBlockLengthString */ #if (NVM_PRV_RUNTIME_RAM_BLOCK_CONFIG == STD_ON) uint16* nrBlockBytes_pu16; #else uint16 const* nrBlockBytes_pu16; #endif /** * Device index where the block is located (Fee / Ea). * TRACE[NVM035_Conf] Parameter NvMBlockDescriptor:NvMNvramDeviceId */ uint8 idxDevice_u8; /** * Number of non-volatile blocks in a contiguous area according to the given block management type. * TRACE[NVM480_Conf] Parameter NvMBlockDescriptor:NvMNvBlockNum */ uint8 nrNvBlocks_u8; /** * Number of multiple ROM blocks in a contiguous area according to the given block management type. * TRACE[NVM485_Conf] Parameter NvMBlockDescriptor:NvMRomBlockNum */ uint8 nrRomBlocks_u8; /** * Pointer to the permanent RAM block data. * If this pointer is NULL_PTR then no permanent RAM block data has been configured by the user. * If runtime calculation of RAM block data addresses is enabled by the NvM configuration * then RAM block data addresses will be located in RAM and pointer points to a void pointer * calculated during runtime. * Otherwise if runtime calculation is disabled by the NvM configuration then RAM block data addresses * will be located in ROM and pointer points to a constant void pointer configured during compile time. * TRACE[NVM126] * TRACE[NVM482_Conf] Parameter NvMBlockDescriptor:NvMRamBlockDataAddress * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3028] Parameter NvMCommon:NvMRbRuntimeRamBlockConfiguration * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3086] Parameter NvMBlockDescriptor:NvMRbRamBlockDataAddressString */ #if (NVM_PRV_RUNTIME_RAM_BLOCK_CONFIG == STD_ON) void** adrRamBlock_ppv; #else void* const* adrRamBlock_ppv; #endif /** * Pointer to the ROM block data. * If this pointer is NULL_PTR then no ROM block data has been configured by the user. * TRACE[NVM020] * TRACE[NVM484_Conf] Parameter NvMBlockDescriptor:NvMRomBlockDataAddress */ void const* adrRomBlock_pcv; /** * Pointer to the block specific callback function which shall be invoked on termination * of each asynchronous single-block request. * If this pointer is NULL_PTR then no callback has been configured by the user. * TRACE[NVM113] * TRACE[NVM467] * TRACE[NVM330] * TRACE[NVM506_Conf] Parameter NvMBlockDescriptor:NvMSingleBlockCallback */ Std_ReturnType (*SingleBlockCallback_pfct)(uint8 ServiceId, NvM_RequestResultType JobResult); /** * Pointer to the block specific callback function which shall be invoked on start * of each asynchronous single-block request. * If this pointer is NULL_PTR then no callback has been configured by the user. * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3056] * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3062] Parameter NvMBlockDescriptor:NvMRbSingleBlockStartCallback */ Std_ReturnType (*SingleBlockStartCallback_pfct)(uint8 ServiceId); /** * Pointer to the block specific callback function which shall be invoked if no ROM block data is available * for initialization of the block. * If this pointer is NULL_PTR then no callback has been configured by the user. * TRACE[NVM469] * TRACE[NVM352] * TRACE[NVM116_Conf] Parameter NvMBlockDescriptor:NvMInitBlockCallback */ Std_ReturnType (*InitBlockCallback_pfct)(void); /** * Pointer to the block specific callback function to let the application copy data from the NvM mirror * to application's RAM block. * If this pointer is NULL_PTR then no callback has been configured by the user. * TRACE[NVM540] * TRACE[NVM542] * TRACE[NVM521_Conf] Parameter NvMBlockDescriptor:NvMReadRamBlockFromNvCallback */ Std_ReturnType (*ReadRamBlockFromNvm_pfct)(void* NvMBuffer); /** * Pointer the block specific callback function to let the application copy data from the application's RAM block * to the NvM mirror. * If this pointer is NULL_PTR then no callback has been configured by the user. * TRACE[NVM539] * TRACE[NVM541] * TRACE[NVM520_Conf] Parameter NvMBlockDescriptor:NvMWriteRamBlockToNvCallback */ Std_ReturnType (*WriteRamBlockToNvm_pfct)(void* NvMBuffer); /** * Block management type. * TRACE[NVM062_Conf] Parameter NvMBlockDescriptor:NvMBlockManagementType */ NvM_BlockManagementType BlockManagementType_en; /** * Block job priority. * TRACE[NVM477_Conf] Parameter NvMBlockDescriptor:NvMBlockJobPriority */ uint8 JobPriority_u8; /** * Bit-field containing several configuration parameter which can be represented by a bit. * NvM provides special bit mask to access individual bits from this bit-field: * - NVM_PRV_BLOCK_FLAG_SELECT_FOR_READ_ALL * TRACE[NVM117_Conf] Parameter NvMBlockDescriptor:NvMSelectBlockForReadAll * - NVM_PRV_BLOCK_FLAG_SELECT_FOR_WRITE_ALL * TRACE[NVM549_Conf] Parameter NvMBlockDescriptor:NvMSelectBlockForWriteAll * - NVM_PRV_BLOCK_FLAG_SELECT_FOR_FIRST_INIT_ALL * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2828] Parameter NvMBlockDescriptor:NvMRbSelectBlockForFirstInitAll * - NVM_PRV_BLOCK_FLAG_SELECT_FOR_INIT_AT_LAYOUT_CHANGE * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2881] Parameter NvMBlockDescriptor:NvMRbInitBlockAtLayoutChange * - NVM_PRV_BLOCK_FLAG_WRITE_PROTECTED * TRACE[NVM033_Conf] Parameter NvMBlockDescriptor:NvMBlockWriteProt * - NVM_PRV_BLOCK_FLAG_WRITE_ONCE * TRACE[NVM072_Conf] Parameter NvMBlockDescriptor:NvMWriteBlockOnce * - NVM_PRV_BLOCK_FLAG_RESISTANT_TO_CHANGED_SW * TRACE[NVM483_Conf] Parameter NvMBlockDescriptor:NvMResistantToChangedSw * - NVM_PRV_BLOCK_FLAG_USE_SYNC_MECHANISM * TRACE[NVM519_Conf] Parameter NvMBlockDescriptor:NvMBlockUseSyncMechanism * - NVM_PRV_BLOCK_FLAG_USE_AUTO_VALIDATION * TRACE[NVM557_Conf] Parameter NvMBlockDescriptor:NvMBlockUseAutoValidation * - NVM_PRV_BLOCK_FLAG_USE_VARIABLE_BLOCK_LENGTH * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2996] Parameter NvMBlockDescriptor:NvMRbNvBlockLengthString * - NVM_PRV_BLOCK_FLAG_SELECT_FOR_MIGRATION * TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3027] Parameter NvMBlockDescriptor:NvMRbFirstReadDataMigration */ uint16 stFlags_u16; } NvM_Prv_BlockDescriptor_tst;
- NvM_Cfg.h:包含了NvM涉及的一些宏定义配置,用以影响静态代码的行为。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ // TRACE[NVM552] // Header file specifying NvM pre-compile time configuration parameters #ifndef NVM_CFG_H #define NVM_CFG_H /* ********************************************************************************************************************** * Includes ********************************************************************************************************************** */ // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2993] // Function-like macro NVM_CFG_NV_BLOCK_LENGTH shall // support runtime calculated block lengths // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2997] // Include declarations of runtime calculated block // lengths to make it usable in function-like macro NVM_CFG_NV_BLOCK_LENGTH /* ********************************************************************************************************************** * Defines/Macros ********************************************************************************************************************** */ /* AUTOSAR version information */ #define NVM_AR_RELEASE_MAJOR_VERSION 4 /* AR major version */ #define NVM_AR_RELEASE_MINOR_VERSION 2 /* AR minor version */ #define NVM_AR_RELEASE_REVISION_VERSION 2 /* AR patch version */ /* SW version information */ #define NVM_SW_MAJOR_VERSION 11 /* SW major version */ #define NVM_SW_MINOR_VERSION 0 /* SW minor version */ #define NVM_SW_PATCH_VERSION 0 /* SW patch version */ /* Additional defines */ #define NVM_VENDOR_ID 6 #define NVM_MODULE_ID 20 /* Module ID NVM */ #define NVM_INSTANCE_ID 0 /* Instance ID NVM */ // --------------------------------------------------------------------------------------------------------------------- // TRACE[NVM028_Conf] // Defines for common options (in the same order as in the ParamDef) // --------------------------------------------------------------------------------------------------------------------- // TRACE[NVM491_Conf] // Enables/disables some APIs which are related to NvM API configuration classes #define NVM_API_CONFIG_CLASS (NVM_API_CONFIG_CLASS_3) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2803] // Enables/disables the notification of BswM about the current status of the multiblock job #define NVM_BSWM_MULTI_BLOCK_JOB_STATUS_INFORMATION (STD_ON) // TRACE[NVM492_Conf] // ID representing the currently configured block layout #define NVM_COMPILED_CONFIG_ID (0u) // TRACE[NVM493_Conf] // Maximum number of bytes which shall be processed within one cycle of job processing #define NVM_CRC_NUM_OF_BYTES (1u) // The parameter NvMDatasetSelectionBits is not supported in this implementation of NvM // TRACE[NVM495_Conf] // Enables/disables development error detection #define NVM_DEV_ERROR_DETECT (STD_ON) // TRACE[NVM496_Conf] // Enables/disables switching memory drivers to fast mode // during performing NvM_ReadAll/NvM_WriteAll #define NVM_DRV_MODE_SWITCH (STD_OFF) // TRACE[NVM497_Conf] // Enables/disables the dynamic configuration management handling // by the NvM_ReadAll request #define NVM_DYNAMIC_CONFIGURATION (STD_OFF) // TRACE[NVM498_Conf] // Enables/disables job prioritization handling #define NVM_JOB_PRIORITIZATION (STD_ON) // TRACE[NVM540_Conf] // Defines the cycle time in seconds of the periodic calling of NvM main function #define NVM_MAIN_FUNCTION_CYCLE_TIME (0.01u) // TRACE[NVM500_Conf] // Callback routine indicating termination of each asynchronous multi block requests #define NVM_MULTI_BLOCK_CALLBACK (NULL_PTR) // TRACE[NVM501_Conf] // Enables/disables polling mode in NvM // (disables/enables callback functions for lower layers) #define NVM_POLLING_MODE (STD_ON) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2945] // Enables/disables the auxiliary service interface #define NVM_RB_AUX_INTERFACE (STD_OFF) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2746] // Version of the generated ARXML file(s) #define NVM_RB_GEN_ARXML_VERSION (NVM_GEN_ARXML_VERSION_402) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2893] // Enables/disables the initialization of blocks #define NVM_RB_INIT_AT_LAYOUT_CHANGE (STD_OFF) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2762] // Callback routine indicating the start of each asynchronous multi block operation #define NVM_RB_MULTI_BLOCK_START_CALLBACK (NULL_PTR) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2843] // Callback routine indicating termination of any NvM job #define NVM_RB_OBSERVER_CALLBACK (NULL_PTR) // RAM (re-)intialization definitions // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2786] // Defines the behavior of NvM module when saved RAM zone is lost #define NVM_RB_RAM_INIT_CHECK (NVM_RB_RAM_INIT_CHECK_NONE) // NvM blocks RAM status bits are initialized with default values. // Saved RAM zone is considered lost. #define NVM_RB_RAM_INIT_CHECK_NONE (0u) // NvM blocks RAM status bits are not initialized. Only blocks with INVLAID RAM bit have // their RAM blocks filled in with Nv data during NvM_ReadAll. #define NVM_RB_RAM_INIT_CHECK_QUICK (1u) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2787] // Enables/disables enhanced configuration #define NVM_RB_REMOVE_NON_RESISTANT_BLOCKS (STD_OFF) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2977] // Enables/disables the NvM_Rb_SetWriteAllTrigger API #define NVM_RB_SET_WRITEALL_TRIGGER_API (STD_ON) // TRACE[NVM518_Conf] // Number of retries for mirror operations before postponing the current job #define NVM_REPEAT_MIRROR_OPERATIONS (0u) // TRACE[NVM502_Conf] // Enables/disables the NvM_SetRamBlockStatus API #define NVM_SET_RAM_BLOCK_STATUS_API (STD_ON) // TRACE[NVM503_Conf] // Number of queue entries for the immediate priority job queue #define NVM_SIZE_IMMEDIATE_JOB_QUEUE (1u) // TRACE[NVM504_Conf] // Number of queue entries for the standard job queue #define NVM_SIZE_STANDARD_JOB_QUEUE (1u) // TRACE[NVM505_Conf] // Enables/disables the NvM_GetVersionInfo API #define NVM_VERSION_INFO_API (STD_OFF) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3124] // Defines the request monitoring function for the NvM #define NVM_RB_REQ_MONITOR (NVM_RB_REQ_MON_DISABLED) // Request monitoring disabled #define NVM_RB_REQ_MON_DISABLED (0u) // Monitoring of write requests enabled #define NVM_RB_REQ_MON_WRITE (1u) // --------------------------------------------------------------------------------------------------------------------- // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2914] // Names of overloaded API functions // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- // TRACE[NVM481_Conf] // IDs for all configured blocks // --------------------------------------------------------------------------------------------------------------------- #define NvMConf_NvMBlockDescriptor_NvM_MultiBlock (0u) #define NvMConf_NvMBlockDescriptor_NvM_ConfigId (1u) #define NvMConf_NvMBlockDescriptor_ECUM_CFG_NVM_BLOCK (2u) #define NvMConf_NvMBlockDescriptor_NvMBlockDescriptor_Dem_AllEventStateByte (3u) #define NvMConf_NvMBlockDescriptor_NvMBlockDescriptor_Dem_EventMemory0 (4u) #define NvMConf_NvMBlockDescriptor_NvMBlockDescriptor_Dem_NvmCommonData (5u) #define NvMConf_NvMBlockDescriptor_NvM_UserData0 (6u) // --------------------------------------------------------------------------------------------------------------------- // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2801] // Lengths of all configured blocks as define // --------------------------------------------------------------------------------------------------------------------- #define NVM_CFG_NV_BLOCK_LENGTH_NvM_MultiBlock (1u) #define NVM_CFG_NV_BLOCK_LENGTH_NvM_ConfigId (2u) #define NVM_CFG_NV_BLOCK_LENGTH_ECUM_CFG_NVM_BLOCK (8u) #define NVM_CFG_NV_BLOCK_LENGTH_NvMBlockDescriptor_Dem_AllEventStateByte (240u) #define NVM_CFG_NV_BLOCK_LENGTH_NvMBlockDescriptor_Dem_EventMemory0 (60u) #define NVM_CFG_NV_BLOCK_LENGTH_NvMBlockDescriptor_Dem_NvmCommonData (16u) #define NVM_CFG_NV_BLOCK_LENGTH_NvM_UserData0 (1u) // --------------------------------------------------------------------------------------------------------------------- // Miscellaneous other definitions // --------------------------------------------------------------------------------------------------------------------- // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3028] // Define directive for checking // Runtime RAM Block Configuration feature enabled/disabled #define NVM_PRV_RUNTIME_RAM_BLOCK_CONFIG STD_OFF // RAM Mirror definitions #define NVM_PRV_HAS_RAM_MIRROR STD_ON #define NVM_PRV_SIZE_RAM_MIRROR (240u) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2870] // The implementation of the maintenance operation is done as if this feature was configurable // Enables/disables the maintenance of redundant blocks (internal definition) #define NVM_PRV_MAINTAIN_REDUNDANT_BLOCKS (STD_OFF) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3158] // ID of the first used block #define NVM_CFG_FIRST_USED_BLOCK (2u) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-2849] // ID of the last NvM user block #define NVM_CFG_LAST_USER_BLOCK (6u) // TRACE[BSW_SWS_AR4_0_R2_NVRAMManager_Ext-3159] // Number of all configured blocks #define NVM_CFG_NR_BLOCKS (7) // Additional internal helper definitions #define NVM_PRV_NR_BLOCKS_ADMIN (7u) #define NVM_PRV_NR_PERSISTENT_IDS (5u) #endif
集成代码
集成代码包括常见的SchM以及MemMap。
在SchM针对SchM_Enter_NvM_Main与SchM_Exit_NvM_Main添加关闭和打开中断代码。
#define SCHM_ENTER_DEFAULT() SuspendAllInterrupts()
#define SCHM_EXIT_DEFAULT() ResumeAllInterrupts()
LOCAL_INLINE FUNC(void, NvM_CODE) SchM_Enter_NvM_Main(void)
{
/*The integrator shall place his code here which would disable/lock the interrupt*/
SCHM_ENTER_DEFAULT();
}
LOCAL_INLINE FUNC(void, NvM_CODE) SchM_Exit_NvM_Main(void)
{
/*The integrator shall place his code here which would disable/lock the interrupt*/
SCHM_EXIT_DEFAULT();
}
静态代码
主要介绍常见的静态代码涉及API说明,具体详细完整的介绍读者可以参考《AUTOSAR_SWS_NVRAMManager.pdf》以及《RTA-BSWReferenceGuide.pdf》。
- NvM_Init:用于重置NvM内部所有变量。
- NvM_MainFunction:用以执行NvM作业处理的循环调度函数。
- NvM_GetErrorStatus:用于读取特定块的错误/状态信息。
- NvM_ReadBlock:用于将NVRAM Block的数据复制到特定的RAM中。
- NvM_WriteBlock:用于将特定RAM中的数据复制到特定的NV块。
- NvM_ReadAll:初始化所有NVRAM Block的管理数据,并将配置在NvM_ReadAll读取的NVRAM Block数据复制到永久RAM块,或调用显式同步回调。
- NvM_WriteAll:函数NvM_WriteAll的工作应将永久RAM块的内容同步到其相应的NV块,或在关机时调用显式同步回调。
- NvM_JobEndNotification/NvM_JobErrorNotification:底层用以通知任务以出错/无错完成。
MemIf
动态配置代码
NvM的动态配置代码包含如下图所示文件。
我们下面说一下这个文件包含的内容:
- MemIf_Cfg.h:文件主要包含了FEE或EE的使用信息,并将NvM使用的MemIf接口映射到具体FEE接口。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ #ifndef MEMIF_CFG_H #define MEMIF_CFG_H /* ********************************************************************************************************************** * Includes ********************************************************************************************************************** */ #include "MemIf_Types.h" #include "Fee.h" /* ********************************************************************************************************************** * Defines/Macros ********************************************************************************************************************** */ #define MEMIF_VENDOR_ID 6 #define MEMIF_MODULE_ID 22 #define MEMIF_INSTANCE_ID 0 #define MEMIF_SW_MAJOR_VERSION 11 #define MEMIF_SW_MINOR_VERSION 0 #define MEMIF_SW_PATCH_VERSION 0 #define MEMIF_AR_RELEASE_MAJOR_VERSION 4 #define MEMIF_AR_RELEASE_MINOR_VERSION 2 #define MEMIF_AR_RELEASE_REVISION_VERSION 2 /* Switch for version info api */ #define MEMIF_VERSION_INFO_API STD_OFF /* Switch for dev error detect */ #define MEMIF_DEV_ERROR_DETECT STD_ON #define MEMIF_FEE_USED STD_ON #define MEMIF_NUM_OF_EA_DEVICES 0 #define MEMIF_FEE_AND_EA_USED STD_OFF #define MEMIF_MIN_NUM_DEVICES 0 #define MEMIF_MAX_NUM_DEVICES 1 /* ********************************************************************************************************************** * Type definitions ********************************************************************************************************************** */ /* ********************************************************************************************************************** * Variables ********************************************************************************************************************** */ /* ********************************************************************************************************************** * Extern declarations ********************************************************************************************************************** */ #define MemIf_Read(DeviceIndex,BlockNumber,BlockOffset,DataBufferPtr,Length) Fee_Read(BlockNumber,BlockOffset,DataBufferPtr,Length) #define MemIf_Write(DeviceIndex,BlockNumber,DataBufferPtr) Fee_Write(BlockNumber,DataBufferPtr) #define MemIf_InvalidateBlock(DeviceIndex,BlockNumber) Fee_InvalidateBlock(BlockNumber) #define MemIf_GetStatus(DeviceIndex) Fee_GetStatus() #define MemIf_GetJobResult(DeviceIndex) Fee_GetJobResult() #define MemIf_Cancel(DeviceIndex) Fee_Cancel() #define MemIf_EraseImmediateBlock(DeviceIndex,BlockNumber) Fee_EraseImmediateBlock(BlockNumber) #define MemIf_Rb_BlockMaintenance(DeviceIndex,BlockNumber) Fee_Rb_BlockMaintenance(BlockNumber) #define MemIf_Rb_VarLenRead(DeviceIndex,BlockNumber,BlockOffset,DataBufferPtr,Length) Fee_Rb_VarLenRead(BlockNumber,BlockOffset,DataBufferPtr,Length) #define MemIf_Rb_VarLenWrite(DeviceIndex,BlockNumber,DataBufferPtr,Length) Fee_Rb_VarLenWrite(BlockNumber,DataBufferPtr,Length) #define MemIf_Rb_GetMigrationResult(DeviceIndex,BlockNumber) Fee_Rb_GetMigrationResult(BlockNumber) /* MEMIF_CFG_H */ #endif
集成代码
集成代码包括常见的SchM以及MemMap。
同样在SchM_Enter_MemIf_Main与SchM_Exit_MemIf_Main添加打开和关闭中断代码,保证部分代码执行的原子性。
LOCAL_INLINE FUNC(void, MEMIF_CODE) SchM_Enter_MemIf_Main(void)
{
/*The integrator shall place his code here which would disable/lock the interrupt*/
SCHM_ENTER_DEFAULT();
}
LOCAL_INLINE FUNC(void, MEMIF_CODE) SchM_Exit_MemIf_Main(void)
{
/*The integrator shall place his code here which would disable/lock the interrupt*/
SCHM_EXIT_DEFAULT();
}
静态代码
主要介绍常见的静态代码涉及API说明,具体详细完整的介绍读者可以参考《AUTOSAR_SWS_MemoryAbstractionInterface.pdf》以及《RTA-BSWReferenceGuide.pdf》。
- MemIf_Read:调用由参数 Devicelndex选择的底层存储器抽象模块的“读取”函数。
- Memlf_Write:调用由参数 Devicelndex选择的底层存储器抽象模块的“写入”函数。
- Memlf_Cancel:调用由参数 Devicelndex选择的底层存储器抽象模块的“取消操作”函数。
- Memlf_GetStatus:调用由参数 Devicelndex选择的底层存储器抽象模块的“获取当前状态”函数。
Fee
动态配置代码
Fee的动态配置代码包含如下图所示文件。
我们下面说一下这两个文件包含的内容:
- Fee_Cfg.c:包含记录扇区信息的Fee_FlashProp_st结构体,以及Fee需要的NvRAM Block的信息Fee_BlockProperties_st。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ #include "Fee.h" #include "Fee_Prv.h" /* Properties of flash sectors */ #define FEE_START_SEC_CONST_UNSPECIFIED #include "Fee_MemMap.h" CONST (Fee_FlashProp_tst, FEE_CONST) Fee_FlashProp_st[FEE_NUM_FLASH_BANKS_AVAILABLE] = { { FEE_PHYS_SEC_START0, FEE_PHYS_SEC_END0, FEE_LOG_SEC_START0, FEE_LOG_SEC_END0 }, /* sector 0 */ { FEE_PHYS_SEC_START1, FEE_PHYS_SEC_END1, FEE_LOG_SEC_START1, FEE_LOG_SEC_END1 }, /* sector 1 */ }; #define FEE_STOP_SEC_CONST_UNSPECIFIED #include "Fee_MemMap.h" /* Linked functions of the Fee */ #define FEE_START_SEC_CODE #include "Fee_MemMap.h" CONST (Fee_LinkedFunctions_tst, FEE_CONST) Fee_LinkedFunctions_cst = { NULL_PTR }; #define FEE_STOP_SEC_CODE #include "Fee_MemMap.h" /* Block properties for all Fee blocks * * Status Flags: * Block flags will help to specify a more detailed block configuration. The low Byte of these block flags is also stored * in the flash (status byte inside the block header). This information (in Flash) can be used to read/write the layout * without configuration (PAV, CB). * * * |<----- Block Status Byte in Block Header ----->| * |<---------------------------------------- Block Flags ---------------------------------------->| * F E D C B A 9 8 | 7 6 5 4 3 2 1 0 | * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ * | | | | | |Prio-| Job type |Ign. |No F.| Rob |Surv.|(Inv)| DataFilter| Sec-| * | | | | | |rity | |Blk |back |Attr.|Attr.| | Type | lvl | * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ * * * 0 ... SecurityLevel => 0...SingleStorage, 1...DoubleStorage * 1+2 ... Data Filter Type => 0...Dynamic: Anybody can erase this block (e.g. during migration) * 1...Static: Only certain users (e.g. repair shops) can erase this block * 2...Permanent: Only very certain users (e.g. OEM) can erase this block * 3...Super Permanent: Block can never be erased * 3 ... Invalid => 0...Block OK, 1...Block is invalid --> can be changed by function Fee_InvalidateBlock * 4 ... Survival Attribute => 0...No survival, 1... Survival (even without being part of the layout) * 5 ... Robustness Attribute (Robustness against data modification during write execution) * => 0...Deactivated: No additional checksum is used * => 1...Activated: Additional checksum is used * 6 ... NoFallback => 0...Deactivated: A fallback to old copies is allowed * => 1...Activated: A fallback to old copies is not allowed * 7 ... Ignore Block => 0...Deactivated: Block is considered * => 1...Activated: Block is ignored * 8+9 ... TypeOfBlock => 0...InternalJob, 1...NvmJob, 2...AdapterJob (e.g. Mx17 Eep adapter) * A ... Priority => Job priority: 0...FEE_NORMAL_PRIO_E --> FeeImmediateData = No * 1...FEE_HIGH_PRIO_E --> FeeImmediateData = Yes */ #ifdef FEE_PRV_USE_ROM_TABLE #define FEE_START_SEC_CONST_UNSPECIFIED #include "Fee_MemMap.h" const Fee_BlockPropertiesType_tst Fee_BlockProperties_st[FEE_NUM_BLOCKS] = { #else #define FEE_START_SEC_VAR_INIT_UNSPECIFIED #include "Fee_MemMap.h" Fee_BlockPropertiesType_tst Fee_BlockProperties_st[FEE_NUM_BLOCKS] = { #endif /* FeeRbBlockPersistentId, StatusFlags, BlkLength , FeeRbCallbackEnd , FeeRbCallbackError */ /* 0 */{ 0x2292 , 0x0100 , 0x0001 ,NULL_PTR ,NULL_PTR } /* NvM_UserData0 */, /* 1 */{ 0x2CFE , 0x0100 , 0x00F0 ,NULL_PTR ,NULL_PTR } /* NvMBlockDescriptor_Dem_AllEventStateByte */, /* 2 */{ 0xC3F9 , 0x0100 , 0x0010 ,NULL_PTR ,NULL_PTR } /* NvMBlockDescriptor_Dem_NvmCommonData */, /* 3 */{ 0xF2FB , 0x0100 , 0x0008 ,NULL_PTR ,NULL_PTR } /* ECUM_CFG_NVM_BLOCK */, /* 4 */{ 0xF4C1 , 0x0100 , 0x003C ,NULL_PTR ,NULL_PTR } /* NvMBlockDescriptor_Dem_EventMemory0 */, }; #ifdef FEE_PRV_USE_ROM_TABLE #define FEE_STOP_SEC_CONST_UNSPECIFIED #include "Fee_MemMap.h" #else #define FEE_STOP_SEC_VAR_INIT_UNSPECIFIED #include "Fee_MemMap.h" #endif /* This section is applicable only for FEE 2.0, ignore or dont configure this section for FEE 1.0 */
- Fee_Cfg.h:包含Fee的一些宏定义配置,如下所示。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ #ifndef FEE_CFG_H #define FEE_CFG_H #include "Fls.h" #define FEE_PRESENT 1 /* For Fee test purposes only */ #define FEE_PRV_DEBUGGING FALSE #define FEE_SIMULATION_ACTIVE FALSE /* ********************************************************************************************************************* * * Description: This configuration is to enable and disable the availability of the variable which gives hint on how much bytes * free bytes available in D-flash. The veriable can be used only for seeing the status of the free bytes using INCA tool * Application should not use this veriable for taking any decision. * TRUE : The veriable is available for INCA measurement * FALSE : The veriable won't be available INCA for measurement ******************************************************************************************************************** */ #define FEE_PRV_FREEBYTES_INDFLASH FALSE /* ********************************************************************************************************************* * SWS Item: FEE039_Conf * Container Name: FeeGeneral * Description: Container for general parameters. These parameters are not specific to a block. ******************************************************************************************************************** */ #define FEE_VENDOR_ID 6 #define FEE_MODULE_ID 21 /* Module ID of Fee */ #define FEE_INSTANCE_ID 0 /* Instance ID */ /* Fee Software Version in BASD is Fee / AR40.11.0.0 */ #define FEE_SW_MAJOR_VERSION 11 #define FEE_SW_MINOR_VERSION 0 #define FEE_SW_PATCH_VERSION 0 /* Fee is compatible with Autosar 4.2Rev2 */ #define FEE_AR_RELEASE_MAJOR_VERSION 4 #define FEE_AR_RELEASE_MINOR_VERSION 2 #define FEE_AR_RELEASE_REVISION_VERSION 2 /* ********************************************************************************************************************* * SWS Item: FEE111_Conf * Name: FeeDevErrorDetect * Description: Pre-processor switch to enable and disable development error detection. * true: Development error detection enabled. * false: Development error detection disabled. * Multiplicity: 1 * Type: EcucBooleanParamDef ********************************* ********************************************************************************** */ #define FEE_DEV_ERROR_DETECT STD_OFF /* ********************************************************************************************************************* * SWS Item: FEE152_Conf * Name: FeeIndex * Description: Specifies the InstanceId of this module instance. If only one instance is present it shall have * the Id 0. * Multiplicity: 1 * Type: EcucIntegerParamDef * Range: 0 .. 254 ******************************************************************************************************************* */ #define FEE_FEEINDEX 0u /* ********************************************************************************************************************* * SWS Item: FEE112_Conf * Name: FeeNvmJobEndNotification * Description: Mapped to the job end notification routine provided by the upper layer module * (NvM_JobEndNotification). * This tag has no effect. Job end and job error notifications must be configured block wise * if necessary via FeeRbCallbackEnd and FeeRbCallbackError. * Multiplicity: 0 .. 1 * Type: EcucFunctionNameDef ******************************************************************************************************************* */ #define FEE_NVM_JOB_END_NOTIFICATION NULL_PTR /* ********************************************************************************************************************* * SWS Item: FEE113_Conf * Name: FeeNvmJobErrorNotification * Description: Mapped to the job error notification routine provided by the upper layer module * (NvM_JobErrorNotification). * This tag has no effect. Job end and job error notifications must be configured block wise * if necessary via FeeRbCallbackEnd and FeeRbCallbackError. * Multiplicity: 0 .. 1 * Type: EcucFunctionNameDef ******************************************************************************************************************* */ #define FEE_NVM_JOB_ERROR_NOTIFICATION NULL_PTR /* ********************************************************************************************************************* * SWS Item: FEE114_Conf * Name: FeePollingMode * Description: Pre-processor switch to enable and disable the polling mode for this module. * true: Polling mode enabled, callback functions (provided to FLS module) disabled. * false: Polling mode disabled, callback functions (provided to FLS module) enabled. * Multiplicity: 1 * Type: EcucBooleanParamDef ******************************************************************************************************************* */ #define FEE_POLLING_MODE STD_ON /* ********************************************************************************************************************* * SWS Item: FEE119_Conf * Name: FeeSetModeSupported * Description: Compiler switch to enable/disable the 'SetMode' functionality of the FEE module. * TRUE: SetMode functionality supported / code present, * FALSE: SetMode functionality not supported / code not present. Note: This configuration setting has * to be consistent with that of all underlying flash device drivers (configuration parameter * FlsSetModeApi). * Multiplicity: 1 * Type: EcucBooleanParamDef ******************************************************************************************************************* */ #define FEE_SET_MODE_SUPPORTED STD_OFF /* ********************************************************************************************************************* * SWS Item: FEE115_Conf * Name: FeeVersionInfoApi * Description: Pre-processor switch to enable / disable the API to read out the modules version information. * true: Version info API enabled. * false: Version info API disabled. * Multiplicity: 1 * Type: EcucBooleanParamDef ******************************************************************************************************************* */ #define FEE_VERSION_INFO_API STD_OFF /* ********************************************************************************************************************* * SWS Item: FEE116_Conf * Name: FeeVirtualPageSize * Description: The size in bytes to which logical blocks shall be aligned. * Multiplicity: 1 * Type: EcucIntegerParamDef * Range: 0 .. 65535 ******************************************************************************************************************* */ #define FEE_VIRTUAL_PAGE_SIZE 8u /* ********************************************************************************************************************* * SWS Item: Conf * Name: FeeRbPageBufferSize * Description: The size in bytes to which logical blocks shall be aligned. * Multiplicity: 0 * Type: EcucIntegerParamDef * Range: 256 .. 65535 ******************************************************************************************************************* */ #define FEE_LL_PAGEBUFFSIZE 1024u /* ********************************************************************************************************************* * SWS Item: Conf * Name: FeeRbMaintainRedundantBlocks * Description: Pre-processor switch to enable / disable the API to maintain the redundant blocks. * true: Maintain function enabled. * false: Maintain function disabled. * Multiplicity: 0 * Type: EcucBooleanParamDef ******************************************************************************************************************** */ #define FEE_RB_MAINTAIN TRUE /* ********************************************************************************************************************* * SWS Item: Conf * Name: FeeRbReadForce * Description: Pre-processor switch to enable and disable read force function. * true: Read force function enabled. * false: Read force function disabled. * Multiplicity: 0 * Type: EcucBooleanParamDef ******************************************************************************************************************** */ #define FEE_RB_READ_FORCE FALSE /* ********************************************************************************************************************* * SWS Item: RB add-on * Name: FeeRbAddonsCCAS * Description: Pre-processor switch to enable and disable addons for CCAS which are realised is an adapter: * - rba_FeeAddOnAS_EnterStopMode * - rba_FeeAddOnAS_WriteAdr * - rba_FeeAddOnAS_ForcedRead * Hint: for the usage of the rba_FeeAddOnAS_ForcedRead functionality, the Fee configuration tag * "FeeRbReadForce" needs to be activated as well. * Multiplicity: 0 * Type: EcucBooleanParamDef ******************************************************************************************************************** */ #define FEE_RB_ADDONS_CCAS FALSE /* ********************************************************************************************************************* * SWS Item: Conf * Name: FeeRbActSurvivalEval * Description: Pre-processor switch to enable or disable an additional block specific reorganization for unknown * blocks with an active survival setting ("FeeRbSurvival") in the medium. * true: Feature enabled ("block specific afterburner" on for blocks with active survival setting). * false: Feature disabled ("block specific afterburner" off for blocks with active survival setting). * Hint: If activated, this block will be overtaken independent from the "FeeRbActUnknownBlockReorg" * setting ("general afterburner"). * Multiplicity: 0 * Type: EcucBooleanParamDef ******************************************************************************************************************** */ #define FEE_RB_ACT_SURVIVAL_EVAL FALSE /* ********************************************************************************************************************* * SWS Item: Conf * Name: FeeRbActUnknownBlockReorg * Description: Pre-processor switch to enable or disable an additional reorganization for any unknown block in * the medium. * true: Feature enabled ("general afterburner" on for all unknown blocks). * false: Feature disabled ("general afterburner" off for all unknown blocks). * Hints: If activated, all unknown blocks will be overtaken independent from the "FeeRbActSurvivalEval" * setting ("block specific afterburner"). * If deactivated and with active survival evaluation ("FeeRbActSurvivalEval" == TRUE), * only blocks with an active survival setting ("FeeRbSurvival" == TRUE) will be overtaken. * Only the CB (Customer Block) is allowed to enable this feature, because this is affecting the * thresholds of the sector reorganization to a special safety level. It must be deactivated * for the ASW! * Multiplicity: 0 * Type: EcucBooleanParamDef ******************************************************************************************************************** */ #define FEE_RB_ACT_UNKNOWN_BLOCK_REORG FALSE /* ********************************************************************************************************************* * SWS Item: Conf * Name: FeeRbActUnknownBlockReorgCacheSize * Description: Pre-processor switch to enable or disable an additional optimisation in sector reorganization * for any unknown block in the medium. * This feature fastens the sector reorganisation for unknown blocks (Global after burner feature) by * scanning the sector and building up a cache for unknown block. Each unknown block requires 6 bytes * information in the cache, 4 bytes for address and 2 bytes for FEE index. * For best performance project must allocate enough cache size to store information of all unknown blocks. * For example, if a project has 250 unknown blocks in CB then at least 250*6 = 1500bytes to be allocated. * Default value is for 300 unknown blocks, which is 300*6=1800bytes. * Using the configured size the size of the array is generated. * Multiplicity: 0 * Type: EcucBooleanParamDef ******************************************************************************************************************** */ #define FEE_RB_ACT_UNKNOWN_BLOCK_CACHE_SIZE 0u /* ********************************************************************************************************************* * SWS Item: Conf * Name: FeeRbActEraseSuspension * Description: Pre-processor switch to enable or disable erase suspension feature of Ti devices. * true: Erase suspension enabled. * false: Erase suspension disabled. * Multiplicity: 0 * Type: EcucBooleanParamDef ******************************************************************************************************************** */ #define FEE_RB_ACT_ERASE_SUSPENSION FALSE /* ****************************************************************************************************************** ******************************************** FeePublishedInformation ********************************************* ****************************************************************************************************************** */ /* FEE117_Conf: FeeBlockOverhead {FEE_BLOCK_OVERHEAD} * Management overhead per logical block in bytes. * Note: * If the management overhead depends on the block size or block location a formula has to be provided that allows the * configurator to calculate the management overhead correctly. * Type: EcucIntegerParamDef * Range: 0 .. 65535 */ #define FEE_BLOCK_OVERHEAD 14u /* FEE070_Conf: FeeMaximumBlockingTime {FEE_MAXIMUM_BLOCKING_TIME} * The maximum time the FEE module's API routines shall be blocked (delayed) by internal operations. * Note: * Internal operations in that case means operations that are not explicitly invoked from the upper layer module but * need to be handled for proper operation of this module or the underlying memory driver. * Type: EcucFloatParamDef * Range: 0.0 .. Inf */ #define FEE_MAXIMUM_BLOCKING_TIME 5u /* FEE118_Conf: FeePageOverhead {FEE_PAGE_OVERHEAD} * Management overhead per page in bytes. * Note: * If the management overhead depends on the block size or block location a formula has to be provided that allows the * configurator to calculate the management overhead correctly. * Type: EcucIntegerParamDef * Range: 0 .. 65535 */ #define FEE_PAGE_OVERHEAD 0u /* ****************************************************************************************************************** *************************************** Fee internally used configuration **************************************** ****************************************************************************************************************** */ /* Fee Robustness Feature active for any of the configured blocks */ #define FEE_ROB_FEATURE_ACTIVE TRUE /* Fee NoFallback feature active for any of the configured blocks */ #define FEE_NO_FALLBACK_ACTIVE FALSE /* Fast cache initialization */ #define FEE_FAST_CACHE_INIT_ACTIVE TRUE /* Header Recheck - necessary for flash types with undefined erase pattern like Renesas RH850 */ #define FEE_HEADER_RECHECK_ACTIVE FALSE /* Robust programming feature setting */ #define FEE_ROBUST_PROG_ACTIVE FALSE /* Threshold calculation*/ #define FEE_REQUIRED_FREE_SPACE_BEFORE_SOFT_SR 131080uL /* FEE_REQUIRED_FREE_SPACE_BEFORE_HARD_SR = Min sector size + 1 = 131072 byte + 1) * 1,5 * 1,0 */ #define FEE_REQUIRED_FREE_SPACE_BEFORE_HARD_SR 131080uL /* FEE_REQUIRED_FREE_SPACE_BEFORE_HARD_SR = Min sector size + 1 = 131072 byte + 1 * 1,0 */ /* Number of pages which are used to store the blockheader */ #define FEE_PAGES_USED_BY_BLK_HEADER 2u /* Number of data bytes behind the blockheader */ #define FEE_FREE_BYTES_AFTER_HEADER 2u /* Size of the sector header */ #define FEE_SEC_HEADER_SIZE 96u /* Number of FeeBlocks */ #define FEE_NUM_BLOCKS 5u /* Number of unknown blocks that can be transfered/checked in one iteration of unknown block sector reorganisation (Global After burner feature) */ #define FEE_RB_ACT_UNKNOWN_BLK_CACHE_ARRAY_SIZE 0u /* Number of retries in case of an error (Compare / Read / Write) */ #define FEE_MAX_RD_WR_COMP_RETRIES 3u /* Init value for the cache */ #define FEE_CACHE_INIT_VALUE 0xCAFEAFFEuL /* Update start value for the cache (there might be an entry available in the flash which can be found via "manual search") */ #define FEE_CACHE_TMP_INVALID_VALUE 0xAFFECAFEuL #define FEE_PRV_CFG_SELECTED_FS 1 /* ****************************************************************************************************************** ******************************************* Generate FLASH configuration ***************************************** ****************************************************************************************************************** */ #define FEE_PAGE_LEN 8u /* Configured virtual page size */ #define FEE_FASTMODE_ALIGNMENT 8u /* Necessary address alignment to write in FastMode */ #define FEE_ERASE_PATTERN 0u /* DFLASH configuration for uC MCU_RB_MANUAL_CFG */ /* ******************************************* Configuration of sector 0 ******************************************** */ #define FEE_PHYS_SEC_START0 0x00000000uL #define FEE_PHYS_SEC_END0 0x0001FFFFuL #define FEE_LOG_SEC_START0 (FEE_PHYS_SEC_START0 + FEE_SEC_HEADER_SIZE) #define FEE_LOG_SEC_END0 FEE_PHYS_SEC_END0 /* ******************************************* Configuration of sector 1 ******************************************** */ #define FEE_PHYS_SEC_START1 0x00020000uL #define FEE_PHYS_SEC_END1 0x0003FFFFuL #define FEE_LOG_SEC_START1 (FEE_PHYS_SEC_START1 + FEE_SEC_HEADER_SIZE) #define FEE_LOG_SEC_END1 FEE_PHYS_SEC_END1 #define FEE_NUM_FLASH_BANKS_AVAILABLE 2u /* Number of sectors which are available by the HW */ /* ****************************************************************************************************************** ******************************************* Defines for accessing blocks ***************************************** ****************************************************************************************************************** */ /* Defines for all configured blocks which should be used by the upperlaying modules (NvM, ...) to access their blocks via the Fee APIs */ #define FeeConf_FeeBlockConfiguration_NvM_UserData0 0 #define FeeConf_FeeBlockConfiguration_NvMBlockDescriptor_Dem_AllEventStateByte 1 #define FeeConf_FeeBlockConfiguration_NvMBlockDescriptor_Dem_NvmCommonData 2 #define FeeConf_FeeBlockConfiguration_ECUM_CFG_NVM_BLOCK 3 #define FeeConf_FeeBlockConfiguration_NvMBlockDescriptor_Dem_EventMemory0 4 /* ****************************************************************************************************************** ********************************** External declarations, provided by/to Fee ************************************* ****************************************************************************************************************** */ /* ****************************************************************************************************************** ********************************************** Fs specific defines *********************************************** ****************************************************************************************************************** */ #define FEE_ERASE_PATTERN_U32 0x00000000uL #define FEE_PHY_PAGE_LEN 8u /* Physical page size */ #endif /* FEE_CFG_H */
集成代码
因为示例程序使用了Rba_FeeFs1,所以集成代码包含两个部分,第一部分还是SchM以及MemMap。
SchM内容如下。
#define SchM_Enter_Fee_Order() SCHM_ENTER_DEFAULT()
#define SchM_Exit_Fee_Order() SCHM_EXIT_DEFAULT()
还有一部分在Rba_FeeFs1中。
它包含了函数Fee_Fls_SyncRead,函数实现同步的读取DFlash(即Fls_Read之后调用Fls_MainFunction,然后再通过Fls_GetJobResult获取状态直到不为MEMIF_JOB_PENDING)。
/*
* This is a template file. It defines integration functions necessary to complete RTA-BSW.
* The integrator must complete the templates before deploying software containing functions defined in this file.
* Once templates have been completed, the integrator should delete the #error line.
* Note: The integrator is responsible for updates made to this file.
*
* To remove the following error define the macro NOT_READY_FOR_TESTING_OR_DEPLOYMENT with a compiler option (e.g. -D NOT_READY_FOR_TESTING_OR_DEPLOYMENT)
* The removal of the error only allows the user to proceed with the building phase
*/
#ifndef NOT_READY_FOR_TESTING_OR_DEPLOYMENT
#error The content of this file is a template which provides empty stubs. The content of this file must be completed by the integrator accordingly to project specific requirements
#else
//#warning The content of this file is a template which provides empty stubs. The content of this file must be completed by the integrator accordingly to project specific requirements
#endif /* NOT_READY_FOR_TESTING_OR_DEPLOYMENT */
#include "rba_FeeFs1_SyncRead.h"
/**
*********************************************************************
* Fee_Fls_SyncRead(): Service for synchronous data read
*
* This function performed synchronous read data from Data Flash.
* Below is a template implementation. Integrators shall
* implement this function in order to match with the target MCAL.
*
* \param SourceAddress: Relative address of the data to be read in flash memory.
* This address offset will be added to the flash memory base address.
* \param TargetAddressPtr: Pointer to target data buffer.
* \param Length: Length in bytes to be read from Data Flash memory.
* \return Function success
* \retval E_OK: Read command has been accepted.
* \retval E_NOT_OK: Read command has not been accepted.
* \seealso
* \usedresources
*********************************************************************
*/
Std_ReturnType Fee_Fls_SyncRead( Fls_AddressType SourceAddress,
uint8 *TargetAddressPtr,
Fls_LengthType Length
)
{
Std_ReturnType RetVal = E_OK;
MemIf_JobResultType Fls_JobResult;
if(TargetAddressPtr == NULL_PTR)
{
RetVal = E_NOT_OK;
}else{
RetVal = Fls_Read((Fls_AddressType) SourceAddress, (uint8*)TargetAddressPtr, Length);
do{
Fls_MainFunction();
Fls_JobResult = Fls_GetJobResult();
} while(Fls_JobResult == MEMIF_JOB_PENDING);
if (Fls_JobResult != MEMIF_JOB_OK){
RetVal = E_NOT_OK;
}
}
return RetVal;
}
静态代码
主要介绍常见的静态代码涉及API说明,具体详细完整的介绍读者可以参考《AUTOSAR_SWS_FlashEEPROMEmulation.pdf》以及《RTA-BSWReferenceGuide.pdf》。
因为我们使用的是Rba_FeeFs1,所以静态代码都在其下。
下面是主要的API说明:
- Fee_Init: 初始化Fee模块。
- Fee_Read:启动一个读取任务。
- Fee_Write:启动一个写入任务。
- Fee_Cancel:调用底层驱动提供的取消任务接口。
- Fee_GetStatus:提供给MemIf获取当前Fee状态。
- Fee_GetJobResult:查询上层软件发出的上一个已接受作业的结果。
- Fee_InvalidateBlock:使逻辑块无效。
- Fee_InvalidateBlock:擦除一个逻辑块。
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。