Autosar云天精讲 :《NVM 体系化讲解(十四万字精讲版本)》



文章目录

1Document Information

NVM系统功能介绍

2 Introduction

本文档描述了AUTOSAR BSW模块NVM的功能、API和配置

UTOSAR Schema Compatibility R4.0.3

Vendor ID: NVM_VENDOR_ID 30 decimal (= Vector-Informatik, according to HIS)

Module ID: NVM_MODULE_ID 20 decimal (according to ref. [5])

模块NVM的创建是为了从应用程序中抽象非易失性内存的使用,例如EEPROM或Flash。所有对NV内存的访问都是基于块(block)的。为了避免冲突和不一致的数据,NVM应该是访问非易失性内存的唯一模块。

NVM访问模块MEMIF(内存抽象接口),它抽象模块FEE(Flash EEPROM 模拟)和EA(EEPROM模拟)。因此,NVM是硬件独立的。FEE模块和EA抽象访问Flash或EEPROM驱动程序。选择合适的FEE(费用或EA)NVM使用由MEMIF提供的句柄。

The following figure shows where the NVM is located in the AUTOSAR architecture

image-20221021105929658

The next figure shows the interfaces to adjacent modules of the NVM. These interfaces are described in chapter

image-20221021110110234

应用程序通常不会直接访问BSW模块的服务。它们通过RTE使用BSW模块提供的服务端口。

3 功能描述 Functional Description

3.1 功能 Features

本章列出的特性涵盖了指定的完整功能。

支持和不支持的特性如下表所示。有关不支持特性的进一步信息

支持以下特性:

功能支持 Supported Feature
完整的API接口/Complete API
Block类型管理/Block Management Types (Native, Redundant, Dataset)
CRC处理(CRC16, CRC32) /CRC handling (CRC16, CRC32)
优先级处理,包括立即数据写入 /Priority handling, including Immediate (Crash) Data write
作业队列 /Job queuing
默认ROM(ROM默认块,初始化回调)/ROM defaults (ROM defaults block, Init callback)
配置Id处理/Config Id handling
RAM块有效/修改处理 /RAM block valid/modified handling
在使用CRC启动期间重新验证RAM块 /Re-Validation of RAM blocks during start up using CRC
工作结束的通知 /Job end notifications
启动时跳过块 /Skipping Blocks during Start-Up
API配置类API Configuration Classes
服务端口-软件组件描述的生成 / Service Ports – Generation of Software Component Description
DCM对NV数据的并发访问 /Concurrent access to NV data for DCM
应用程序和NVM之间的显式同步机制 /Explicit Synchronization mechanism between application and NVM
与BswM内部交互/Interaction with BswM

不支持如下功能:

Not Supported Feature
数据集ROM块(管理类型数据集,多个ROM块) \ Dataset ROM blocks (Management Type Dataset, multiple ROM blocks)
禁用Set/Get DataIndex API \Disabling Set/Get_DataIndex API
静态块ID读取时的检查Static Block ID Check during read
写验证\Write Verification
读重试\Read Retries

3.1.1 Safety Features

3.1.1.1 Block Id check

NvM提供了一个特性来确保底层设备为当前正在处理的NvM块交付数据—块Id检查。

由于块Id检查是在CRC计算中通过扩展实现的,因此该特性只对配置了CRC的NvM块有效。由于该特性使用NvM块Id,在配置更新过程中,用户必须确保每个NvM块的块Id保持相同。否则,虽然读取了正确的数据,但检查将失败。

为了检查数据属于当前正在处理的NvM块,NvM计算NvM块Id和当前数据索引到它的CRC。这意味着实际上NvM计算的是块Id(2字节),数据索引(1字节)和实际数据-NvM需要一个CRC计算函数调用比没有块Id检查更多。

NvM无法区分错误的CRC和为另一个NvM块计算的CRC !如果底层模块交付的数据属于错误的NvM块,NvM的行为与CRC不匹配的情况相同。

3.1.2 Automatic Block Length

由于块长度可能在配置期间未知,因此可以为具有永久配置RAM的NvM块启用自动块长度功能。该特性将块长度的含义从实际长度更改为最大长度—实际块长度通过生成结构中的永久RAM的大小设置。配置的长度被底层模块用来初始化它们的结构,因此它不能小于实际长度。要检查配置的长度是否有效,必须启用块长度检查(参见3.5.3)。

Caution
系统运行后,知道实际块长度后,根据实际块长度调整配置。由于底层模块使用配置的长度,所以Flash或EEPROM中可能有很多未使用的空间。

3.2 Initialization

在使用模块NVM之前,必须先初始化它。NVM所依赖的所有模块都需要初始化。所有这些模块的初始化都应该由ECU状态管理器完成。如果NVM没有在AUTOSAR环境中使用,那么它应该由不同的实体来完成。注意,NVM不会自己初始化所使用的模块。

根据NVM堆栈的配置,可能需要初始化不同的模块。建议使用自底向上的策略进行初始化:

  • 内部设备的NV设备驱动程序(FLS/EEP)
  • 外部NV设备驱动程序可能依赖的低级驱动程序(例如DIO, SPI)
  • 外部NV设备的驱动程序(例如外部EEP或FLS)
  • NV设备抽象模块(EA/FEE)
  • 非易失性管理器(NVM)

按此顺序初始化模块可以确保在使用模块时,它所依赖的模块已经准备就绪。

Note

NvM 初始化步骤

  1. NvM_Init() (see 3.2.1)
  2. NvM_ReadAll() (see 3.2.2)
    Indenpendently from SelectBlockForReadAll NvM uses the NvM_ReadAll() to initialize all its blocks. Therefore it is not possible to access any NvM block until it was initialized during NvM_ReadAll().

3.2.1 Start-up

NVRAM Manager的基本初始化是通过请求NvM_Init()完成的,它应由ECU状态机调用 NvM_ReadAll()。由于对ECU启动时间有很强的约束,NvM_Init()请求不包含NVRAM块的基本初始化。NvM_Init()请求重置NVM的内部变量,例如队列和状态机。

3.2.2 Initialization of the Data Blocks

单个块的初始化通常由ECU状态管理器调用*NvM_ReadAll()*。所有没有有效RAM数据的块,并已经设置了SelectBlockForReadAll集将从NV内存中重新加载或从ROM(如果可用)。所有其他块都不会重新加载,它们必须由调用NvM_ReadBlock()的应用程序手动加载,但它们将被初始化,例如它们的编写保护和状态

块1 (Block 1)(配置ID)有一个特殊的角色。它存储在NV内存中,也是一个常量(NvM_CompiledConfigId_t),对外可见,可在链接时配置。

NvM_ReadAll()期间,块1的NV值与常量NvM_CompiledConfigId_t进行比较。在匹配的情况下,所有的NV块都被认为是有效的,NVM尝试从NV内存中读取它们。在不匹配的情况下,或者如果配置ID无法读取,系统的行为如下:

/* Type for an the additional published parameter Compiled Configuration ID (see CompiledConfigurationId in NvM.h). */
/* Compiled Config Id Type */
typedef union
{ /* PRQA S 0750 */ /* MD_MSR_Union */
    uint16 Word_u16;
    uint8  Bytes_au8[2u];
} NvM_CompiledConfigIdType;
  • 如果配置开关“动态配置处理(Dynamic Configuration Handling)”为“OFF”,则忽略不匹配。它将尝试从NV内存中读取所有块(也称为“正常的运行时准备normal runtime preparation”)。
  • 如果“动态配置处理(Dynamic Configuration Handling)”为“ON”,则对所有配置了“Resistant to Changed SW”选项的块进行正常的运行时准备。对于所有其他块,将进行“扩展运行时准备extended runtime preparation”。
  • 所有将被’扩展运行时准备extended runtime preparation’处理的块将被视为无效或空白。因此,可以重写标记为“Write Once”的块。如果可用,则加载ROM默认值或调用初始化回调。

3.3 States

NVRAM管理器内部由一个状态机组织,该状态机将在下面的章节中展示。

3.4 Main Functions

3.4.1 Hardware Independence

NVRAM管理器独立于其底层内存硬件。它访问MEMIF(内存抽象接口)的API。MEMIF为NVM抽象了模块FEE (Flash EEPROM仿真)和EA (EEPROM抽象)。FEE和EA用于在Flash或EEPROM设备中存储数据块。为了选择将块存储在哪个FEE或EA实例,NVM使用MEMIF提供的设备句柄(设备ID)。

3.4.2 Synchronous Requests

NVM API服务分为同步请求(synchronous)和异步请求(asynchronous)。

同步服务在调用时立即执行,它们在调用任务的上下文中执行。这意味着,行为取决于调用任务的特征,而不是NVM。例如,如果调用任务是非抢占任务,同步NVM请求将被执行,直到它完成。否则,如果调用任务是抢占任务,则同步NVM请求可以被另一个优先级更高的任务抢占。

以下NVM API服务启动同步请求:

/*	Init	*/
NvM_Init()
/*	Set		*/
NvM_SetDataIndex()
NvM_GetDataIndex()
NvM_SetBlockProtection()
NvM_SetBlockLockStatus()
NvM_SetRamBlockStatus() (for not CRC protected blocks)
/*	GET		*/    
NvM_GetErrorStatus()
NvM_GetVersionInfo()
/*	Cancel	*/     
NvM_CancelJobs()
NvM_CancelWriteAll()
/*	Kill	*/     
NvM_KillWriteAll()
NvM_KillReadAll()

3.4.3 Asynchronous Requests

Following NVM API services initiate asynchronous requests:

> NvM_ReadBlock()
> NvM_WriteBlock()
> NvM_RestoreBlockDefaults()
> NvM_EraseNvBlock()
> NvM_InvalidateNvBlock()
> NvM_SetRamBlockStatus() (for CRC protected blocks)
> NvM_ReadAll()
> NvM_WriteAll()
> NvM_RepairRedundantBlocks()

API调用是在调用任务的上下文中处理的。在这里,服务被排队并将被异步处理。排队请求的处理是在循环函数NvM_MainFunction()中完成的。

警告:

RAM块不能被任何用户访问,当一个请求到它的关联NVRAM块是挂起的!

这种限制也有一些例外:

> NvM_InvalidateNvBlockNvM_EraseNvBlock不访问任何RAM块。因此,仍然可以不受限制地访问

当NVM处理一个NvM_WriteBlock请求时,RAM块仍然可以读。

虽然应用程序不期望在NVM进程NvM_WriteAll时运行,但RAM块可能被读取,就像在NvM_WriteBlock处理期间一样。

3.4.4 API Configuration Classes and additional API Services

根据客户的需求,可以定制NVM的范围。指定了三个配置类,它们提供不同数量的NVM功能:

API configuration class 1:

使用了最少的API服务集。没有实现排队和作业优先级。

可提供以下功能:

> NvM_Init()
> NvM_GetErrorStatus()
> NvM_SetRamBlockStatus()
> NvM_ReadAll()
> NvM_WriteAll()
> NvM_CancelWriteAll()

API configuration class 2:

API服务的中间集。实现了排队和作业优先级。根据API配置类1,还提供了以下功能:

> NvM_SetDataIndex()
> NvM_GetDataIndex()
> NvM_ReadBlock()
> NvM_WriteBlock()
> NvM_RestoreBlockDefaults()
> NvM_CancelJobs()

API configuration class 3:

所有API服务都可用。以下函数可用于API配置类2:

> NvM_SetBlockProtection()
> NvM_EraseNvBlock()
> NvM_InvalidateNvBlock()

函数NvM_SetRamBlockStatus()NvM_GetVersionInfo()可以通过配置工具另外启用/禁用。函数NvM_SetBlockLockStatus()总是独立于API配置类而可用。

3.4.5 Block Handling

3.4.5.1 NV Blocks and Block Handles

用于存储在NV内存中的每个应用程序的数据包都被视为一个块。对于每个块使用一个惟一的块句柄(block ID)。对于应用程序来说,(RAM)块只是与该块相关联的变量之一。为了将这个变量写入NV内存,它调用NvM_WriteBlock()服务,该服务带有映射到这个变量的块句柄。块句柄名称是在NVM的配置过程中给出的。它们通过包含NvM.h发布到应用程序。

Note
块句柄名称根据AUTOSAR规范EcucConfiguration自动添加前缀:
<Module Definition>Conf_<Container Definition Short Name>_<Container Instance Short Name>
前缀对RTE没有影响。

Caution
异步作业(such as a write job)的实际处理在NvM_MainFunction中完成。因此它需要循环调用。这通常是由基本软件调度器(SCHM)完成的。

3.4.5.2 Different Types of NV Blocks

应用程序数据可以存储在NV内存中不同类型的块中。

3.4.5.2.1 Native Blocks

这是标准的块类型。数据只存储在NV区域一次。

3.4.5.2.2 Redundant Blocks

这种类型的目的是在出现错误时增加数据的可用性,即不打算提供额外的错误检测。主要关注写中止,特别是由于电压不足导致的复位。

Note
建议为冗余块配置一种数据完整性机制(例如CRC或MAC)的使用,因为它们提供了足够的错误检测,超出了中止的范围。

用户数据存储在NV区域两次。虽然依赖于较低层(FEE/EA)对中止写访问的检测,NVM确保可读数据块保持可读,即使在写中止的情况下。

为此,在开始写访问之前,NVM检查主NV块和从NV块,以确定适当的写顺序(首先写哪个NV块):如果它检测到一个有缺陷的NV块,它将优先写入一个有效的NV块。如果写入单个NV Block失败,NVM将向DEM报告错误NVM_E_REQ_FAILED(参见3.5.2章)。如果写主NV块(primary NV block)失败,NVM总是以一个消极的作业结果结束请求(a negative job result)。如果主NV块成功写入,则请求总是以正作业结果结束,即使辅助NV块(the secondary NV block)失败也是如此。

Expert Knowledge
NVM不检查任何数据来确定写顺序。相反,它只是检查下层是否能找到有效的数据实例(例如,它们是否成功读取了块的第一个数据字节)。此时,NVM依赖于较低层的中止检测功能。

Note

NVM总是尝试写入两个NV块,而不管下层报告的错误。

即使一个块损坏而另一个块可以读取,读请求也会成功。

擦除或无效请求只有在两个块均被擦除无效时才会成功。

3.4.5.2.3 Dataset Blocks

Expert Knowledge

在写中止之后,数据的“年龄”(“age”)是没有定义的。NVM可以提供以前或最近的数据;事实上,它并没有区分它们。在NVM用NVM_REQ_OK完成结果之前,客户端不能对NV内存中数据的“年龄”进行假设。

一个数据集块可以被看作一个数组。该块的可配置数量的实例存储在NV-memory中。在RAM区域中只有一个RAM缓冲区。适当的NV块实例由所谓的数据索引选择。数据索引可以通过同步API服务NvM_GetDataIndex()NVM_SetDataIndex()读取和设置。

ConceptDescription
Block数据、状态和CRC组成的结构的一般概念。它分布在RAM, ROM和NVRAM上。
NV BlockNVRAM 中的一个块 ,CRC是可选的。
NV Block of
> Native type
> Redundant type
> Dataset type
一种NV Block的类型
RAM BlockRAM中的一个数据块。数据由NVRAM Manager和应用程序共享。例如,应用程序将数据写入此块,并请求NVRAM管理器将其写入NVRAM。
ROM BlockROM中的一个数据块。由应用程序提供的默认数据。
NVRAM Block一个RAM块及其对应的NV和ROM块的逻辑组合。
NV = NVRAM非易失性内存(Non-volatile memory.)。实际上是Flash或EEPROM设备的同义词。

Table 3-4 Block concept

3.4.5.3 Permanent and non-permanent RAM Blocks永久和非永久RAM块

RAM块(应用程序变量application variable)可以是永久的,也可以是非永久的。永久RAM块属于只被一个应用程序访问的NV块。RAM块的地址是固定的,存储在NVM的配置中。

也可以让多个应用程序访问同一个NV块。每个应用程序使用它自己的RAM块。在这种情况下,RAM块被称为非永久块。由于RAM地址没有被存储(并且可能会变化),因此必须给出一个指针来读写一个非永久块

Caution

异步API函数可以由不同的任务重新输入。因此,有可能多个任务同时排队,例如一个写作业(高优先级的任务可能会中断低优先级的任务)。但是不可能对同一个块进行多次排队(既不是通过不同的任务也不是针对不同的作业)。因此,例如,如果块5的读取作业正在排队,则该块的擦除作业在读取作业完成之前无法排队。

如果一个块被多个任务使用(这是非永久RAM块的常见任务),则应用程序负责同步。当然,例如,如果一个擦除请求正在处理中,则可以在不影响擦除作业结果的情况下对RAM块进行读写。唯一的问题是NVM不向应用程序提供任何信息,一个块当前正在处理什么服务。启动该服务的应用程序当然知道,但另一个同样使用该块的应用程序不知道。因此,块访问最安全的方法是,只要RAM块挂起(pending),就不要使用它。这样就可以避免RAM的不一致性。

3.4.5.4 ROM Defaults

ROM默认值可以分配给任何NVRAM块。ROM默认块由应用程序提供。另外,也可以使用初始化回调(参见3.4.14)。这些特性是在配置过程中选择的。只可能配置ROM默认值或块的初始化回调。

ROM默认值可以显式读取(通过调用NvM_RestoreBlockDefaults())。如果由于数据完整性验证错误或由于底层MemHwA通过MEMIF报告的失败,无法从NV-memory中读取有效数据,则在读请求期间也会隐式读取ROM默认值。

如果在读取块的过程中加载了ROM默认数据,结果将是NVM_REQ_RESTORED_FROM_ROM。调用NvM_RestoreBlockDefaults()不会提供结果NVM_REQ_RESTORED_FROM_ROM

3.4.5.5 Data Integrity数据完整性

NvM提供多个策略来确保配置块的数据完整性,即。它可以检查从NV-memory中读取的块数据是否与之前所写的数据相对应。

Note
只有一个数据完整性机制可以一次配置一个块。如果配置不同的数据完整性机制,则需要一个专用策略的附加特性。

如果NvMDataIntegrityIntBuffer被禁用,那么存储数据完整性值(例如CRC或MAC)必须由每个用户提供;否则NVM提供一个内部缓冲区。在本例中,它将用户数据(与NVRAM块与完整性值相关联)复制到内部缓冲区中,而不是直接将它们传递到低层。在这里,数据被添加到完整性值,以保持在一个NV块中,这需要NVM通过一个单个的写入请求传递。

3.4.5.5.1 CRC

对于每个块,可以配置一个可选的CRC校验和。这个校验和可以是CRC16CRC32。校验和将被添加到用户数据中;在NV内存中,它们将被连续存储在一个NV块中。

如果还启用了NvMCalcRamBlockCrc阻塞,NVM将在RAM中内部存储CRC值,以便在NvM_ReadAll处理期间对它们进行检查。如果没有内部缓冲,RAM块中的额外空间就会为此目的服务。

CRC支持是一个AUTOSAR特性。

3.4.5.5.2 MAC

对于每个块,可以配置可选的MAC。由于NvM没有实现任何MAC功能,所以CSM模块用于生成和验证MAC。生成的MAC将被添加到用户数据中,两者都存储在nv内存中的单个块中。

MAC支持是一个非AUTOSAR特性。

在6.2.3中可以找到关于如何配置MAC的更多信息。

Note

当为一个块配置MAC时,有多个特性变得不可用,需要一个不同的数据完整性机制来使用(例如,NvMCalcRamBlockCrc,NvMBlockUseCRCCompMechanismNvMUseBlockIdCheck,需要CRC)。

3.4.6 Prioritized or non-prioritized Queuing of asynchronous Requests优先级或非优先级队

列异步请求

如前所述,异步服务不会立即处理,而是由NvM_MainFunction()异步处理和处理。这需要减少应用程序运行时的运行时间,并增加其持续时间的可预测性(在EEPROM或Flash中同步写工作会使您的任务在一秒钟内阻塞您的任务)。

可以根据用户配置对工作进行排队或优先排序。

如果配置工作优先级,优先级0(直接优先级)到255(最低优先级)可以选择一个块。重要的是,优先级取决于块,而不是请求。多块请求始终具有255的优先级值,即它们的优先级小于最小块的优先级;它们将在所有的singleblock请求完成后处理。

如果不选择块优先级,则工作队列作为一个FIFO缓冲区工作。

3.4.7 Asynchronous Job-End Polling 异步作业轮询

如之前提到的,在后台处理异步请求。应用程序有可能通过调用NvM_GetErrorStatus()来对NVM进行投票。只要工作排队或在过程中,NVM_REQ_PENDING将会返回。一旦工作完成,NvM_GetErrorStatus()将返回工作结果。

3.4.8 Single Block Job End Notifications单块作业结束通知

或者为工作端进行种仲裁,可以实现并配置一个工作结束通知。NvM每次调用该通知,并通过参数对完成的工作和结果进行处理。

函数的返回值被指定,但将不被NVM使用。

3.4.9 Immediate Priority Jobs and cancellation of current Jobs立即优先工作和取消当前工作

正常的优先级块,优先级[1,255],不要取消优先级的工作,NvM将等待工作完成然后将下一项工作从队列中获得最高优先级进行处理。

只有立即优先级的NvM块,必须尽快处理(priority 0)

根据目前的处理状态,可能有以下情况:

  1. NvM不处理任何工作:处理直接优先级(immediate priority job)。
  2. 暂停工作:暂停工作,处理直接优先级的工作,最后重新启动暂停的工作。
  3. 在底层模块处理一个工作:取消底层的工作,处理直接的优先级工作,最后重新启动暂停的工作。

在暂停工作可以重新启动之前,所有直接优先级工作将被处理。NvM对单一和多块工作都是一样的,即在立即优先任务完成后,一项多块作业也将被暂停或重新启动。

Caution
只有优先级大于(0)的块才能被擦除 (使用API NvM_EraseNvBlock)!

3.4.10 Asynchronous CRC Calculation

block的CRC的(re-)calculation计算是由NvM_MainFunction()异步完成的。为了能够分割CRC计算工作,可以通过配置工具对一个周期中计算的CRC字节数进行计算

  • >在块数据写入NV RAM之前,将数据添加到数据中。
  • >在读取块数据后,验证其完整性(重新计算CRC必须匹配存储的CRC)。

Note
如果使用了AUTOSAR符合的CRC库实现,NVM确保所有支持的CRC类型计算值不取决于计算所需的周期数量,即任何计算步骤的任何计算步骤,任何CRC值都保证与计算在相同数据上计算的CRC值相等,并调用适当的库函数。

Breaking Change
在版本7.00.00之前,计算的CRC32不是AUTOSAR兼容的。

这是固定于7.00.00版本的,然而,启用CRC32的现有模块将需要迁移以避免数据丢失。

Note

版本7.01.00引入了一个兼容模式,这使得用旧的CRC32计算读写块成为可能。如果使用兼容模式,新的CRC32计算将完全不使用。要启用此模式,必须在某处使用以下定义

在项目:

#define NVM_CRC32_COMPATIBILITY_MODE STD_ON

请注意,仍然建议尽快迁移使用CRC32的块。这种兼容模式的生命周期有限,可能会在未来的版本中被删除。

3.4.11 Calculate RAM block CRC

为NvM块启用此特性将导致每次在MainFunction(后台)中对BlockChanged值为TRUE的块调用NvM_SetRamBlockStatus()时进行异步CRC重算。

每次调用NvM_SetRamBlockStatus()时请求重新计算RAM CRC的目的是提供重用RAM数据的有效性,即使发生系统重置(短电源丢失,看门狗重置)。NvM假设RAM中的数据比NV RAM中的数据更新

NvM在所有配置中启用了SelectBlockForReadAll和CalcRamBlockCrc的NVRAM块的NvM_ReadAll处理过程中尝试这样做:如果块内部仍然标记为VALID, NvM计算当前RAM块内容的CRC值,并将其与存储在其他地方的值进行比较。如果它们匹配,则不触及RAM内容;相反,NVM假装已经成功地从NV读取了这些值。

NvM在NvM_ReadAll过程中,如果配置SelectBlockForReadAllCalcRamBlockCrc使能,则尝试这样做:

如果块内部仍然标记为VALID, NvM计算当前RAM块内容的CRC值,并将其与存储在其他地方的值进行比较。

如果它们匹配,则不更改RAM内容;相反,NVM会假装已经成功地从NV读取了这些值。(此处翻译不准确)

NvM attempts so during NvM_ReadAll processing for all NVRAM blocks having SelectBlockForReadAll and CalcRamBlockCrc enabled in their configuration: If the block is internally still marked as VALID, NVM calculates the CRC value over current RAM block’s contents and compares it with the value stored elsewhere. If they match it does not touch RAM contents; rather NVM pretends having successfully read those values from NV.

计算RAM块CRC特性可用于配置了永久RAM块(permanent RAM block)或显式(Explicit Synchronization)同步机制的块:

  • 永久RAM保存要计算CRC的最新数据
  • 配置的NvMWriteRamBlockToNvCallback必须提供最新的数据来计算的CRC。

Note

如果一个配置为使用显式同步机制的NvM块使用计算RAM块CRC特性,NvM将使用内部缓冲区通过配置的NvMWriteRamBlockToNvCallback从用户那里获取数据。

这种情况需要发生在块空闲/未请求的时候!

由于NvM计算RAM块CRC并行作业处理,将有两个内部缓冲区!

  1. 一个用于作业处理(也将由显式同步机制使用)
  2. 一个用于计算RAM块CRC特性。

3.4.12 Write Protection

3.4.12.1 Modifiable write protection

NVM支持任意NV Block的写保护。API服务NvM_SetBlockProtection()用于保护和取消保护NV块。初始写保护(复位后)可以配置,它将在NvM_ReadAll()期间设置。

3.4.12.2 Write once protection

有些数据只能存储一次,禁止覆盖。为了实现这一点,NvM为每个NvM块提供写一次配置参数。实际的保护对用户是不可见的且不能被查询,但是NvM将会回复无效请求以拒绝所有写/擦除请求

NvM在ReadAllReadBlock请求时设置的保护如下:

  1. 块可读,数据可用且有效(readable, data available and valid):块已经被写入并且被写入保护。
  2. 块不可读或数据无效(数据完整性验证错误)(not readable or data invalid):没有有效数据可用,该块可以写入。
状态可读性有效性
已写入可读有效
未写入不可读无效

为了初始化写一次块的保护,NvM将会读取所有块,无论它们是否被选择为ReadAll

ReadAll期间需要基于如下配置的的行为:

  1. Write once block被Readall包含:正常读取为ReadAll选择的所有写once块,并设置写保护。错误状态与读取结果匹配。
  2. Write once block没有被Readall包含:对未选择为ReadAll的block读取一个字节的数据,只是根据可读性初始化写保护。错误状态为NVM_REQ_BLOCK_SKIPPED,因为不会提供任何数据。(翻译不准确)

Write once block selected for ReadAll:
Reads all write once blocks selected for ReadAll normally and sets the write
protection. Error status matches the read result.
Write once block not selected for ReadAll:
Reads a byte of the data for blocks not selected for ReadAll, just to initialize the write
protection according to readability.

Caution

对于所有具有写一次保护但未被选择为ReadAll的块,NvM只读取一个字节。因此,即使配置了数据完整性机制,完整性值也不会被验证,块将被标记为写保护,尽管数据可能是无效的。

如果一个写一次块被配置为使用数据完整性机制,那么它应该被选为ReadAll。

成功写入一个不受保护的写一次块后,NvM将该块设置为受保护的。写一次块的写保护不能通过API调用擦除。然而,通过在NvM_ReadAll()期间使用扩展的运行时准备可以重写这样的块(参见[2])。

Caution

  1. 对于配置为写一次的数据集块,只能写一次数据。之后其他数据集不能再写了。第一次写后,整个块被保护。
  2. NvM_KillReadAll请求之后,NvM将不再访问NV RAM。因此,NvM不能验证NV RAM的内容,也不能设置写一次块的写保护—NvM将跳过这些块,并确保它们没有被写保护!块所有者必须通过NvM_ReadBlock读取该块,以便NvM根据NV RAM内容设置写保护。

3.4.13 Erase and Invalidate

有两个指定的服务用于使NV块不可读:NvM_EraseNvBlock()NvM_InvalidateNvBlock()

使块失效比擦除块要快得多,因为只有状态信息会失效。

3.4.14 Init Block Callbacks

对于任何块ROM默认值(参见3.4.5.4)或初始化回调都可以配置。每次必须加载块的默认值时都会调用初始化回调函数,例如,在恢复块默认服务或失败的读作业期间。

该方式与ROM默认值不同,NvM本身不更新RAM数据,RAM的更新会在在初始化回调中完成。

函数的返回值是指定的,但不会被NVM使用。

Note

初始化回调函数会被阻塞相关block,所以在调用期间相关block不可以触发其他请求。

NvM_ReadAll()期间,如果块配置了启用的NvMUseServicePorts,初始化回调将不会被调用。这样做是因为在NvM_ReadAll()期间RTE还没有初始化,回调调用可能会导致DET错误。

如果禁用NvMUseServicePorts,回调函数将在NvM_ReadAll()期间被调用,没有任何限制。

3.4.15 Protect and validate NV data

在某些情况下,用户可能想要在写入或从NV RAM读取数据之前转换数据:例如,用户可能想要实现自己的CRC或MAC,加密或解密并验证数据或实现旧数据检测。

在这种情况下,用户可以配置两个数据转换回调函数:

  1. 预写转换(pre-write transformation:):在将数据写入NV RAM之前直接调用,然后NvM将转换后的数据写入NV RAM。
  2. post-read转换(post-read transformation):从NV RAM读取数据后调用。NvM将把转换后的数据转发给用户。如果这个函数的返回值是E_NOT_OK, NvM将认为读作业不成功。

Caution

在这两种情况下,用户都要对正确的数据长度负责。转换回调不能更改配置的数据长度。如果需要存储额外的数据,例如CRC值,用户必须相应地配置NvM块长度,并提供足够大的缓冲区来存储所有所需的数据。

Note

  1. 读后转换并不总是可能的:如果读作业失败,则不会调用回调。
  2. 转换只能成对配置:要么两个回调都配置,要么一个都不配置。

3.4.16 Define Locking/ Unlocking Services

在抢占系统中,有必要对某些抢占行为进行保护。这意味着一些NVM内部操作需要是原子的。因此,为了保护这些序列,可以配置进入和离开这样一个临界区的函数。默认使用操作系统服务(OS)。

配置工具可以定义或配置服务,如OSEK服务GetResource(…)和ReleaseResource(…),以锁定和解锁资源。要使用操作系统的这些服务,你还必须通过配置工具发布操作系统的头文件(在’ MyECU ‘窗口和包含的’ OS services '选项卡中)。

3.4.17 Interrupts

当写访问期间发生中断时,它们不会损坏已经保存的数据或要写入的数据。为了确保这一点,这些关键部分必须被锁定,这可以通过配置工具进行配置。

3.4.18 Data Corruption

对非易失性内存的写操作是非原子操作。写访问过程中电源故障可能导致数据损坏/无效。确保损坏的数据不会被当作有效的信号不再是NVM的任务,而是FEE或EA的任务。

3.4.19 Concurrent access to NV data for DCM/DCM对NV数据的并发访问

NVM提供了通过NVM的应用程序并发访问NV数据的可能性。因此,每个配置的NVRAM块都有一个额外的别名,即“DCM块”(“DCM block”)。

别名与普通NvM块有以下区别:

  1. 别名具有与源NvM块相同的配置(例如CRC或长度)
  2. 别名被视为没有永久RAM块的NVRAM块(without permanent RAM block)
    • 别名在启动时(在NvM_ReadAll处理期间)不会被读取,在关闭时(在NvM_WriteAll处理期间)也不会被写入
    • 显式读或写请求必须提供对临时RAM块的引用
    • NvM_SetRamBlockStatus的调用对别名没有任何影响
  3. 一个别名的异步请求一次只能排队
  4. 如果一个已经在队列中,请求将被拒绝(API返回E_NOT_OK)
  5. NvM_GetErrorStatus适用于所有别名,无论给函数的是哪个别名ID。
    • 对于所有别名只有一个作业结果,该作业结果在请求下一个别名之前有效
  6. NvM_SetDataIndexNvM_GetDataIndex适用于所有别名,无论给函数的别名ID是什么
  7. NvM_SetBlockProtection适用于所有别名,无论给函数的别名ID是什么

DCM的所有作业总是放在标准作业队列中,即使请求的Block具有立即优先级也要同样处理。因此尽量避免对immediate DCM-Block进行 DCM操作,这样才能保留原有的优先级;

为了访问一个NVRAM块的别名,NVM提供了全局宏NvM_GetDcmBlockId(<NvMBlockId>),它期望源NVRAM BlockId作为参数,并返回类型为NvM_BlockIdType的块别名。

Note

建议DCM只通过别名访问NVRAM数据。否则DCM将负责与每个NVM客户端(块的所有者)进行同步。

Caution

DCM应该在请求作业(通过别名,特别是写请求)之前使用NvM_SetBlockLockStatus(参见5.4.8章)锁定块。如果在作业处理期间出现错误,DCM也应该再次解锁块。如果作业处理成功完成,块应该保持锁定;它将在下次启动后自动解锁(NvM_ReadAll处理)。

锁本身只影响原始块(即别名不能被锁定)。

3.4.20 Explicit synchronization mechanism between application and NVM 应用程序和NVM

之间的显式同步机制

NvM支持应用程序和NvM之间的显式同步机制。它是通过NvM模块中的RAM镜像实现的。应用程序通过NvM模块调用的回调函数双向传输数据。

同步机制可以为每个NVRAM块单独配置。如果配置了同步机制,NvM使用内部缓冲区作为NvM和应用程序之间的RAM镜像。它与用于数据完整性计算的内部缓冲区是相同的(参见4.4.5.1章)。内部缓冲区的大小是最大的配置块的大小加上配置的数据完整性记录的大小(例如CRC或MAC)。

如果配置了同步机制,则必须同时配置NvMWriteRamBlockToNvMNvMReadRamBlockFromNvM

为使用同步机制的块配置永久RAM块是没有用的。在这种情况下,RAM块将被忽略。也不建议使用同步机制为块配置Init回调。

Note
如果为块配置了显式同步,客户端可以在块挂起时修改RAM内容(NVM不可见)。在这种情况下,要注意当挂起的读取完成时,它们可能会被覆盖。

Basic Knowledge
根据定义,该机制充当永久RAM块。

Expert Knowledge

计算RAM CRC和在NvM_ReadAll处理期间对RAM数据的相关快速重新验证不能与显式同步机制一起使用。

3.4.20.1 Explicit synchronization mechanism during write requests 写请求期间的显式同步机制

在应用程序发出NvM_WriteBlock之后,应用程序可能会修改内存块,直到NvM调用回调函数NvMWriteRamBlockToNvM为止。如果调用NvMWriteRamBlockToNvM,应用程序必须向内部RAM镜像提供一个一致的RAM块副本。

Note
在调用NvMWriteRamBlockToNvM回调时,相关块仍然繁忙。只要block忙,就不会发出请求。

3.4.20.2 Explicit synchronization mechanism during read requests 读请求期间的显式同步机制

在应用程序发出NvM_ReadBlock之后,应用程序可能会修改内存块,直到NvM调用NvMReadRamBlockFromNvM函数。如果调用了NvMReadRamBlockFromNvM,那么应用程序必须将数据从内部内存镜像复制到内存块。

Note
在调用NvMReadRamBlockFromNvM回调时,相关块仍然繁忙。只要block忙,就不会发出请求。

3.4.21 CRC Compare Mechanism

为了避免在NV内存中进行不必要的写操作,如果在运行时没有更新特定RAM块的NV数据,NvM模块提供了一种基于CRC的比较机制,可以应用于写操作中。

这意味着,在写入数据到NV内存之前,NvM重新计算当前数据的CRC,并将该值与之前读取或写入数据(存储在RAM中)的CRC进行比较:

  • CRC的数值一致,则NvM会假设数据没有被更改(是最新的NV内存),不会对block进行写入操作,并且回复成功写完成的状态;
  • CRC的数据不一致,NvM假设数据已更改(不是最新的NV内存),并将数据写入NV RAM。

在某些情况下,NvM也将进行写操作,及时RAM内容没有改变(CRCs匹配):

  • 前一次读取失败
  • 先前写失败
  • 先前的写入导致了**冗余的丢失(**参见第0章)
  • 以前该块无效或已删除
  • 以前恢复默认数据(显式通过API,或在读取请求失败时隐式恢复)。

NvM实现的CRC比较机制特性偏离了AUTOSAR [2]: CRC比较机制不依赖于Calc Ram块CRC特性,两种特性都使用自己的CRC缓冲区。

NvM_SetRamBlockStatus导致在后台重新计算CRC。NvM保存拟合到当前内存内容的CRC,并在NvM_ReadAll期间使用CRC以避免从NV RAM读取数据(参见3.4.10章)。

CRC比较机制:NvM保存了上一次成功读取或写入的CRC, CRC与NV RAM内容匹配。CRC将用于避免向NV RAM写入(NvM_WriteBlock, NvM_WriteAll)。

该机制可以通过NvMBlockUseCRCCompMechanism对NvM块启用。

Caution

  1. 对于不同的数据计算相同的CRC值是有可能的。在这种情况下,NvM将不会写入,并且NV内存内容与RAM内容不同步——用户必须能够操作过时的数据(例如在关机和启动后)。
  2. 仍然需要使用NvM_SetRamBlockStatus函数,在WriteAll期间,NvM只会检查CRC,如果块状态是有效的并且已经改变——NvM_SetRamBlockStatus被调用为“true”。
  3. 该特性不仅影响NvM_WriteAll,其中写取决于RAM块状态,还影响NvM_WriteBlock作业——如果启用CRC比较机制,如果CRC匹配NvM_WriteBlock将不会写。在禁用CRC比较机制的情况下,NvM_WriteBlock总是写入数据
  4. 如果启用了NvMBlockUseCRCCompMechanism,多个数据集的相同数据不会被写入,因为在第一个数据集写入之后,CRC与数据匹配,NvM跳过写入NV RAM。如果需要写入,跟进章节3.1.1.1块Id检查特性。
3.4.21.1 Redundant blocks 冗余模块

在写入Native Block 或 dataset block 之前,NvM比较CRC并决定是否需要写入NV RAM。对于冗余块(redundant block ),扩展了处理以确保NV RAM中的数据冗余:NvM将首先检查后续两个块的可读性,然后根据它们的可读性进行相应的操作:

可读性操作
2块可读使用CRC比较机制,行为与其他块类型相同。
1块不可读跳过CRC比较机制,直接进行数据写操作。
2块不可读跳过CRC比较机制,直接进行数据写操作。

Note

NvM永远不会比较数据或检查其内容:可读数据意味着有效数据,尽管它可能过期。

3.4.22 Check loss of redundancy 冗余损失校验

配置选项NvMCheckLossOfRedundancy可以为配置了数据完整性机制的所有冗余块启用每个块。如果对一个块使用该特性,则在读取请求时将检查块的两个数据实例的一致性。

如果它们的数据完整性记录不相等(即数据不再冗余)或其中一个子块有缺陷,则将调用NvM/NvMCommon/NvMDetectedLossOfRedundancyCallback中指定的函数。回调函数中包含了受影响块的ID,因此可以以每个块为单位推导出操作。如果至少有一个实例是有效的,那么作业的结果仍然是成功的,只会在此基础上再调用回调函数。

检测到部分冗余丢失,但是仍有有效数据可用,则该块的作业结果为NVM_REQ_OK。如果想要恢复块的冗余,必须确保块会被写入(NvM_WriteBlockNvM_SetRamBlockStatus)。在没有数据可以读取的情况下,此功能没有影响。

Note

  1. 该功能可以被认为是API NvM_RepairRedundantBlock的替代方案。另外要记住,这些特性之间没有协同效应。
  2. 由于检测冗余数据丢失的机制是通过验证数据的数据完整性记录来实现的,因此该特性仅在对配置的块启用数据完整性机制时才有效。
  3. 启用此功能将对读取性能产生负面影响,性能的影响效果主要这取决于内存镜像中的错误数量。
  4. 该功能的回调函数会在排队的任务完成之前执行。由于写操作会使得当前状态为NVM_REQ_PENDING,因此,在写得过程中无法进行冗余校验。

3.4.23 Ciphering interface 加密接口

出于安全目的,NvM支持通过CSM模块使用16字节对齐的对称算法(如AES128)进行同步加密和解密操作。

用户总是处理纯数据,NV RAM存储加密数据:

  1. 写数据:NvM对明文用户数据进行加密后,再转发给设备。
  2. 读取数据:NvM从设备读取加密数据,解密数据,最后将明文数据提供给用户。

为了验证加密数据的完整性(integrity),可以配置数据完整性机制。然后,NvM将根据加密数据计算数据完整性记录,并在解密之前重新计算和验证完整性记录:数据完整性记录始终与加密数据匹配。

如果完整性检查失败,NvM不会解密数据,而是中止NVM_REQ_INTEGRITY_FAILED任务。

Caution

不推荐同时使用NvMCalcRamBlockCrc数据加密:

(1)当调用NvM_SetRamBlockStatus时,NvM将在后台计算CRC。此时,NvM只知道用户数据,因此计算用户数据的CRC。

(2)实际的CRC将在稍后的写请求期间对加密数据进行计算。——

以上两个数据不同(尽管用户数据没有改变),可能导致NvM再次从NV RAM读取加密数据。

3.4.23.1 CSM usage

由于NvM目前只支持同步加密和解密,因此NvM直接依赖于Csm_EncryptCsm_Decrypt的结果。

为了避免频繁的读、写作业的操作,NvM支持重试机制(retry mechanism)

CSM结果及相关NvM处理如下:

CSM的工作结果(Return code)NvM操作
CSM_E_OKNvM继续处理作业。读取和写入(解密和加密)的行为是相同的。
CSM_E_BUSY、CSM_E_QUEUE_FULLNvM尝试在下一个主函数周期中重试CSM任务。超过重试次数将导致作业失败和NvM结果NVM_REQ_NOT_OK。具体请参见3.4.23.2.2。
All other return codesNvM将其归类为错误。这将导致作业结束,NvM结果为NVM_REQ_NOT_OK。
CSM返回的结果长度不匹配(参考3.4.23.2)NvM将其归类为错误。这将导致作业结束,NvM结果为NVM_REQ_NOT_OK。

Table 3-5 NvM – CSM job result mapping

存储加密数据NvM使用独立的内部“CSM缓冲区”(另一个用于例如显式同步机制3.4.20):

  • 加密:输入缓冲区是用户数据缓冲区(由用户提供,或者NvM内部缓冲区),输出缓冲区是“CSM缓冲区”,
  • 解密:输入缓冲区是“CSM缓冲区”,输出缓冲区是用户数据缓冲区(由用户或NvM内部缓冲区提供)。

Caution
根据配置和NvM作业的设置,NvM可以直接将用户缓冲区传递给CSM模块,以便将解密数据存储在其中。

如果CSM作业失败,NvM不保证缓冲区内容准确性,因为在CSM或加密过程中,可能会在失败前就已经更改内容了。

3.4.23.2 Configuration
3.4.23.2.1 Block configuration

对于每个NvM块,必须配置以下参数:

  • NvMCsmEncryptionJobReference:对CSM加密作业的引用
  • NvMCsmDecryptionJobReference:对CSM解密作业的引用
  • NvMNvBlockNVRAMDataLength:加密后和解密前的数据大小(存储在NVRAM中的数据大小)。

Note

NvMNvBlockLength标记用户数据的长度

NvMNvBlockNVRAMDataLength标记NV内存数据的长度,在这里是加密数据的长度。加密数据的结果长度必须与此值匹配(参见3.4.23.1)。由于支持16字节对齐算法,NvM假设此长度为对齐的NvMNvBlockLength甚至更高。

最高的NvMNvBlockNVRAMDataLength +数据完整性记录的长度将被用作内部“CSM缓冲区”的大小。

3.4.23.2.2 General configuration

NvMCommon配置容器中,参数NvMCsmRetryCounter可以是配置。此参数将用于限制由于CSM繁忙状态而被拒绝的CSM作业的重试尝试的最大次数。

将该参数设置为0意味着:错误情况下没有重试行为——作业将直接终止

3.5 Error Handling

3.5.1 Development Error Reporting

默认情况下,如果启用了开发错误报告(DET)(即预编译参数NVM_DEV_ERROR_DETECT == STD_ON),则使用[3]中指定的服务Det_ReportError()将开发错误报告给DET。

报告的NVM ID可以在[第2章]中看到。

Service IDService
0x00NvM_Init()
0x01NvM_SetDataIndex()
0x02NvM_GetDataIndex()
0x03NvM_SetBlockProtection()
0x04NvM_GetErrorStatus()
0x05NvM_SetRamBlockStatus()
0x06NvM_ReadBlock()
0x07NvM_WriteBlock()
0x08NvM_RestoreBlockDefaults()
0x09NvM_EraseNvBlock()
0x0ANvM_CancelWriteAll()
0x0BNvM_InvalidateNvBlock()
0x0CNvM_ReadAll()
0x0DNvM_WriteAll()
0x0ENvM_MainFunction()
0x0FNvM_GetVersionInfo()
0x10NvM_CancelJobs()
0x13NvM_SetBlockLockStatus()
0x14NvM_KillWriteAll()
0x15NvM_RepairRedundantBlocks()
0x16NvM_KillReadAll()

Table 3-6 Mapping of service IDs to services

报告给DET的错误如下表所示:

Error CodeDescription
0x14NVM_E_NOT_INITIALIZED除了 NvM_Init() and NvM_GetVersionInfo(), 其他NVM的API接口都会检测是否初始化
0x15NVM_E_BLOCK_PENDING只要对某个块的异步操作没有完成,就不允许进一步请求属于该块。
0x18NVM_E_BLOCK_CONFIG此配置无法提供此服务。
0x0ANVM_E_PARAM_BLOCK_IDNVM API服务可能会检查传入的BlockId是否在允许的范围内。
0x0BNVM_E_PARAM_BLOCK_ TYPENvM_SetDataIndex()NvM_GetDataIndex()仅限于数据集块(Dataset bocks)
如果用任何其他块类型调用这些函数,则会产生此错误码。
0x0CNVM_E_PARAM_BLOCK_DATA_IDXNvM_SetDataIndex()可以检查传入的DataIndex的范围。
0x0DNVM_E_PARAM_ADDRESS传递了错误的指针参数。(异步调用中传递的NULL_PTR,例如用于非永久块的NvM_WriteBlock())
0x0ENVM_E_PARAM_DATA在同步函数NvM_GetDataIndex()NvM_GetErrorStatus()nvm_getversioninfo()中传入了NULL_PTR。

Table 3-7 Errors reported to DET

3.5.1.1 Parameter Checking

AUTOSAR要求API函数检查其参数的有效性。表3-8中的检查是API函数的内部参数检查。

下表显示了对哪些服务执行哪些参数检查:

Service初始化状态Blcok 类型Pending状态Block IdDataIndex 类型数据指针
NvM_Init()
NvM_SetDataIndex()
NvM_GetDataIndex()
NvM_SetBlockProtection()
NvM_GetErrorStatus()
NvM_GetVersionInfo()
NvM_SetRamBlockStatus()
NvM_SetBlockLockStatus()
NvM_ReadBlock()
NvM_WriteBlock()
NvM_RestoreBlockDefaults()
NvM_EraseNvBlock()
NvM_CancelWriteAll()
NvM_InvalidateNvBlock()
NvM_ReadAll()
NvM_WriteAll()
NvM_MainFunction()
NvM_CancelJobs()
NvM_RepairRedundantBlocks()
NvM_KillWriteAll()
NvM_KillReadAll()

Table 3-8 Development Error Checking: Assignment of checks to services

3.5.2 Production Code Error Reporting

NvM检查并报告以下错误代码给DEM:

Error CodeDescription
NVM_E_INTEGRITY_FAILEDAPI请求完整性失败
NVM_E_REQ_FAILEDAPI请求失败
NVM_E_WRITE_PROTECTEDNvM_WriteBlockNvM_EraseNvBlockNvM_InvalidateNvBlock检查指定BlockId的块是否在写入(或擦除或失效)之前被写保护。
NVM_E_QUEUE_OVERFLOW所有异步请求只有在队列未满时才能进入队列。
NVM_E_LOSS_OF_REDUNDANCY冗余块中的单个块无效。

Table 3-9 Errors reported to DEM

根据AUTOSAR组件特定的DEM错误码必须在DEM中进行配置,从而使得NvM的配置可以引用它们。

为了向DEM报告生产错误,NvM必须使用通过DEM .h发布的Dem_ReportErrorStatus 的API(如果NvM引用了DEM错误码)。NvM使用配置的错误码调用DEM API,状态为DEM_EVENT_STATUS_FAILEDNvM不会使用DEM_EVENT_STATUS_PASSED状态

Caution
如果没有引用DEM, 则NvM不会输出DEM的报告。

如果需要任何DEM错误报告,NvM错误码必须指向一个DEM错误码。

3.5.3 Compile-time Block Length Checks

对于每个具有永久RAM或ROM的块,NvM提供块长度检查,以确保配置的块长度和永久RAM /ROM的长度相互匹配。

永久内存(permanent RAM)有三种不同的检查方式:

  • 启用自动块长度(参见3.1.2)(Automatic Block Length):永久内存的大小不能超过配置的块长度
  • 严格块长度(Strict Block Length):配置的块长度必须与永久内存的大小完全匹配
  • 非严格块长度(Non-strict Block Length):配置的块长度不能超过永久内存的大小

永久ROM(permanent ROM)

  • 非严格块长度:配置的块长度不能超过永久ROM的大小

Basic Knowledge

为了在编译时检查块长度,NvM使用位字段必须被初始化为正值length

一旦初始化为负长度(块长度检查失败),将发生编译器错误并标记相应的行。

每个长度检查都显示了所有必需的信息:块名、内存符号和块的错误(取决于严格、非严格或自动块长度的长度类型)

4 Integration 整合与集成

本章提供了将MICROSAR NVM集成到ECU应用环境的必要信息。

4.1 Embedded Implementation 嵌入式集成

NvM的交付包含这些源代码文件:

文件名描述
NvM.cNVM文件源码
NvM.hNvM的头文件。定义NVM的接口。应用程序/用户只能包含此文件。
NvM_Act /
NvM_Crc /
NvM_JobProc /
NvM_Qry /
NvM_Queue.c/ *.h
NvM_IntTypes.h
这些文件是NvM内部使用的。应用程序/用户不能访问它们。
NvM_Cbk.h包含在禁用轮询模式时由基础设备抽象调用的回调函数的声明。
NvM_Types.h包含公共的NvM类型和它们的值(作为宏),例如请求结果。
此文件不打算被用户/应用程序包含。然而,如果在某些情况下需要,可以直接包括在内。
NvM_Cfg.c这是一个生成的包含NvM配置的源文件,例如配置的块(Block ID)。
NvM_Cfg.h这是一个生成的头文件,包含公共配置参数。该文件将包含在NvM.h中,因此提供给应用程序/用户
NvM_PrivateCfg.h这是一个生成的头文件,其中包含私有配置参数。

4.2 Critical Sections临界段

为了保护关键代码免受中断,NvM使用以下关键段:

NvM_NVM_EXCLUSIVE_AREA_0

4.3 Compiler Abstraction and Memory Mapping编译器抽象和内存映射

对象Object (例如变量、函数、常量)由编译器独立的定义声明。每个编译器抽象定义都分配给一个内存段(memory section)。

下表列出了NVM的内存段名称和编译器抽象定义,并说明了它们之间的关系。

image-20221108152735597

Table 4-2 Compiler abstraction and memory mapping

对于每个开始关键字,都有一个停止关键字。由于这些停止关键字用于恢复默认部分,因此不需要配置停止关键字。

上面列出的节关键字依赖于编译器。它们设置在文件MemMap.h和Compiler.h/Compiler_Cfg.h中。编译器的编译语可用于打开和关闭特定的内存段。

Note
集成必须确保特定部分的相关设置(#pragmas)涵盖特定部分中定义的所有变量。

(可能需要编译器进一步划分变量,例如按类型/大小/对齐要求)。

4.4 Dependencies on SW Modules对SW模块的依赖

4.4.1 OSEK / AUTOSAR OS

除非用于中断或资源锁定问题,否则不需要操作系统环境

4.4.2 DEM

NvM向DEM报告运行时错误。更多信息请参见3.5.2章。

4.4.3 DET

模块DET:可以在开发模式下使用。它记录了所有开发错误,以供评估。它的使用可以通过开关开发错误报告的配置工具启用/禁用。

4.4.4 MEMIF

NVM使用MEMIF定义的配置参数

4.4.5 CRC Library

对于CRC计算,NVM使用AUTOSAR兼容的CRC库提供的服务。

Note
由于配置Id块必须配置为CRC16或CRC32。你将始终需要CRC库。

4.4.6 Callback Functions

MICROSAR NVM提供了通知的用法(callback),这些通知可以映射到其他模块提供的回调函数,以便通知它们作业完成。对于每个NVRAM块,可以根据应用定义一个单独的回调函数。这些回调函数声明必须在应用程序中声明,并且要包含在NVM中

4.4.7 RTE

当至少启用一个服务端口(Service Port)并提供相应的PIM(参见RTE的技术参考)时,将自动包含所有其他必要的头文件。SWC不能包含NvM.h

4.4.8 BSWM

如果启用了开关BSWM多块作业状态信息(BSWM Multi Block Job Status Information),NVM将通过BswM_NvM_CurrentJobMode()通知BSWM多块作业的当前状态。多任务回调不会被调用

Note
在调用BswM_NvM_CurrentJobMode()期间,如果调用状态为NVM_REQ_PENDING,则与回调相关的块仍然繁忙。只要block pending,就不会发出请求。

如果单个块的开关BSWM块状态信息为true, NVM应通过BswM_NvM_CurrentBlockMode()通知BSWM块的当前状态。

4.4.9 CSM

NvM使用CSM来启用不同的特性

  • 加密:对于加密,CSM用于在写入数据之前加密数据,在读取数据之后解密数据:NV RAM存储加密数据,用户使用明文数据。更多信息请参见3.4.22章

  • MAC:为了实现MAC作为数据完整性机制,使用CSM来生成和验证MAC。更多信息请参见3.4.5.5.2章。

4.5 Integration Steps配置步骤

要将MICROSAR NVM集成到你的系统中,从配置开始,需要完成以下几个步骤:

  1. 使用MICROSAR配置工具或GCE编辑器,根据应用需求配置MICROSAR NVM和MICROSAR MEMIF。
  2. 生成模块NVM和MEMIF的配置文件。
  3. 为FLS/EEP配置和生成较低的FEE/EA模块和驱动模块。
  4. 如果使用了非Vector交付的FEE或EA模块,请确保两个模块之间交换的参数是一致的。
  5. 每个应用程序负责使其RAM和ROM块可用(不要使用static修饰符!)。MICROSAR NVM包含声明这些块的文件,并定义内存修饰符来寻址这些块。这个内存修饰符可以在Compiler.h中修改。
  6. 确保所有使用MICROSAR NVM的应用程序都包括Std_Types.h和NVM .h
  7. 检查驱动程序的初始化FLS/EEP, FEE/EA和MICROSAR NVM(MICROSAR NVM不初始化任何其他模块)。
  8. 请确保初始化顺序正确。FEE/EA和FLS/EEP必须在使用任何NVM请求(通常是NvM_ReadAll())之前初始化。注意FEE/EA的初始化序列必须完成,直到FEE/EA能够接受NvM的工作。如果Fee_MainFunction调用和/或Fls_MainFunction调用是完成FEE/EA初始化过程所必需的,则调用必须在NvM向FEE/EA请求第一个任务之前执行。
  9. 确保NVM、FEE/EA和FLS/EEP驱动程序的主要功能(main functions)是循环调用的。这必须在以足够优先级运行的应用程序任务中完成(以避免饿死)。
  10. 确保正在等待的进程释放CPU,使其等待的操作能够完成!
  11. 最后:编译你的MICROSAR NVM并将其链接到你的项目中。

4.6 Estimating Resource Consumption资源消耗评估

除了使用NVM时需要的资源之外,还有一些配置选项会影响系统的资源消耗。通常,这些选项对NVRAM使用的影响与配置的NVRAM块的数量无关。此外,每个NVRAM块分别需要RAM、ROM和NV中的资源。下面的小节将总结这些选项并给你提示,如何估计它们的效果。

4.6.1 RAM Usage

一般来说,每个NVRAM块都会消耗RAM——无论是应用程序定义的RAM块,还是内部的块管理结构,后者保存了有关请求结果、块的属性及其当前数据索引的信息。内存块本身占用的内存数量应该等于配置的长度。然而,实际的大小取决于应用程序声明的对象(变量)的大小。当前每个管理区域的大小是3字节

然而,尽管在评估RAM消耗时需要考虑它们,但从技术上讲,RAM块属于NVM的客户端。

影响内存消耗的配置与队列的大小和作业优先级有关。一个队列项的长度取决于目标平台和所用的编译器配置。它的范围从8字节(16位平台、16位指针)到12字节(32位体系结构、对齐结构成员)。

此外,设置NvMDataIntegrityIntBuffer会影响RAM的使用率:

​ 如果启用,NVM会在内部分配一个RAM缓冲区。其大小至少是配置了数据完整性机制的最大NVRAM块的大小,包括最大数据完整性记录的大小。使用NvMBlockUseSyncMechanism机制配置的NVRAM块的大小也会在计算内部缓冲区的大小。

此外,如果一个块配置了数据完整性机制(data integrity mechanism),并且启用了NvMDataIntegrityIntBuffer,则会为该块创建一个与数据完整性记录大小相同的额外缓冲区。

4.6.2 ROM Usage

因为每个NVRAM块的配置都会编译为一个常量块描述符,所以所需的ROM也会受到已配置NVRAM块总数的影响。同样,描述符的大小因目标平台和所使用的编译器选项而异。

有一些配置选项会影响NVM代码大小如下所示:

  1. Development mode
  2. API configuration class
  3. use Version Info API
  4. use Set Ram Block Status API

NVM的ROM使用不包含默认ROM的块。和任何回调函数一样,ROM默认块(定义默认数据)属于NVM的客户端。

4.6.3 NV Usage

每个设备对NV内存空间的要求受NVRAM块及其配置的影响。基本上,每个NV块分配了与其长度相同的字节数,加上数据完整性字节数(如果配置过)。底层组件(FEE或EA)还将添加内部管理信息,以及填充字节,以满足NV内存设备的对齐要求。

根据NVRAM块的管理类型,它由一个或多个块组成

NV消耗空间如下:

Block TypeNV usage
Native1 NV Block
Redundant2 NV Block
DatasetN NV Block

4.7 How-To: Integrate NVM with AUTOSAR3 SWC’s 如何集成SWC

ASR4 NVM嵌入式接口与ASR3不兼容;特别是返回类型已经改变。然而,RTE封装了所有的操作:如果SWC调用C/S接口(C/S-Interface)的操作(通过RTE),它总是会得到Std_ReturnType。最后,现有的嵌入式代码(SWC和NVM本身)无需修改就可以针对这些改变的接口进行编译。

但是,为了实现这种嵌入式兼容性,在AUTOSAR服务之间,SWC-descriptions(指导RTE生成器,如何创建兼容的代码)略有不同。为了同时使用AUTOSAR4 BSW和AUTOSAR3 SWC,用户必须调整其客户端的接口引用。

4.7.1 NVM’s provided Interfaces/Ports NVM的提供的接口/端口

客户端SWCs使用的每个接口都需要重新映射

4.7.1.1 NvMAdministration Nvm管理

SetBlockProtection是使得状态从POSSIBLE-ERRORS()变成了POSSIBLE-ERRORS(E_NOT_OK)的唯一方式。

该定义可以在R-Port端口端交换,因为由于RTE API,嵌入式软件已经使用了Std_ReturnType(和E_OK/E_NOT_OK)进行状态返回,因此SWC的代码需要对返回值进行检查。

但是,如果开启了错误检查功能,则如上的操作只会返回错误。

4.7.1.2 NvMService_AC[1|2|3][_SRBS][_Defs]

命名方法请参见6.1.4

以下操作可能改变返回类型(POSSIBLE-ERRORS):

  1. GetErrorStatus
  2. GetDataIndex
  3. SetDataIndex
  4. SetRamBlockStatus

Note
如果“开发错误检测”被禁用,NvM_SetDataIndexNvM_GetDataIndex可能会失败。

与NvMAdministration接口类似,客户端的R-Port端口原型必须与这些接口关联。

4.7.2 Callbacks (Ports provided by client SWCs)回调接口

实际上,从AUTOSAR3到AUTOSAR4,回调规范并没有改变。然而,最近DaVinci Developer和RTE Generator添加了一个功能,允许在建模的过程中增加回调函数。关于回调模型(SWC’s P-Ports)与其RUNNABLE的原型之间的关系,请参阅第6.1.5章。

4.7.3 Request Result Types请求结果类型

在AUTOSAR4中,为NvM_RequestResultType定义了新的值,即NVM_REQ_REDUNDANCY_FAILED。但由于未指定实际用途,NVM不会使用它。它的接口描述中省略了它,客户端不需要处理它。

NvM使用NVM_REQ_RESTORED_FROM_ROM来表示在NvM_ReadBlock()NvM_ReadAll()期间加载的默认ROM数据。对于AUTOSAR3,这个作业结果可以通过以下两种不同的方式映射:

  1. 在数据正常应使用时,将返回请求状态为NVM_REQ_OK。在这种情况下,应用程序不需要知道是否配置了默认数据。
  2. 如果操作失败,即NVM_REQ_OK以外的所有结果。在这种情况下,NvM将加载默认数据(当配置时)。因此,应用程序可以对这种情况实现特殊处理。

5 API Description API 描述

5.1 Interfaces Overview 接口介绍

有关接口概述,请参见图 2-3。

5.2 Definitions 定义

返回数据的定义如下表所示:

Type NameC-TypeDescriptionValue Range
NvM_RequestResultTypeuint8        异步API服务可以有以下结果或状态,
可以由NvM_GetErrorStatus()轮询查看状态
NVM_REQ_OK
最后一个异步请求已经成功完成。
这是重置后的默认值。
该状态的值为0。
可以由所有异步API均可以返回。
NVM_REQ_NOT_OK
最后一个异步请求不成功。
所有异步处理的API均可以返回。
NVM_REQ_PENDING
异步请求已经排队(队列繁忙)
所有异步处理的API均可以返回
NVM_REQ_INTEGRITY_FAILED
一个NV块应该是有效的,但结果是数据被损坏。
可能是据完整性验证失败,或者FEE或EA报错。
NvM_ReadBlock或NvM_ReadAll返回该状态。
NVM_REQ_BLOCK_SKIPPED
在多块请求期间跳过块
NvM_ReadAll和NvM_WriteAll返回该状态。
NVM_REQ_NV_INVALIDATED NV
块被标记为无效可以通过
NvM_ReadBlock或NvM_ReadAll返回该状态。
NVM_REQ_CANCELLED
上次的异步NvM_WriteAll()已经被NvM_CancelWriteAll()取消了。
NVM_REQ_RESTORED_FROM_ROM
对NV块的读取导致将默认数据加载到RAM映像。
可以通过NvM_ReadBlock()或NvM_ReadAll()下发。
NvM_ReadBlock() or
NvM_ReadAll().
NvM_BlockIdTypeuint16它是应用程序用来访问NVM块的块句柄的类型。
有两个保留的id:
{
[0. .2𝑛 [, ]215. . 215 + 2𝑛 [,
𝑛 = 16 − NVM_DATASET_SELECTION_BITS
}
块ID 0用于多块请求
(块ID 0只允许用于API NvM_GetErrorStatus()),
块ID 1 用于配置ID块
NVM_DATASET_SELECTION_BITS
是存储最大数据集值所需的最大位数。
第二个范围描述了每个数据块的DCM别名。
块ID 0没有这样的别名。
块句柄创建在一个升序的define链表中,
可以在NvM_Cfg.h中找到。
示例:
数据集数量最多的数据集块有6个数据集。
因此有必要存储数据索引0…5以选择合适的数据集块。
要存储值5,需要3个比特位。
所以NVM_DATASET_SELECTION_BITS的值为3。
只有块id 0…8191可以作为块句柄。
此外,NVM通过句柄32768+1…32768+8191
提供了对这些id的块别名的访问
定义模式:
NvMConf_NvMBlockDe scriptor_
NvM_ServiceIdTypeuint8NVM不同服务例程的Service id。NVM_INIT (0u)
NVM_SET_DATA_INDEX (1u)
NVM_GET_DATA_INDEX (2u)
NVM_SET_BLOCK_PROTECTION (3u)
NVM_GET_ERROR_STATUS (4u)
NVM_SET_RAM_BLOCK_STATUS (5u)
NVM_READ_BLOCK (6u)
NVM_WRITE_BLOCK (7u)
NVM_RESTORE_BLOCK_DEFAULTS (8u)
NVM_ERASE_BLOCK (9u)
NVM_CANCEL_WRITE_ALL (10u)
NVM_INVALIDATE_NV_BLOCK (11u)
NVM_READ_ALL (12u)
NVM_WRITE_ALL (13u)
NVM_MAINFUNCTION (14u)
NVM_GET_VERSION_INFO (15u)

Table 5-1 Type definitions

NvM_RequestResultType 对应的宏定义如下所示,在NvM_Types.h文件中

# define NVM_REQ_OK                 (0u)  /*!< The last asynchronous request has been finished successfully. */
# define NVM_REQ_NOT_OK             (1u)  /*!< The last asynchronous request has been finished unsuccessfully. */
# define NVM_REQ_PENDING            (2u)  /*!< An asynchronous request is currently being processed. */
# define NVM_REQ_INTEGRITY_FAILED   (3u) /*Result of the last NvM_ReadBlock or NvM_ReadAll is an integrity failure.*/
# define NVM_REQ_BLOCK_SKIPPED      (4u)  /*!< The referenced block was skipped during a multi block request. */
# define NVM_REQ_NV_INVALIDATED     (5u)  /*!< The NV block is invalidated. */
# define NVM_REQ_CANCELED           (6u)  /*!< A WriteAll was cancelled. */
# define NVM_REQ_REDUNDANCY_FAILED  (7u) /*!< A redundant block lost its redundancy. */
# define NVM_REQ_RESTORED_FROM_ROM  (8u) /*!< Default data from ROM are restored. */

NvM_ServiceIdType 对应的宏定义如下所示,在NvM_Types.h文件中

/* These Service Ids are important to an SW-C, as they can be passed to it in the "single block job end notification"
 *  callback. Therefore they are also defined by the RTE. */

#ifndef NVM_READ_BLOCK
# define NVM_READ_BLOCK             (6u) /*!< Service ID NvM_ReadBlock(). */
#endif
#ifndef NVM_WRITE_BLOCK
# define NVM_WRITE_BLOCK            (7u) /*!< Service ID NvM_WriteBlock(). */
#endif
#ifndef NVM_RESTORE_BLOCK_DEFAULTS
# define NVM_RESTORE_BLOCK_DEFAULTS (8u) /*!< Service ID NvM_RestoreBlockDefaults(). */
#endif
#ifndef NVM_ERASE_BLOCK
# define NVM_ERASE_BLOCK            (9u) /*!< Service ID NvM_EraseNvBlock(). */
#endif
#ifndef NVM_INVALIDATE_NV_BLOCK
# define NVM_INVALIDATE_NV_BLOCK   (11u) /*!< Service ID NvM_InvalidateNvBlock(). */
#endif
#ifndef NVM_READ_ALL
# define NVM_READ_ALL              (12u) /*!< Service ID NvM_ReadAll(). */
#endif

5.3 Global API Constants 全局API常数

这些特定于NVM的常数可以通过包含NVM .h来获得。它们可以在DaVinci Configurator Pro中进行配置。

> NVM_COMPILED_CONFIG_ID: NV内存布局配置的标识符

> NVM_NO_OF_BLOCK_IDS:定义的所有NVRAM块的数目(包括保留块)

> NVRAM块名称

如上对应的宏定义一般在文件夹NvM_Cfg.h 进行配置的。

5.4 Services provided by NVM NVM的服务接口

NVM API由服务组成,通过函数调用实现。

5.4.1 NvM_Init

Prototype
void NvM_Init ( void )
Parameter
————
Return code
void——
Functional Description
用于基本NVM初始化的服务。
对NVRAM块初始化
根据块描述符设置是通过NvM_ReadAll完成请求
Particularities and Limitations
1、同步业务。
2、该服务不可重入。
3、该服务始终可用。
Expected Caller Context
期望在应用程序上下文中调用此服务。
需要有ECU状态管理进行调用
/**********************************************************************************************************************
 * NvM_Init
 *********************************************************************************************************************/
/*! \brief Initializes component.
 *  \details Service for basic NVRAM manager initialization: initializes internal structures and the state machines.
 *  \context TASK
 *  \reentrant FALSE
 *  \synchronous TRUE
 *  \pre -
 *  \trace CREQ-723
 */
extern FUNC(void, NVM_PUBLIC_CODE) NvM_Init(void);

5.4.2 NvM_SetDataIndex

Prototype
Std_ReturnType NvM_SetDataIndex ( NvM_BlockIdType BlockId,
uint8 DataIndex )
Parameter
BlockId块标识符。
DataIndex数据集类型的NV块中的索引位置。
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如Det检查出错误
Functional Description
该请求设置指定的索引,将数据集NV块(包含/不包含ROM块)与其对应的RAM块关联起来。
在发起读/写/擦除或无效请求之前,DataIndex需要有一个有效的值。
如果数据集块有一组默认的ROM,则使用该函数(在NvM_ReadBlock()之前)来选择适当的ROM。
Particularities and Limitations
>同步业务。
>业务重入。
>配置API配置类2或3时可用。
在这个请求被调用之前,NVRAM管理器应该已经初始化。
注意:
使用显式同步,不允许NvM的客户端对待决块发出新请求。
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-3 NvM_SetDataIndex

5.4.3 NvM_GetDataIndex

Prototype
Std_ReturnType NvM_GetDataIndex ( NvM_BlockIdType BlockId,
uint8* DataIndexPtr )
Parameter
BlockId块标识符。
DataIndexPtr数据指针,指向被写得位置
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如Det检查出错误
Functional Description
该请求传递了指定数据集块的当前DataIndex
Particularities and Limitations
>同步业务。
>业务重入。
>配置API配置类2或3时可用。
在这个请求被调用之前,NVRAM管理器应该已经初始化。
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-4 NvM_GetDataIndex

5.4.4 NvM_SetBlockProtection

Prototype
Std_ReturnType NvM_SetBlockProtection( NvM_BlockIdType BlockId,
boolean ProtectionEnabled )
Parameter
BlockId块标识符。
ProtectionEnabled该参数用于设置已选数据的写保护。
NVRAM block:
TRUE:开启保护。
1FALSE:禁用保护
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如Det检查出错误
Functional Description
该请求设置NV块的写保护。
如果设置了NV块写保护,任何对NVRAM块的写/擦除/无效请求都会被同步拒绝。
在任何情况下,物理内存块的数据区都是可写的。
Particularities and Limitations
>同步业务。
>业务重入。
>配置API配置类3时可用。
在这个请求被调用之前,NVRAM管理器应该已经初始化。
对于已经写过的写一次块,则该写一次块就不能解除保护。
提示:
对于显示同步,NVM的客户端不允许对一个pending的block进行相应的操作。
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-5 NvM_SetBlockProtection

5.4.5 NvM_GetErrorStatus

Prototype
Std_ReturnType NvM_GetErrorStatus ( NvM_BlockIdType BlockId,
NvM_RequestResultType* RequestResultPtr )
Parameter
BlockId块标识符。
RequestResultPtr将结果写入的指针。
Result的类型是NvM_RequestResultType。
所有可能的结果在5.2章中描述
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如Det检查出错误
Functional Description
该请求读取与块相关的错误/状态信息,并将其写入给定地址。
先前或当前的异步请求设置了状态/错误信息。
这个API也可以通过BlockId 0(多块)来请求。
然后将多块错误/状态信息读取到给定的地址。
只有NvM_ReadAll()和NvM_WriteAll()是多块请求,并更改多块的状态/错误信息。
Particularities and Limitations
>同步业务。
>业务重入。
>任何级别的API Class 均可用。
在这个请求被调用之前,NVRAM管理器应该已经初始化。
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-6 NvM_GetErrorStatus

5.4.6 NvM_GetVersionInfo

Prototype
void NvM_GetVersionInfo ( Std_VersionInfoType* versioninfo )

Parameter
versioninfo需要写入版本数据的数据地址。
Return code
void——
Functional Description
版本信息:
厂商ID,模块ID, SW主版本,SW次版本,SW补丁版本
将版本信息写入到给定的指针。
Particularities and Limitations
>同步业务。
>业务重入。
>需要使能 version info API
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-7 NvM_GetVersionInfo

5.4.7 NvM_SetRamBlockStatus

Prototype
Std_ReturnType NvM_SetRamBlockStatus ( NvM_BlockIdType BlockId,
boolean BlockChanged )
Parameter
BlockIdBlock ID 识别码
BlockChanged设置内存块的新状态:
TRUE:验证内存块并将其标记为已更改。
如果块有CRC且选项NVM_CALC_RAM_BLOCK_CRC为TRUE,则开始CRC计算。
FALSE:将块标记为未改变
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如,可能发生DET错误
Functional Description
1.该请求将块的状态分别设置为valid/changed为unchanged。
将一个块设置为更改(changed),标志着它可以在NvM_WriteAll()期间写入。
2.如果内存块设置为changed,
如果NVM_CALC_RAM_BLOCK_CRC为TRUE,则启动内存块的CRC计算。
注意:
虽然此服务被定义为同步操作,但CRC重新计算将被异步执行。但是,对访问RAM块数据或调用其他服务没有限制。WriteBlock/WriteAll机制在写入前无条件地重新计算CRC,保证了数据和CRC的一致性。再次使用NvM_SetRamBlockStatus请求重新计算CRC,将以一种保存的方式被识别,如果需要,计算将重新排队。
Particularities and Limitations
>同步业务。
>业务重入。
>使用所有Class 级别
>在调用前需要对NVM进行初始化;
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-8 NvM_SetRamBlockStatus

5.4.8 NvM_SetBlockLockStatus

Prototype
void NvM_SetBlockLockStatus( NvM_BlockIdType BlockId,
boolean BlockLocked )
Parameter
BlockIdBlock ID 识别码
BlockLocked该参数用于设置所选NVRAM块的锁保护状态。
TRUE:启用锁。
FALSE:禁用锁
Return code
void——
Functional Description
用于设置/重置NV块的锁的服务。
如果锁定,与BlockId标识的NVRAM块相关的NV内容将不会被任何后续的写请求修改,即NvM_WriteAll期间将跳过该块;
其他请求,即NvM_WriteBlock, NvM_InvalidateNvBlock, NvM_EraseNvBlock,将被拒绝,不向Det或Dem发出错误通知;
也就是说,它们只是返回E_NOT_OK。
在NvM_ReadAll的处理过程中,一个锁定的NVRAM块将从NV内存中加载,无论RAM块的状态如何(见3.4.10)。之后,锁再次被禁用。
如果一个块被NvM_SetBlockLockStatus锁定,只有原始的NVRAM块被锁定
Note
1.该服务允许一个已经挂起(pending)块进行操作;
2.在使用该服务后,会影响后续的相应请求;其中之前在挂起过程中的操作会被处理,不受影响;
Particularities and Limitations
>同步业务。
>业务重入。
>使用所有Class 级别
>在调用前需要对NVM进行初始化;
>该服务不能对已经写过的写一次块(write once block)进行操作
>该服务只能在BSW层的组件中进行调用,不能通过RTE被访问
Expected Caller Context
此服务通常被DCM调用

Table 5-9 NvM_SetBlockLockStatus

5.4.9 NvM_MainFunction

Prototype
void NvM_MainFunction ( void )
Parameter
————
Return code
void——
Functional Description
这个函数必须循环调用。
它是NVRAM管理器的入口。在这里处理异步任务(读/写/擦除/无效/CRC计算…)。
Particularities and Limitations
>同步业务。
>业务不可以重入。
>使用所有Class 级别
>在调用前需要对NVM进行初始化;
Expected Caller Context
次服务通常被DCM调用

Table 5-10 NvM_MainFunction

5.4.10 NvM_ReadBlock

Prototype
Std_ReturnType NvM_ReadBlock ( NvM_BlockIdType BlockId,
void* NvM_DstPtr )
Parameter
BlockId块标识符。
NvM_DstPtr1.非永久物理内存块的数据要写入的指针。
2.如果块是永久的,则传递NULL_PTR ......
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如工作队列溢出
Functional Description
请求将NV块的数据复制到对应的RAM块中。
该函数对读取请求进行排队,并同步返回接收结果。
当服务完成时,NVM可以通过回调通知应用程序。
Particularities and Limitations
>异步业务。
>业务可以重入。
>配置API配置类2,3时可用。
>在这个请求被调用之前,NVRAM管理器应该已经初始化。
>在开发模式中,如果该块已经排在队列中(也包括其他服务),则该服务不接受调用。
Note
在显示同步中,如果该block处于pending状态,则NVM客户端不允许发送一个新的请求
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-11 NvM_ReadBlock

5.4.11 NvM_WriteBlock

Prototype
Std_ReturnType NvM_WriteBlock ( NvM_BlockIdType BlockId,
const void* NvM_SrcPtr )
Parameter
BlockId块标识符。
NvM_DstPtr1.非永久物理内存块的数据要读的指针。
2.如果块是永久的,则传递NULL_PTR ......
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如工作队列溢出
Functional Description
请求将数据从RAM块复制到对应的NV块。
该函数对写请求进行排队,并同步返回接受结果。
如果块有CRC,则在数据和CRC写入NV内存之前,会重新计算RAM块的CRC。
如果对该块配置了CRC后台计算(NvM_SetRamBlockStatus和NvMCalcRamBlockCrc),情况也是如此。
如果数据写入NV内存失败,NVM会重试写入。写重试的次数是一个配置选项。
当服务完成时,NVM可以通过回调通知应用程序。
Particularities and Limitations
>异步业务。
>业务可以重入。
>配置API配置类2,3时可用。
>在这个请求被调用之前,NVRAM管理器应该已经初始化。
>在开发模式中,如果该块已经排在队列中(也包括其他服务),则该服务不接受调用。
Note
在显示同步中,如果该block处于pending状态,则NVM客户端不允许发送一个新的请求
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-12 NvM_WriteBlock

5.4.12 NvM_RestoreBlockDefaults

Prototype
Std_ReturnType NvM_RestoreBlockDefaults ( NvM_BlockIdType BlockId,
void* NvM_DstPtr )
Parameter
BlockId块标识符。
NvM_DstPtr1.默认数据的地址
2.如果块是永久的,则传递NULL_PTR ......
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如工作队列溢出
Functional Description
请求将ROM块默认数据复制到相应的RAM块。
选中的块需要ROM默认值或初始化回调。
该函数对恢复请求进行排队,并同步返回接受结果。
当服务完成时,NVM可以通过回调通知应用程序。
Particularities and Limitations
>异步业务。
>业务可以重入。
>配置API配置类2,3时可用。
>在这个请求被调用之前,NVRAM管理器应该已经初始化。
>在开发模式中,如果该块已经排在队列中(也包括其他服务),则该服务不接受调用。
>该函数不能用于读取当前ROM的设置,需要用NvM_ReadBlock 替代
Note
在显示同步中,如果该block处于pending状态,则NVM客户端不允许发送一个新的请求
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-13 NvM_RestoreBlockDefaults

5.4.13 NvM_EraseNvBlock

Prototype
Std_ReturnType NvM_EraseNvBlock ( NvM_BlockIdType BlockId )
Parameter
BlockId块标识符。
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如工作队列溢出
Functional Description
请求删除指定的NV块。
该函数对擦除请求进行排队,并同步返回接收结果。
当服务完成时,NVM可以通过回调通知应用程序。
Particularities and Limitations
>异步服务。
>业务重入。
>配置API配置类3时提供。
在这个请求被调用之前,NVRAM管理器应该已经初始化。
在开发模式下,如果块已经排队(无论是此服务还是其他服务),则服务将不接受调用。
如果块的写保护被激活,它也不能被擦除。
注意:
只有高优先级的任务(优先级为0)可以被删除!
使用显式同步,不允许NvM的客户端对待决块发出新的请求。
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-14 NvM_EraseNvBlock

5.4.14 NvM_InvalidateNvBlock

Prototype
Std_ReturnType NvM_InvalidateNvBlock ( NvM_BlockIdType BlockId )
Parameter
BlockId块标识符。
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如工作队列溢出
Functional Description
请求使指定的NV块无效。
该函数对无效请求进行排队,并同步返回接受结果。
当服务完成时,NVM可以通过回调通知应用程序。
Particularities and Limitations
>异步服务。
>业务重入。
>配置API配置类3时提供。
在这个请求被调用之前,NVRAM管理器应该已经初始化。
在开发模式下,如果块已经排队(无论是此服务还是其他服务),则服务将不接受调用。
如果块的写保护被激活,它也不能被擦除。
注意:
只有高优先级的任务(优先级为0)可以被删除!
使用显式同步,不允许NvM的客户端对待决块发出新的请求。
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-15 NvM_InvalidateNvBlock

5.4.15 NvM_ReadAll

Prototype
void NvM_ReadAll ( void )
Parameter
————
Return code
void——
Functional Description
请求加载(重新加载)所有选择的NVM_SELECT_BLOCK_FOR_READALL选项的RAM块。
函数队列将在NvM_MainFunction中处理的请求。
在重新加载block的NV数据之前,首先检查RAM块数据是否仍然有效。
会对有校验和时进行检验,在有效RAM数据的情况下,NV数据将不会重新加载。
警告:
在ReadAll作业中也跳过了非永久块和数据集块。
从NV内存中读取的第一个块是配置ID(block 1)。此检查的结果影响了ReadAll作业的进一步处理,
这取决于动态配置处理(Dynamic Configuration Handling)的设置:
(1)如果禁用,所有NVRAM块都将被处理,如上面描述的那样,不管读取/检查配置ID(匹配/不匹配/块无效/完整性错误/读取失败)的结果。
(2)如果启用了动态配置处理,NVM将加载所有的NVRAM块,程序会遍历出所有可用的 Block ID,并读取相应的数据。
(3)如果使能Resistant to Changed Software功能,将对无效的Block数据进行恢复,恢复为ROM默认值,
(4)如果配置了ReadAll的完成通知函数,则当最后一个块重新加载时,NVM可以通过回调(可配置的多块回调)通知应用程序。
Particularities and Limitations
>这个服务是一个多块请求。
>该服务是异步的。
>此服务是不可重入的。
>这个服务总是可用的。
> NVRAM管理器应在调用此请求之前初始化。
注意:
显性同步中,如果Block处于pending的状态,则不允许NvM的客户端发布新的请求
Expected Caller Context
这个函数只在启动时由ECU状态管理器(ECU State Manager)调用。

Table 5-16 NvM_ReadAll

5.4.16 NvM_WriteAll

Prototype
void NvM_WriteAll ( void )
Parameter
————
Return code
void——
Functional Description
对所有已经开启NVM_SELECT_BLOCK_FOR_WRITEALL的选项的Block,该请求会将已经改动RAM值得Block写入Nv Block中
该函数将排队的所有工作都将被处理。

注意:
(1)如果NvM_SetRamBlockStatus() API被使能,对应的Block只有在被标记更改后,才会被重新写入。否则不进行写入;
(2)如果一个block的配置选项NvMBlockUseSetRamBlockStatus被禁用,由于无法对块内容进行检测,那么它将总是在NvM_WriteAll()中写入;

警告:
非永久(Nonj-permanent)和数据集块(dataset block )将不会在NvM_WriteAll()中写入。

当最后一个块写的时候,NVM可以通过回调(可配置的多块回调)通知应用程序。

注意:
(1)不建议对将处理哪些块的顺序做任何假设。
(2)Config Block(ID1)是被处理的最后块,以便“提交”配置更新和任何相关活动。
Particularities and Limitations
>这个服务是一个多块请求。
>该服务是异步的。
>此服务是不可重入的。
>这个服务总是可用的。
> NVRAM管理器应在调用此请求之前初始化。
注意:
显性同步中,如果Block处于pending的状态,则不允许NvM的客户端发布新的请求
Expected Caller Context
这个函数只在关机时由ECU状态管理器(ECU State Manager)调用。

Table 5-17 NvM_WriteAll

5.4.17 NvM_CancelWriteAll

Prototype
void NvM_CancelWriteAll ( void )
Parameter
————
Return code
void——
Functional Description
请求取消正在运行的NvM_WriteAll()请求。这个调用将异步处理的请求排队。
Particularities and Limitations
>异步服务。
>该服务不可重入。
>该服务始终可用。
>在这个请求被调用之前,NVRAM管理器应该已经初始化。
Expected Caller Context
期望在应用程序上下文中调用此服务。

Table 5-18 NvM_CancelWriteAll

5.4.18 NvM_KillWriteAll

Prototype
void NvM_KillWriteAll ( void )
Parameter
————
Return code
void——
Functional Description
取消正在运行的NvM_WriteAll()请求。
该请求具备破坏性
由于NvM_CancelWriteAll()的请求可能会对ECUM的唤醒时间启动时间有影响,造成超时。
因此可以采用如上的API接口进行具备破坏性的中断Writeall的接口函数。
Particularities and Limitations
>同步业务。
>该服务不可重入。
>这个API需要一个独立的API配置的Class.需要在Nvm_30CommonVendorParas中进行配置,开启预编译器中的 NvmKillWriteAllApi的编译开关。
>在这个请求被调用之前,NVRAM管理器应该已经初始化。
Expected Caller Context
期望在ECUM中调用此服务。

Table 5-19 NvM_KilllWriteAll

5.4.19 NvM_CancelJobs

Prototype
Std_ReturnType NvM_CancelJobs ( NvM_BlockIdType BlockId)
Parameter
BlockId块标识符。
Return code
E_OK请求被接受
E_NOT_OK请求没有被接受,比如列表溢出(overflow)
Functional Description
取消一个正在pending的block的操作队列
Particularities and Limitations
>异步服务。
>业务重入。
>配置API配置类2或3时可用。
>在这个请求被调用之前,NVRAM管理器应该已经初始化。
>结果设置为NVM_REQ_CANCELED。
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-20 NvM_CancelJobs

5.4.20 NvM_RepairRedundantBlocks

Prototype
void NvM_RepairRedundantBlocks (void)
Parameter
————
Return code
void——
Functional Description
请求检查NV RAM内所有配置的冗余块的冗余。
该API与写保护(write protection)或锁状态(lock state)无关,NvM不会改变数据,它总是用NV RAM中的数据覆盖数据块。

如果NvM识别到丢失的冗余,它将尝试通过使用有效块中的数据覆盖缺陷块来恢复它。
存在以下集中情况:
(1)无修复:
-两个子块是可读的
-两个子块的Crc匹配重新计算的Crc
(2)可修复块:
                   -一个子块是不可读的,另一个是可读的
                   -一个子块的CRC不匹配,另一个子块的CRC匹配
                   -两个子块的CRC均匹配数据,但他们彼此不一致,则第一块为有效块
(3)不可修复的块:
                  -两个子块都不可读
                  - Block子块的的CRC均不匹配

NvM将报告错误NVM_E_LOSS_OF_REDUNDANCY
如果块没有有效冗余存储在NV RAM中,NvM将无法恢复冗余。
Particularities and Limitations
>此服务是异步的
>此服务是可重入的
>此服务可以对单块或多块进行挂起请求,在完成该请求后再进行恢复。
>此服务可通过配置启用或禁用
>在此请求调用之前NVRAM管理器应已初始化
Expected Caller Context
此服务预期在应用程序上下文中调用。

Table 5-21 NvM_RepairRedundantBlocks

5.4.21 NvM_KillReadAll

Prototype
void NvM_KillReadAll ( void )
Parameter
————
Return code
void——
Functional Description
请求中止正在进行的NvM_ReadAll服务。
请求之后,NvM将不再访问NV内存(必要时取消底层模块),以尽快完成块初始化。
NvM仍然需要调用NvM_MainFunction,直到多块错误状态标志着NvM_ReadAll的结束。
NvM行为如下:
> Normal NvM_ReadAll
> NvM_KillReadAll
>对于以下所有块:
             > Default data available:加载默认数据,假装读取成功
             > Default data not available:跳过block
>返回状态  Multi block error status表示任务被终止
Particularities and Limitations
>异步服务。
>该服务不可重入。
> Write once NvM_KillReadAll调用后处理的块不做写保护。
>所有块都调用
>在作业结束后,会调用回调函数进行状态信息的的结束通知。
>在这个请求被调用之前,NVRAM管理器应该已经初始化。
Expected Caller Context
任何可能的上下文。

Table 5-22 NvM_KillReadAll

5.5 Services used by NVM

下表列出了NVM使用的其他组件提供的服务。有关原型和功能的详细信息,请参阅提供组件的文档。

ComponentAPI
DETDet_ReportError
DEMDem_SetEventStatus
MEMIFMemIf_Read
MEMIFMemIf_InvalidateBlock
MEMIFMemIf_GetJobResult
MEMIFMemIf_Write
MEMIFMemIf_EraseImmediateBlock
MEMIFMemIf_GetStatus
MEMIFMemIf_Cancel
MEMIFMemIf_SetMode
CRCCrc_CalculateCRC16
CRCCrc_CalculateCRC32
EAUsed by MEMIF
FEEUsed by MEMIF
CSMCsm_Encrypt
CSMCsm_Decypt
CSMCsm_MacGenerate
CSMCsm_MacVerify

Table 5-23 Services used by the NVM

5.6 Callback Functions

本章描述了由NVM实现的回调函数,其他模块可以调用这些函数。回调函数的原型由NVM提供在头文件NvM_Cbk.h中。

5.6.1 NvM_JobEndNotification

Prototype
void NvM_JobEndNotification ( void )
Parameter
————
Return code
void请求被接受
Functional Description
在没有出现错误的情况下,由底层内存抽象使用的函数,用于发出作业结束。
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
在没有发生错误的情况下,回调函数NvM_JobEndNotification被底层的内存抽象(Fee/Ea)用来发出作业结束的信号。

Table 5-24 NvM_JobEndNotification

5.6.2 NvM_JobErrorNotification

Prototype
void NvM_JobErrorNotification ( void )
Parameter
————
Return code
void请求被接受
Functional Description
出现错误的情况下,由底层内存抽象使用的函数,用于发出作业结束。
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
在发生错误的情况下,回调函数NvM_JobErrorNotification被底层的内存抽象(Fee/Ea)用来发出作业结束的信号。

Table 5-25 NvM_JobErrorNotification

5.7 Configurable Interfaces

在其可配置的接口上,NVM定义了可以映射到其他模块提供的回调函数的通知。

该映射不是由BSW模块静态定义的,而是可以在配置时执行的。

用于配置的函数原型必须符合后面各章描述的签名。

5.7.1 SingleBlockCallbackFunction

Prototype
Std_ReturnType <SingleBlockCallbackFunction>
( NvM_ServiceIdType ServiceId, NvM_RequestResultType)
Parameter
ServiceId已完成请求的服务标识符(参见第5.2章)。NvM_ServiceIdType类型为uint8。
JobResult单块作业的结果。
Return code
E_OK回调函数已成功处理
E_NOT_OK回调函数尚未成功处理
Functional Description
回调例程,通知上层异步单块请求已经完成。
Particularities and Limitations
>此服务是同步的。
>该服务不可重入。
注意:
1.此描述仅限于嵌入式代码;
2.这个接口函数不能在SWC中的Runnable中强行调用;
3.可以由RTE或BSW组件实现/生成的原型。
Expected Caller Context
>从NvM_MainFunction调用
>异步块处理完成

Table 5-26 SingleBlockCallbackFunction

5.7.2 SingleBlockCallbackExtendedFunction

Prototype
Std_ReturnType <SingleBlockCallbackExtendedFunction> (  NvM_BlockIdType BlockId,  NvM_ServiceIdType ServiceId,  NvM_RequestResultType JobResult )
Parameter
BlockIdBlock 标识码
ServiceId已完成请求的服务标识符(参见第5.2章)。NvM_ServiceIdType类型为uint8。
JobResult单块作业的结果。
Return code
E_OK回调函数已成功处理
E_NOT_OK回调函数尚未成功处理
Functional Description
回调例程,通知上层异步单块请求已经完成。
这个回调函数还可以配置为<SingleBlockCallbackFunction>。
如果配置了两个回调函数,<SingleBlockCallbackFunction>将在<SingleBlockCallbackExtendedFunction>之前被调用。
与<SingleBlockCallbackFunction>相反,如果该参数存在且不是NULL_PTR,则配置了<SingleBlockCallbackExtendedFunction>。
Note
这个回调是AUTOSAR扩展,不能通过“使用服务端口”选项使用。
Particularities and Limitations
>同步业务。
>该服务不可重入。
注意:
此描述仅限于嵌入式代码;它没有描述在SWC中实现回调行为的RUNNABLES,但它描述了由RTE或BSW组件实现/生成的原型。
Expected Caller Context
>从NvM_MainFunction调用
>异步块处理完成

Table 5-26 SingleBlockCallbackFunction

5.7.3 MultiBlockCallbackFunction

Prototype
void <MultiBlockCallbackFunction> ( NvM_ServiceIdType ServiceId,  NvM_RequestResultType JobResult )
Parameter
ServiceId已完成请求的服务标识符(参见第5.2章)。NvM_ServiceIdType类型为uint8。
JobResult单块作业的结果。
Return code
void——
Functional Description
通知上层异步多块请求已经完成的通用回调例程。
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
>从NvM_MainFunction调用
>分别在NvM_ReadAll和NvM_WriteAll完成时调用

Table 5-28 MultiBlockCallbackFunction

5.7.4 InitBlockCallbackFunction

Prototype
Std_ReturnType <InitBlockCallbackFunction> ( void )
Parameter
ServiceId已完成请求的服务标识符(参见第5.2章)。NvM_ServiceIdType类型为uint8。
JobResult单块作业的结果。
Return code
E_OK该函数总是回复 E_OK
Functional Description
如果没有配置ROM块,NVM模块将调用该回调例程,将默认数据复制到RAM块。
注意:
在调用init block回调时,相关的block会处于忙状态,在忙状态中不做回复,直至block空闲后
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
>从NvM_MainFunction调用

Table 5-29 InitBlockCallbackFunction

5.7.5 InitBlockCallbackExtendedFunction

Prototype
Std_ReturnType <InitBlockCallbackExtendedFunction> (  NvM_BlockIdType BlockId,  void* BufferPtr,  uint16 Length)
Parameter
BlockIdBlock 标识
BufferPtr默认数据的地址
LengthBlock的数据长度
Return code
E_OK该函数总是回复 E_OK
Functional Description
如果没有配置ROM块,NVM模块将调用该回调例程,将默认数据复制到RAM块。
这个回调函数是<InitBlockCallbackFunction>的扩展版本。
与<InitBlockCallbackFunction>相反,如果该参数存在且不是NULL_PTR,则配置了<InitBlockCallbackExtendedFunction>。

注意:
1.此回调是AUTOSAR扩展,不能通过“使用服务端口”选项使用。
2.一次只能配置一个init块回调。
3.在调用init块时,回调相关的块仍然繁忙。直至空闲后回复
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
>在NvM_ReadAll的处理过程中调用
>如果应用程序将默认值复制到相应的RAM块。

5.7.6 Callback function for RAM to NvM copy

Prototype
Std_ReturnType <NvM_WriteRamBlockToNvm> ( void* NvMBuffer )
Parameter
NvMBuffer内存RAM镜像,用于写入NVM的数据源
Return code
E_NOT_OK回调函数处理成功
E_OK回调函数没有处理成功
Functional Description
为了让应用程序将数据从RAM块复制到内部的NvM RAM镜像,需要调用该块特定的回调例程。

注意:
在调用NvM_WriteRamBlockToNvM回调时,相关块会处于忙状态,直至空闲后发出回复请求。
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
1、在NvM_MainFunction函数中调用
2、如果应用程序需要将RAM block数据写入内部RAM镜像,则需要调用NVM写请求;

Table 5-30 Callback function for RAM to NvM copy

5.7.7 Callback function for NvM to RAM copy

Prototype
Std_ReturnType <NvM_ReadRamBlockFromNvm> ( const void* NvMBuffer )
Parameter
NvMBuffer内部RAM的数据地址,用于缓存读出得Nvm数据
Return code
E_NOT_OK回调函数处理成功
E_OK回调函数没有处理成功
Functional Description
为了让应用程序从NvM模块的镜像复制数据到RAM块,需要调用特定的回调例程。
在调用NvM_ReadRamBlockFromNvM回调时,相关块处于忙状态,直至空闲后发送回复请
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
1、在NvM_MainFunction函数中调用
2、如果应用程序需要将内部镜像RAM 数据复制到RAM中,则需要调用NVM读请求;

Table 5-31 Callback function for NvM to RAM copy

5.7.8 PreWriteTransformCallbackFunction

Prototype
Std_ReturnType <NvM_ReadRamBlockFromNvm> ( const void* NvMBuffer )void <PreWriteTransformCallbackFunction> ( NvM_BlockIdType BlockId, void* DataPtr, uint16 Length )
Parameter
BlockIdBlock 的标识
DataPtr需要的写入到 NvRam的数据源地址
Length数据长度
Return code
void——
Functional Description
是一个特定的回调函数,用于在应用程序中做数据转换的接口回调函数。
更多信息请参见3.4.15章。
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
1、在NvM_MainFunction函数中调用
2、如果配置了该回调函数,则Nvm在写入之前会调用该函数进行数据转换;

Table 5-32 PreWriteTransformCallbackFunction

5.7.9 PostReadTransformCallbackFunction

Prototype
Std_ReturnType <PostReadTransformCallbackFunction> ( NvM_BlockIdType  BlockId, void* DataPtr, uint16 Length )
Parameter
BlockIdBlock 的标识
DataPtr用于从 NvRam中读出数据的目的数据地址
Length数据长度
Return code
E_OK数据有效
E_NOT_OK数据无效,并且NVM将会在read作业中回复失败
Functional Description
是一个特定的回调函数,用于在应用程序中做数据读出前数据转换接口回调函数。
更多信息请参见3.4.15章。
Particularities and Limitations
>同步业务。
>该服务不可重入。
Expected Caller Context
1、在NvM_MainFunction函数中调用
2、如果配置了该回调函数,则Nvm在读取之前会调用该函数进行数据转换;

Table 5-33 PostReadTransformationCallbackFunction

5.8 Service Ports服务端口

软件组件独立于底层的基本软件栈,软件组件(SWC)因此需要通过服务端口,才可以使用抽象的RTE接口来执行NVM的服务。

5.8.1 Client Server Interface

客户端服务器接口与服务器端的提供端口(Pport)和客户端的要求端口(Rport)相关。

配置依赖的命名细节在6.1.3和6.1.4章节中描述。

5.8.1.1 Provide Ports on NVM side

在NVM的端口中,5.4中描述的API函数作为可运行实体(Runnable Entities)可用。可运行实体是通过操作调用的。从SWC客户端调用到操作的映射由RTE执行。在这个映射中,如果配置了,RTE将端口定义的参数值添加到SWC的客户端调用。下面的子章节介绍了为NVM定义的端口及其操作,与这些操作相关的API函数,以及RTE要添加的端口定义参数值:

5.8.1.1.1.1 PS_<BlockName>

一个Padmin类型的端口是一个NVRAM块的Pport端口,它被配置为使用服务端口。

如果开启了配置长服务端口名称(Long Service Port Names)的SWC,则服务端口的名称为Padmin_<BlockName>;

如果“长服务端口名称(Long Service Port Names)”未启用,则名称为Padmin_。

当API配置类Class= 3时可用时

OperationAPI FunctionPort Defined Argument Values
SetBlockProtectionNvM_SetBlockProtection()NvM_BlockIdType4 1…n

Table 5-34 Operations of Port Prototype Padmin_<BlockName>

PS_<BlockName>

PS类型的端口是一个NVRAM块的Pport端口,它被配置为使用服务端口。

如果开启了配置长服务(Long Service Port Names)端口名称的SWC,则服务端口的名称为PS_<BlockName>;

如果没有开启“长服务端口名称Long Service Port Names”为“PS_<BlockId>”。

OperationAPI FunctionPort Defined Argument Values
GetErrorStatus 1NvM_GetErrorStatus()NvM_BlockIdType4 1…n
SetRamBlockStatus1NvM_SetRamBlockStatus()NvM_BlockIdType4 1…n
SetDataIndex2,5NvM_SetDataIndex()NvM_BlockIdType4 1…n
GetDataIndex2,5NvM_GetDataIndex()NvM_BlockIdType4 1…n
ReadBlock2NvM_ReadBlock()NvM_BlockIdType4 1…n
WriteBlock2NvM_WriteBlock()NvM_BlockIdType4 1…n
RestoreBlockDefaults2,6NvM_RestoreBlockDefaults()NvM_BlockIdType4 1…n
EraseBlock3NvM_EraseNvBlock()NvM_BlockIdType4 1…n
InvalidateNvBlock3NvM_InvalidateNvBlock()NvM_BlockIdType4 1…n

Table 5-35 Operations of Port Prototype PS_<BlockName>

  1. 总是可用的

  2. 当API配置类>= 2时可用(Class >= 2)

  3. 当API配置类= 3时可用(Class >= 3)

  4. 从块在配置中的位置得到的(Is derived from the block’s position in the configuration)

  5. 仅对管理类型数据集的块可用(Type Dataset)

  6. 仅对配置了Rom默认值的块可用(Rom defaults)

5.8.1.2 Require Ports

NVM使用Rports调用回调函数。这些操作必须由SWC通过使用端口的可运行实体提供。这些可运行实体(Runnable Entities)实现了NVM期望的回调函数。下面的子章节介绍了为NVM定义的Require Ports、从NVM调用的操作和相关的通知(在5.7章中描述)。

5.8.1.2.1 NvM_RpNotifyFinished_Id<BlockName>

NvM_RpNotifyFinished_Id类型的端口是一个NVRAM块的Rport,它被配置为Service服务端口。

如果SWC设置了长服务端口名称,则服务端口的名称为NvM_RpNotifyFinished_Id<BlockName>;

如果不启用长服务端口名称,则名称为NvM_RpNotifyFinished_Id<BlockId>

在所有API配置类中可用,但使用**回调(Use Callbacks)**必须启用。

OperationNotification
JobFinishedSingleBlockCallbackFunction

6 Configuration 配置 (待补充TODO)

6.1 Software Component Template

6.1.1 Generation

提供端口的定义在XML文件中描述。该文件将NVM描述为一个带有端口的软件组件,其他应用程序可以连接到它。当保存DaVinci Configurator中的项目时,这个XML文件总是与当前ECUC文件保存一致。SWC文件的目标目录可以在Dpa文件中设置。

有关更多信息,请参阅DaVinci Configurator的文档//TODO。

6.1.2 Import into DaVinci Developer

为了进一步处理,必须将生成的软件组件模板文件导入到DaVinci Developer中。这可以在打开DaVinci-project项目时通过单击File | Import XML File…来完成为导入选择正确的文件。

image-20221114101035739

Figure 6-1 Import a new software component into DaVinci Developer

将NVM作为软件组件导入后,会显示一个可用的新的组件类型可用。双击组件NVM后,显示所有已配置的端口。

DaVinci工具套件允许您设计完整的汽车架构,包括几个ecu,每个ecu都有自己的NVM。因此,需要导入几个NVM SWC描述,每个描述包含一个要映射到特定ECU的NVM的描述。使用“服务组件名称参数(Service Component Name Parameter)”,您可以为您的配置提供有意义的唯一名称。在这个特定的配置中,所有SWC描述的元素都是唯一的,并且都以这个参数的值作为前缀。然而,大多数元素对于所有的SW-C描述都是通用的,或者至少对于所使用的配置是唯一的(也由元素的名称表示),因此一些元素包含在每个不同的SW-C描述中。在导入过程中,达芬奇会警告你这些双元素。您可以忽略它们(覆盖现有的元素);它们是一样的。

6.1.3 Dependencies on Configuration of NVM Attributes 配置NVM属性的依赖关系

NVM属性的配置(在6.1.5章中描述过)对结果的SW-C描述有很大影响。因此,参数服务组件名称的值会影响描述中几个元素的名称,特别是服务组件的名称(Service Component Name)。它也是属于这个特定的NVM配置(以及生成的服务组件)的其他几个名称的前缀。

根据特定的配置,将生成几个不同的端口接口。每个由特定配置生成的接口都有一个唯一的名称,即在不同的SW-C描述中,具有相同名称的端口接口是兼容的;它们提供相同的操作,每个操作都有相同类型的参数。

6.1.3.1 Naming of Service Port Interfaces 服务端口接口的命名

服务端口接口提供了NVM基本块相关服务的原型,如从NV内存读取数据、向NV内存写入数据等。它通常包含字符串Service

如上所述,不同配置产生的端口接口有不同的名称。这些名称是按照下面的方案给出的:

  1. 每个接口都有NvM前缀

  2. 设置Ram块状态API(Set Ram Block Status)

    如果启用,接口名称包含字符串’ SRBS ',它包含SetRamBlockStatus操作。

  3. API 配置的Class

    接口名包含一个短字符串,表示它所属的API配置类:AC1、AC2或AC3。该配置类中接口描述的操作请参见5.8.1.1章(TODO)。

  4. ROM默认数据的可用性(ROM default data)

    该接口包含RestoreBlockDefaults操作;它包含字符串Defs。该接口将被属于NVRAM块的所有P- Port原型使用,该NVRAM块配置了ROM默认数据。

  5. 块管理类型数据集Block Management Type DATASET

    接口提供了GetDataIndexSetDataIndex操作。它的名称包含DS。此接口将被管理类型数据集(DATASET)的所有NVRAM块使用。

    前两种可能性在一个SW-C描述中很常见。只有一种组合会发生。除非选择API配置类1(API Configuration Class 1),否则可能生成描述后两种可能性任意组合的端口接口。

6.1.4 Service Port Prototypes

对于使用Use Service port配置的每个活动NVRAM块(包括配置ID块),都会生成原型。它们所基于的端口接口可能不同。这些接口依赖于块的配置,因此也依赖于当前块所需要的操作。

6.1.4.1 Port Prototype Naming端口原型命名

标识原型的短名称基于数字块ID(由块在配置中的位置派生)和它对应的端口接口类。

每个原型都以字符串NvM_作为前缀;下一个子字符串描述了对应的端口接口,以及它是提供端口(Provide Port)(’ Pp ‘)还是需要端口(’ Rp ')(Require Port):

  • Padmin

​ 与端口接口NvMAdministration链接(仅在API配置类3中)

  • PS

    ​ 与端口 ‘NvMService_AC{1|2|3}[_SRBS][_Defs][_DS]’链接 ,实际的接口依赖于上述的描述。

  • NvM_RpNotifyFinished

​ 与端口接口NvMNotifyJobFinished连接,该接口描述了NVM用于单块作业结束通知的接口

如果SWC设置的长服务端口名称是禁用的,每个端口原型的名称是由**_Id{BlockId}**固定。

如果启用了SWC设置长服务端口名称,则每个端口原型的名称都由_{BlockName}固定。

6.1.5 Modelling SWC’s callback functions

根据AUTOSAR的说法,SingleBlockCallbackFunction(第5.7.1章//TODO)的原型与实现SWC回调的RUNNABLE的原型不同。因此原型描述了NVM调用的RTE函数。

实际被RTE调用的RUNNABLE的原型必须与model匹配,即返回类型必须与callback接口描述中给出的信息匹配(“Application Errors”)。正确的建模应该是“无应用程序错误”,这需要一个没有返回类型的RUNNABLE实现:

void <init_cbk_runnable_name>(void)
void <jobend_cbk_runnable_name>( NvM_ServiceIdType ServiceId,NvM_RequestResultType JobResult)

然而,3.8版本的DaVinci开发者以及4.04.00及之后的MICROSAR RTE版本使NVM支持另一个不同(实际上不兼容)的函数原型:

Std_ReturnType <init_cbk_runnable_name>(void)
Std_ReturnType <jobend_cbk_runnable_name>( NvM_ServiceIdType,ServiceId,NvM_RequestResultType JobResult)

两种实现都需要稍微不同的接口定义;他们可能被改编使用DaVinci Developer。从建模的角度来看,runnable必须根据与相关的Pport-Prototype相关联的接口来实现。

image-20221114133805157

Figure 6-2 A “Single Block Job End Notification” with return type Std_ReturnType

image-20221114134135246

Figure 6-3 A “Single Block Job End Notification” with return type void.

根据它们(计划的)RUNNABLEs的实现。当然,接口必须符合AUTOSAR的规则;这将可能的接口定义限制为这里提到的两个接口中的一个。

6.2 Configuration of NVM Attributes 配置NVM属性

NVM属性可以使用DaVinci配置器(DaVinci Configurator)配置。配置和生成过程的输出是配置源文件。每个使用的参数的描述都在NvM bswmd 文件中设置。

本章只提供额外的信息。

sizeof-operator不能在生产环境代码的配置过程中使用,因为大小也会影响底层,即NVRAM块的确切大小,因此必须在配置时知道数据结构。因此,您需要自己确定这些值。这导致了一些重大的缺陷:

  • 基本数据类型的大小是平台相关的。要处理这个问题,应该只使用Std_Types.h(分别是Platform_Types.h)中定义的AUTOSAR数据类型。它们被定义为在所有平台上具有相同的大小。枚举类型的大小还取决于平台、编译器及其选项。注意编译器实际选择的大小。enum通常默认等于int,但你可以强制它是最小的可能类型(例如char)。

  • 要知道位域的组成。它可能会受到编译器开关的影响。

  • 编译器可以重排结构的成员以节省内存。最好的解决方案是根据成员的类型手动安排成员。编译器可以添加未使用的填充字节,以增加对结构成员的可访问性。根据前面的事实,应该对结构的成员进行排序。这样做,你应该知道对齐的开始地址为更大的整数数据类型(例如uint16uint32),根据CPU的需求访问它们。

  • 如上所述,一些编译器开关会影响数据类型的大小。

    请记住,更改这些参数可能会导致数据块的大小发生变化,从而导致NVM的重新配置。确定块大小的一个好方法是从链接器文件或生成的对象中提取所需的信息。

6.2.1 NvM Block Use Set Ram Block Status

服务NvM_SetRamBlockStatus可以根据AUTOSAR规范4.2.2使用。这允许在组件配置中提供每个NvBlock可配置的API。NvM将拒绝所有对NvBlocks的NvM_SetRamBlockStatus API的请求,因为NvBlocks禁用了NvMBlockUseSetRamBlockStatus配置参数。只有在配置中启用了全局NvMSetRamBlockStatusApi时,才能使用此功能。

6.2.2 NvM Invoke Callbacks For Read/Write All

参数NvMInvokeCallbacksForReadAllNvMInvokeCallbacksForWriteAll用于控制在NvM_ReadAll/NvM_WriteAll期间是否调用配置的单块回调。调用的回调函数可以通过参数NvMSingleBlockCallback和/或NvMSingleBlockCallbackExtended来配置。

6.2.3 NvM Using MAC as data integrity mechanism

为了使MAC作为一个块的数据完整性机制,需要配置三个参数。

  1. NvMCsmMacGenerationJobReferenceNvMCsmMacVerificationJobReference都必须引用所需的CSM作业来生成和验证块的mac。
  2. 被引用的作业本身必须引用正确的CsmPrimitives (CsmMacGenerateCsmMacVerify),其中处理必须设置为CSM_SYNCHRONOUS(当前的NvM实现仅支持同步CSM作业)。
  3. 第三个参数NvMCsmMacSize指定了由块数据生成的MAC的实际大小。

7 AUTOSAR Standard Compliance 符合AUTOSAR标准

7.1 Deviations 差异

  1. 与AUTOSAR相比,大多数配置都是link-time parameters。
  2. 存储当前块的RAM CRC是配置相关的。它要么保存在块数据后面,要么由NVM内部保存在自己的变量中。
  3. 统一处理所有块管理类型的ROM默认值。Rom默认处理数据集类型的块就像处理其他管理类型的块一样。
  4. NVM能够自己提供配置Id的RAM块。
  5. NvM_WriteAll()不会写入未改变的数据,即使这将修复(冗余/redundant))NV数据。
  6. 试图写入一个锁定的块(NvM_SetBlockLockStatus)不会被视为开发错误。错误NVM_E_BLOCK_LOCKED没有定义。
  7. NvM_SetBlockLockStatus允许处理待决的块。不会执行相关的开发错误检查。
  8. 不支持块CRC类型CRC8。
  9. 写重试只能全局配置,而不是每个NVRAM块单独配置。
  10. 对显式同步回调(参见3.4.20章)的调用不能被配置限制。相反,这些功能有望在几次尝试中获得成功。

7.2 Additions/ Extensions

7.2.1 Parameter Checking参数检测

API函数的内部参数检查可以单独禁用。AUTOSAR标准只要求en-/disabling完整的参数检查。请参见3.5.1.1章(TODO)。

7.2.2 Concurrent access to NV data并发访问NV数据

NVM为DCM提供了与NVM应用程序并发访问NV数据的可能性。(参见3.4.19章)

7.2.3 RAM-/ROM Block Size checks

NVM可以配置为根据相应的NV块长度检查所有RAM和ROM块的长度,使用sizeof操作符;参见第3.5.3章(TODO)

7.2.4 Calculated CRC value does not depend on number of calculation steps计算出的CRC值与计算步数无关

由于指定了CRC32算法,并且缺少对NVM的CRC计算的进一步要求,计算出的CRC32值取决于必要的计算步骤数(由块长度和每个周期的参数CRC字节数定义)。除非CRC可以一步计算(即块足够小),否则CRC32值将与调用CRC32库函数产生的值不匹配。

原因是对结果的否定,正如CRC32所规定的那样(它又属于标准的/广泛使用的以太网CRC)。这种行为给NVM带来了一些缺点,特别是:

  1. 在不知道配置的情况下,在现有(已加载)项目中,更改每个周期的参数CRC字节数(用于运行时优化)。在更新之后,无法读取具有CRC32的数据块。
  2. CRC32的值不能在NVM之外进行验证(例如用于测试)——每个步骤都必须重新生成。
  3. 有效的数据块及其CRC32不能使用标准CRC算法预先定义

NVM通过还原除最后一步以外的每个CRC32计算步骤的最终求反,绕过了这些限制。这种(非常简单)度量保证CRC值不依赖于计算步骤的数量,因为CRC16最初保证了这一点(因为它不会被CRC库倒排)。

7.3 Limitations 限制

8 Glossary and Abbreviations 词汇和缩略语

8.1 Glossary

TermDescription
DaVinci Configurator ProMICROSAR的配置和生成工具。
Primary NV Block冗余型NVRAM块的第一个NV块。在读取过程中,总是首先尝试该块。在写操作期间,除非只有secondary有缺陷,否则优先选择它。
Secondary NV Block冗余型NVRAM块的第二NV块。在读取时,该块将被立即访问;如果初级是有缺陷的。

8.2 Abbreviations

AbbreviationDescription
APIApplication Programming Interface 应用程序接口
AUTOSARAutomotive Open System Architecture 汽车开放系统体系结构
BSWBasis Software基础软件
CRCCyclic Redundancy Check 循环冗余校验
CSMCrypto Service manager 加密服务管理器
DCMDiagnostic Communication Manager 诊断通信管理器
DEMDiagnostic Event Manager诊断事件管理器
DETDevelopment Error Tracer
DPADaVinci Project Assistant
EAEEPROM Abstraction Module/EEPROM抽象模块
ECUElectronic Control Unit
ECUCECU Configuration
ECUMECU State Manager
EEPEEPROM Driver
EEPROMElectrically Erasable Programmable Read Only Memory
FEEFlash EEPROM Emulation Module
FIFOFirst In First Out
FLSFlash Driver
GCEGeneric Configuration Editor – generic tool for editing AUTOSAR
configuration files.
In DaVinci Configurator, the view can be switch to Generic Editor.
HISHersteller Initiative Software
ISRInterrupt Service Routine
MACMessage Authentication Code
MemHwAMemory Hardware Abstraction Layer

入未改变的数据,即使这将修复(冗余/redundant))NV数据。
6. 试图写入一个锁定的块(NvM_SetBlockLockStatus)不会被视为开发错误。错误NVM_E_BLOCK_LOCKED没有定义。
7. NvM_SetBlockLockStatus允许处理待决的块。不会执行相关的开发错误检查。
8. 不支持块CRC类型CRC8。
9. 写重试只能全局配置,而不是每个NVRAM块单独配置。
10. 对显式同步回调(参见3.4.20章)的调用不能被配置限制。相反,这些功能有望在几次尝试中获得成功。

7.2 Additions/ Extensions

7.2.1 Parameter Checking参数检测

API函数的内部参数检查可以单独禁用。AUTOSAR标准只要求en-/disabling完整的参数检查。请参见3.5.1.1章(TODO)。

7.2.2 Concurrent access to NV data并发访问NV数据

NVM为DCM提供了与NVM应用程序并发访问NV数据的可能性。(参见3.4.19章)

7.2.3 RAM-/ROM Block Size checks

NVM可以配置为根据相应的NV块长度检查所有RAM和ROM块的长度,使用sizeof操作符;参见第3.5.3章(TODO)

7.2.4 Calculated CRC value does not depend on number of calculation steps计算出的CRC值与计算步数无关

由于指定了CRC32算法,并且缺少对NVM的CRC计算的进一步要求,计算出的CRC32值取决于必要的计算步骤数(由块长度和每个周期的参数CRC字节数定义)。除非CRC可以一步计算(即块足够小),否则CRC32值将与调用CRC32库函数产生的值不匹配。

原因是对结果的否定,正如CRC32所规定的那样(它又属于标准的/广泛使用的以太网CRC)。这种行为给NVM带来了一些缺点,特别是:

  1. 在不知道配置的情况下,在现有(已加载)项目中,更改每个周期的参数CRC字节数(用于运行时优化)。在更新之后,无法读取具有CRC32的数据块。
  2. CRC32的值不能在NVM之外进行验证(例如用于测试)——每个步骤都必须重新生成。
  3. 有效的数据块及其CRC32不能使用标准CRC算法预先定义

NVM通过还原除最后一步以外的每个CRC32计算步骤的最终求反,绕过了这些限制。这种(非常简单)度量保证CRC值不依赖于计算步骤的数量,因为CRC16最初保证了这一点(因为它不会被CRC库倒排)。

7.3 Limitations 限制

8 Glossary and Abbreviations 词汇和缩略语

8.1 Glossary

TermDescription
DaVinci Configurator ProMICROSAR的配置和生成工具。
Primary NV Block冗余型NVRAM块的第一个NV块。在读取过程中,总是首先尝试该块。在写操作期间,除非只有secondary有缺陷,否则优先选择它。
Secondary NV Block冗余型NVRAM块的第二NV块。在读取时,该块将被立即访问;如果初级是有缺陷的。

8.2 Abbreviations

AbbreviationDescription
APIApplication Programming Interface 应用程序接口
AUTOSARAutomotive Open System Architecture 汽车开放系统体系结构
BSWBasis Software基础软件
CRCCyclic Redundancy Check 循环冗余校验
CSMCrypto Service manager 加密服务管理器
DCMDiagnostic Communication Manager 诊断通信管理器
DEMDiagnostic Event Manager诊断事件管理器
DETDevelopment Error Tracer
DPADaVinci Project Assistant
EAEEPROM Abstraction Module/EEPROM抽象模块
ECUElectronic Control Unit
ECUCECU Configuration
ECUMECU State Manager
EEPEEPROM Driver
EEPROMElectrically Erasable Programmable Read Only Memory
FEEFlash EEPROM Emulation Module
FIFOFirst In First Out
FLSFlash Driver
GCEGeneric Configuration Editor – generic tool for editing AUTOSAR
configuration files.
In DaVinci Configurator, the view can be switch to Generic Editor.
HISHersteller Initiative Software
ISRInterrupt Service Routine
MACMessage Authentication Code
MemHwAMemory Hardware Abstraction Layer
  • 36
    点赞
  • 230
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

义薄云天us

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

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

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

打赏作者

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

抵扣说明:

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

余额充值