AUTOSAR进阶图解==>AUTOSAR_SRS_MemoryHWAbstractionLayer

AUTOSAR 内存硬件抽象层 (MemHwA) 详解

基于AUTOSAR标准的内存硬件抽象层架构、组件和接口分析

目录

  1. 概述
  2. 内存硬件抽象层架构
  3. 虚拟地址空间与物理地址空间映射
  4. 组件与接口详解
  5. 写入操作序列
  6. 配置需求
  7. 总结

1. 概述

AUTOSAR(汽车开放系统架构)内存硬件抽象层(Memory Hardware Abstraction Layer, MemHwA)是AUTOSAR基础软件中的关键组成部分,它为上层软件提供了对非易失性存储器(如EEPROM和Flash)的统一访问接口,屏蔽了底层硬件的差异。

内存硬件抽象层主要由以下模块组成:

  • EEPROM抽象(EA)模块:抽象底层EEPROM驱动,提供虚拟分段和线性地址空间
  • Flash EEPROM模拟(FEE)模块:在Flash技术上模拟EEPROM行为
  • 内存抽象接口(MemIf)模块:为上层提供统一的接口,抽象底层的EA和FEE模块

这些模块共同工作,为NVRAM管理器提供一个统一的接口,使应用程序能够方便地访问非易失性存储器,而不必关心底层硬件的细节。


2. 内存硬件抽象层架构

在这里插入图片描述

架构组件解释

NVRAM Manager(应用层)
  • 功能:非易失性RAM管理器,位于应用层,是上层应用访问非易失性存储的接口
  • 职责
    • 管理非易失性数据的读写操作
    • 提供数据一致性保证
    • 处理块管理和CRC校验
Memory Abstraction Interface(内存硬件抽象层)
  • 功能:内存抽象接口,替代了驱动接口层
  • 职责
    • 允许NVRAM管理器访问多个内存抽象模块
    • 提供统一的地址空间
    • 转发请求到适当的底层模块(FEE或EA)
EEPROM Abstraction(内存硬件抽象层)
  • 功能:EEPROM抽象层,为上层提供统一的EEPROM访问方式
  • 职责
    • 提供虚拟分段和线性地址空间
    • 支持"几乎无限"的擦写周期
    • 抽象底层EEPROM驱动和设备的差异
Flash EEPROM Emulation(内存硬件抽象层)
  • 功能:Flash EEPROM模拟,在闪存技术上模拟EEPROM行为
  • 职责
    • 提供与EA相同的功能和API
    • 管理闪存磨损均衡
    • 处理块对齐和地址映射
内存驱动层
  • EEPROM Driver:直接操作EEPROM硬件
  • Flash Driver:直接操作Flash硬件
  • Vendor Specific Library:特定供应商库,可替代FEE/EA模块,只要提供相同的功能和API接口

关键架构特点

  1. 分层设计:清晰的分层结构,每层职责明确
  2. 硬件独立性:上层应用不依赖于具体硬件
  3. 接口统一:无论底层是EEPROM还是Flash,都提供统一的接口
  4. 可配置性:支持灵活配置,适应不同硬件
  5. 可替代性:组件可以被特定供应商库替代,只要保持API一致

3. 虚拟地址空间与物理地址空间映射

在这里插入图片描述

虚拟地址结构解释

32位虚拟地址
  • 功能:FEE和EA模块提供的虚拟32位地址空间

  • 结构

    • 16位逻辑块ID (0x0001-0xFFFE):唯一标识一个逻辑块
    • 16位块内偏移量 (0x0000-0xFFFF):块内数据的偏移地址
  • 特点

    • 支持最多65534个逻辑块(0x0000和0xFFFF被保留)
    • 每个块最大可达64KB
    • 抽象了底层物理存储器的地址空间
物理地址空间
  • 功能:底层实际的存储器地址空间
  • 特点
    • 页是最小可写单元
    • 扇区是最小可擦除单元
    • 支持地址对齐配置
逻辑块
  • 功能:内存抽象层管理的基本单位

  • 属性

    • 块ID:16位唯一标识符
    • 块大小:以字节为单位的大小
    • 起始/结束地址:支持配置对齐方式
    • 擦写次数要求:可配置所需的擦写次数
  • 特点

    • 支持配置所需的擦写次数
    • 地址边界对齐可配置
    • 模块自动处理物理磨损平衡

地址映射代码示例

/* 虚拟地址定义 */
typedef struct {
    uint16 BlockId;    /* 逻辑块ID (0x0001-0xFFFE) */
    uint16 Offset;     /* 块内偏移量 */
} MemIf_VirtualAddressType;

/* 逻辑块配置结构 */
typedef struct {
    uint16 BlockNumber;       /* 逻辑块编号 */
    uint16 BlockSize;         /* 块大小(字节) */
    uint16 WriteCyclesLimit;  /* 所需擦写周期数 */
    uint8 AddressAlignment;   /* 地址对齐要求 */
} Fee_BlockConfigType;

/* 物理地址映射示例函数 */
Std_ReturnType Fee_ConvertVirtualToPhysicalAddress(
    MemIf_VirtualAddressType VirtualAddress,
    uint32* PhysicalAddressPtr)
{
    uint16 blockId = VirtualAddress.BlockId;
    uint16 offset = VirtualAddress.Offset;
    Fee_BlockConfigType* blockConfig;
    uint32 physicalAddress;
    
    /* 检查块ID有效性 */
    if (blockId == 0x0000 || blockId == 0xFFFF) {
        return E_NOT_OK;  /* 无效的块ID */
    }
    
    /* 获取块配置 */
    blockConfig = Fee_GetBlockConfig(blockId);
    if (blockConfig == NULL) {
        return E_NOT_OK;  /* 未找到块配置 */
    }
    
    /* 检查偏移量有效性 */
    if (offset >= blockConfig->BlockSize) {
        return E_NOT_OK;  /* 偏移量超出块大小 */
    }
    
    /* 计算物理地址(示例算法,实际实现会更复杂) */
    physicalAddress = Fee_GetBlockStartAddress(blockId) + offset;
    
    /* 返回物理地址 */
    *PhysicalAddressPtr = physicalAddress;
    
    return E_OK;
}

4. 组件与接口详解

组件接口解释

Memory Abstraction Interface (MemIf)
  • 功能:提供统一的接口,抽象底层多个FEE或EA模块
  • 主要接口
    • MemIf_Init:初始化内存抽象接口
    • MemIf_Read:读取数据块
    • MemIf_Write:写入数据块
    • MemIf_Erase:擦除数据块
    • MemIf_GetStatus:获取当前作业状态
    • MemIf_GetJobResult:获取上一个作业结果
    • MemIf_InvalidateBlock:使数据块无效
    • MemIf_Cancel:取消当前作业
    • MemIf_GetVersionInfo:获取版本信息
EEPROM Abstraction (EA)
  • 功能:抽象底层EEPROM驱动,提供虚拟分段和线性地址空间
  • 主要接口
    • EA_Init:初始化EEPROM抽象层
    • EA_Read:读取数据
    • EA_Write:写入数据
    • EA_Erase:擦除数据
    • EA_GetStatus:获取当前作业状态
    • EA_GetJobResult:获取上一个作业结果
    • EA_InvalidateBlock:使数据块无效
    • EA_Cancel:取消当前作业
    • EA_GetVersionInfo:获取版本信息
    • EA_MainFunction:周期性处理函数
Flash EEPROM Emulation (FEE)
  • 功能:在闪存技术上模拟EEPROM行为
  • 主要接口
    • FEE_Init:初始化Flash EEPROM模拟层
    • FEE_Read:读取数据
    • FEE_Write:写入数据
    • FEE_Erase:擦除数据
    • FEE_GetStatus:获取当前作业状态
    • FEE_GetJobResult:获取上一个作业结果
    • FEE_InvalidateBlock:使数据块无效
    • FEE_Cancel:取消当前作业
    • FEE_GetVersionInfo:获取版本信息
    • FEE_MainFunction:周期性处理函数

接口详细描述和代码示例

/* 内存抽象接口状态定义 */
typedef enum {
    MEMIF_UNINIT = 0,      /* 模块未初始化 */
    MEMIF_IDLE,            /* 模块空闲 */
    MEMIF_BUSY,            /* 模块正在处理作业 */
    MEMIF_BUSY_INTERNAL    /* 模块内部处理中 */
} MemIf_StatusType;

/* 作业结果状态 */
typedef enum {
    MEMIF_JOB_OK = 0,         /* 作业成功完成 */
    MEMIF_JOB_FAILED,         /* 作业失败 */
    MEMIF_JOB_PENDING,        /* 作业正在处理 */
    MEMIF_JOB_CANCELED,       /* 作业被取消 */
    MEMIF_BLOCK_INCONSISTENT, /* 数据块不一致 */
    MEMIF_BLOCK_INVALID       /* 数据块无效 */
} MemIf_JobResultType;

/* 内存抽象接口模块定义 */
typedef enum {
    MEMIF_FEE_INSTANCE_0 = 0, /* FEE实例0 */
    MEMIF_EA_INSTANCE_0       /* EA实例0 */
} MemIf_DeviceIndexType;

/* Memory Abstraction Interface API示例 */
Std_ReturnType MemIf_Read(
    MemIf_DeviceIndexType DeviceIndex,
    uint16 BlockNumber,
    uint16 BlockOffset,
    uint8* DataBufferPtr,
    uint16 Length)
{
    /* 根据设备索引转发请求到相应的底层模块 */
    switch (DeviceIndex) {
        case MEMIF_FEE_INSTANCE_0:
            return Fee_Read(BlockNumber, BlockOffset, DataBufferPtr, Length);
        
        case MEMIF_EA_INSTANCE_0:
            return Ea_Read(BlockNumber, BlockOffset, DataBufferPtr, Length);
            
        default:
            return E_NOT_OK;
    }
}

/* EEPROM Abstraction模块接口示例 */
Std_ReturnType Ea_Write(
    uint16 BlockNumber,
    uint8* DataBufferPtr)
{
    Ea_BlockConfigType* blockConfig;
    
    /* 检查模块是否已初始化 */
    if (Ea_Status == EA_UNINIT) {
        Ea_JobResult = MEMIF_JOB_FAILED;
        return E_NOT_OK;
    }
    
    /* 检查是否有作业正在进行 */
    if (Ea_Status != EA_IDLE) {
        return E_NOT_OK;
    }
    
    /* 获取块配置 */
    blockConfig = Ea_GetBlockConfig(BlockNumber);
    if (blockConfig == NULL) {
        Ea_JobResult = MEMIF_JOB_FAILED;
        return E_NOT_OK;
    }
    
    /* 更新模块状态并启动写入作业 */
    Ea_Status = EA_BUSY;
    Ea_JobResult = MEMIF_JOB_PENDING;
    Ea_JobType = EA_JOB_WRITE;
    Ea_CurrentBlockNumber = BlockNumber;
    Ea_CurrentDataPtr = DataBufferPtr;
    
    /* 返回挂起状态,实际写入将在Ea_MainFunction中处理 */
    return E_OK;
}

5. 写入操作序列

在这里插入图片描述

写入操作序列解释

参与者说明
  • NVRAM Manager:非易失性RAM管理器,负责协调数据的读写操作
  • Memory Abstraction Interface:内存抽象接口,提供统一访问接口
  • Flash EEPROM Emulation:Flash EEPROM模拟,处理闪存的读写操作
  • Flash Driver:闪存驱动,直接操作闪存硬件
写入操作流程
  1. 操作发起

    • NVRAM Manager调用MemIf_Write函数,指定设备索引、块号、数据指针和长度
    • Memory Abstraction Interface根据设备索引转发请求到相应的底层模块(FEE或EA)
  2. 请求处理

    • FEE模块接收写入请求,将逻辑块ID转换为内部管理的块结构
    • 检查块大小是否符合配置,并将虚拟地址转换为物理地址
    • 设置内部状态为BUSY,开始异步写入操作
  3. 异步处理

    • FEE调用Flash Driver的Flash_Write函数,开始实际的写入操作
    • Flash Driver返回FLASH_E_PENDING,表示操作已开始但尚未完成
    • FEE返回MEMIF_JOB_PENDING,表示作业正在进行
    • NVRAM Manager记录操作状态为待处理
  4. 状态轮询

    • NVRAM Manager循环调用MemIf_GetStatus检查操作状态
    • Memory Abstraction Interface转发请求到FEE模块
    • FEE查询Flash Driver的作业状态
  5. 操作完成

    • 当Flash Driver完成写入操作,返回FLASH_E_OK
    • FEE更新内部状态为IDLE,并更新块的磨损计数
    • NVRAM Manager检测到状态为MEMIF_IDLE,调用MemIf_GetJobResult获取操作结果
    • 根据返回结果(E_OK或E_NOT_OK)确定操作是否成功

写入操作代码示例

/* NVRAM Manager中的写入函数示例 */
Std_ReturnType NvM_WriteBlock(
    NvM_BlockIdType BlockId,
    const void* NvM_SourceDataPtr)
{
    uint8 deviceIndex;
    uint16 blockNumber;
    MemIf_StatusType status;
    MemIf_JobResultType result;
    Std_ReturnType ret;
    
    /* 获取块配置 */
    const NvM_BlockDescriptorType* blockDescriptor = NvM_GetBlockDescriptor(BlockId);
    if (blockDescriptor == NULL) {
        return E_NOT_OK;
    }
    
    /* 获取设备索引和块号 */
    deviceIndex = blockDescriptor->DeviceIndex;
    blockNumber = blockDescriptor->BlockNumber;
    
    /* 调用MemIf写入函数 */
    ret = MemIf_Write(deviceIndex, blockNumber, NvM_SourceDataPtr);
    if (ret != E_OK) {
        return E_NOT_OK;
    }
    
    /* 等待操作完成 */
    do {
        /* 延时或任务切换,取决于系统配置 */
        NvM_TaskDelay();
        
        /* 获取当前状态 */
        status = MemIf_GetStatus(deviceIndex);
        
        if (status == MEMIF_IDLE) {
            /* 操作已完成,获取结果 */
            result = MemIf_GetJobResult(deviceIndex);
            
            if (result == MEMIF_JOB_OK) {
                return E_OK;
            } else {
                /* 处理错误情况 */
                return E_NOT_OK;
            }
        }
    } while (status == MEMIF_BUSY || status == MEMIF_BUSY_INTERNAL);
    
    /* 如果循环退出但状态不是IDLE,则出现了未预期的错误 */
    return E_NOT_OK;
}

6. 配置需求

内存硬件抽象层的配置需求主要包括逻辑块配置、地址对齐要求和擦写周期设置等方面。以下是这些配置的详细说明:

逻辑块配置

根据源文档需求[SRS_MemHwAb_14001],FEE和EA模块需要支持逻辑块起始和结束地址的对齐配置:

typedef struct {
    uint16 BlockNumber;         /* 逻辑块编号(0x0001-0xFFFE) */
    uint16 BlockSize;           /* 块大小(字节) */
    uint8 AddressAlignment;     /* 地址对齐要求(字节) */
    boolean ImmediateData;      /* 是否为即时数据 */
    uint16 WriteCyclesLimit;    /* 所需擦写周期数 */
} Fee_BlockConfigType;

/* 块配置示例 */
const Fee_BlockConfigType Fee_BlockConfig[] = {
    /* BlockNumber, BlockSize, AddressAlignment, ImmediateData, WriteCyclesLimit */
    {1, 16, 4, FALSE, 10000},   /* 块1: 16字节,4字节对齐,非即时数据,10000擦写周期 */
    {7, 32, 4, TRUE, 50000},    /* 块7: 32字节,4字节对齐,即时数据,50000擦写周期 */
    {8, 64, 8, FALSE, 5000}     /* 块8: 64字节,8字节对齐,非即时数据,5000擦写周期 */
};

擦写周期需求

根据源文档需求[SRS_MemHwAb_14002],FEE和EA模块需要支持每个逻辑块所需擦写周期数的配置:

  • 这允许模块抽象底层物理设备的硬件特性
  • 即使底层物理设备只支持有限的擦写周期,模块也能够提供更多的擦写次数
  • 模块通过磨损均衡算法来实现这一功能

块号限制

根据源文档需求[SRS_MemHwAb_14026],块号0x0000和0xFFFF不能被内存抽象模块使用:

  • 这些块号无法与闪存或EEPROM的擦除值区分开
  • 配置工具在生成块号时必须避免使用这些值
  • 这些限制确保了块号的唯一性和可识别性

地址空间配置

根据源文档需求[SRS_MemHwAb_14005],FEE和EA模块需要提供32位虚拟地址空间:

  • 32位虚拟地址包括16位逻辑块标识符和16位块内偏移量
  • 支持最多65534个逻辑块(0x0001-0xFFFE)
  • 每个块最大可达64KB

7. 总结

AUTOSAR内存硬件抽象层(MemHwA)通过提供统一的接口和抽象层,有效解决了不同非易失性存储技术之间的差异,为上层软件提供了一致的访问方式。

主要特点

  • 硬件独立性:抽象底层硬件差异,提供统一接口
  • 扩展擦写周期:通过软件实现"几乎无限"的擦写次数
  • 灵活配置:支持逻辑块、地址对齐和擦写周期的灵活配置
  • 异步操作:支持异步读写操作,提高系统效率
  • 状态管理:提供完善的状态和错误管理机制

应用优势

  1. 可移植性:应用可以在不同硬件平台上移植,无需修改
  2. 延长寿命:通过磨损均衡算法延长存储器寿命
  3. 简化开发:开发人员无需关心底层存储技术细节
  4. 标准化:符合AUTOSAR标准,保证系统兼容性

内存硬件抽象层作为AUTOSAR架构中的关键组件,为汽车电子系统提供了可靠、高效的非易失性数据存储解决方案,是现代汽车电子控制单元(ECU)中不可或缺的部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

KaiGer666

慧眼~施主!!!

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

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

打赏作者

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

抵扣说明:

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

余额充值