0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

NVM Block连续写及Default Value问题分析

832065824 来源:汽车电子嵌入式 2023-07-25 14:22 次阅读

前言

NVM这块还只停留在按需求配置阶段,遇到问题不能深入分析。本系列文章将从遇到的问题或者提出的疑问着手,一起来更深入学习AUTOSAR架构下的存储协议栈。目前遇到的问题和疑问如下:

1.通过RTE接口连续读写NVMBlock会影响其他Block的读写吗?

2.没有配置NVMRom Block的default value且没有写过NVM Block,通过RTE接口去读NVMBlock读到的是什么值?

3.Fee模块中的Block的长度更改会造成NVM Block在Flash中重排吗?中间插入NVMBlock了?

本文使用的AUTOSAR配置工具为:Vector公司的Davinci工具

正文

1.应用SWC读写NVMBlock的两种方式

入下图所示,Vector的AUTOAR配置工具Davinci Developer提供两种方式配置SWC使用NVM的服务。

方式一:SWC和NVM直连。NVM提供5个标准接口供SWC使用,SWC可以直接通过C-S接口直接读写NVMBlock。这种方式适用于NVMBlock仅被一个SWC访问的场景

209011d6-2a7f-11ee-a368-dac502259ad0.png

图1:SWC和NVM直连

如下图所示,在Developer中直接配置SWC中的Service Need的NvM_Block_NeeDs即可配置NVM服务。

2103632a-2a7f-11ee-a368-dac502259ad0.png

图2:配置NvMBlockNeed

最后在Rte_SWC.h生成的读写NvM_Block的接口如下所示,Rte接口直接封装了NvM的标准接口(NvM_ReadBlock, NvM_WriteBlock, NvM_GetErrorStates)。

# define Rte_Call_NvMService_AC3_SRBS_NvBlockNeed_ PortName _GetErrorStatus(arg1) (NvM_GetErrorStatus((NvM_BlockIdType)57, arg1))
# define Rte_Call_NvMService_AC3_SRBS_NvBlockNeed_ PortName _ReadBlock(arg1) (NvM_ReadBlock((NvM_BlockIdType)57, arg1))
# define Rte_Call_NvMService_AC3_SRBS_NvBlockNeed_ PortName _WriteBlock(arg1) (NvM_WriteBlock((NvM_BlockIdType)57, arg1))

方式二:SWC通过NonvolatileMemoryBlock访问NVM。Davinci提供一个类似NvM User的NonvolatileMemoryBlock的中间模块,SWC配置普通的S-R接口和NonvolatileMemoryBlock连接,NonvolatileMemoryBlock模块通过标准的S-R接口和NvM连接。SWC通过NonvolatileMemoryBloc来读写NvM模块。这种方式适用于多个SWC访问同一个NvM Block的场景

213708f6-2a7f-11ee-a368-dac502259ad0.png

图3:SWC通过NonvolatileMemoryBlock访问NVM

如下图所示,使用方式二需要配置中间NonvolatileMemoryBlock模块,然后在SWC和NonvolatileMemoryBlock分别配置S-R的读写接口,然后进行连接即可。

217557c8-2a7f-11ee-a368-dac502259ad0.png

图4:配置NoVolatileMemoryBlock

如下所示,生成的Rte_SWC.h中SWC读写NvM Block的接口仅仅是读写一个名为Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName全局变量。

FUNC(Std_ReturnType, RTE_CODE) Rte_Read_SWC_Pp_NvData_PortName_Rx_Element_NvData_PortName(P2VAR(uint8, AUTOMATIC, RTE_SWC_APPL_VAR) data) /* PRQA S 1505, 3206 */ /* MD_MSR_Rule8.7, MD_Rte_3206 */
{
  Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */
  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
  Rte_MemCpy(data, Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */
  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
  return ret;
}




FUNC(Std_ReturnType, RTE_CODE) Rte_Write_SWC_Pp_NvData_PortName_Tx_Element_NvData_PortName(P2CONST(uint8, AUTOMATIC, RTE_SWC_APPL_DATA) data) /* PRQA S 1505, 2982 */ /* MD_MSR_Rule8.7, MD_Rte_2982 */
{
  Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */
  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
  Rte_MemCpy(Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, data, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */
  Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 1U;
  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
  /* scheduled trigger for runnables: NonVolatileMemoryBlockTriggerRunnable */
  (void)SetEvent(AplTask_10ms_Core0, Rte_Ev_Run_NonVolatileMemoryBlock_NonVolatileMemoryBlockTriggerRunnable); /* PRQA S 3417 */ /* MD_Rte_Os */
  return ret;
}

然后NvM也通过Rte_SetMirror_xxx/Rte_GetMirror_xxx接口来更新这个Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName全局变量。


FUNC(Std_ReturnType, RTE_CODE) Rte_SetMirror_NonVolatileMemoryBlock_NVBlockDescriptor_PortName(P2CONST(void, AUTOMATIC, RTE_APPL_DATA) NVMBuffer) /* PRQA S 3112 */ /* MD_Rte_3112 */
{
  Std_ReturnType ret = E_NOT_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */
  CONST(uint16_least, RTE_CONST) size = sizeof(NvData_PortName);
  if (size <= 100U) /* PRQA S 2991, 2995 */ /* MD_Rte_2991, MD_Rte_2995 */ /* COV_RTE_NVMBUFFER_SIZE */
  {
    Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
    Rte_MemCpy32(Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, NVMBuffer, size); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */
    Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
    ret = E_OK;
    }
  return ret;
}


FUNC(Std_ReturnType, RTE_CODE) Rte_GetMirror_NonVolatileMemoryBlock_NVBlockDescriptor_PortName(P2VAR(void, AUTOMATIC, RTE_APPL_VAR) NVMBuffer) /* PRQA S 3112 */ /* MD_Rte_3112 */
{
   Std_ReturnType ret = E_NOT_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */
  CONST(uint16_least, RTE_CONST) size = sizeof(NvData_PortName);
  if (size <= 100U) /* PRQA S 2991, 2995 */ /* MD_Rte_2991, MD_Rte_2995 */ /* COV_RTE_NVMBUFFER_SIZE */
  {
  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
  Rte_MemCpy32(NVMBuffer, Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, size); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */
  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
  ret = E_OK;
  }
  return ret;
}

2.RAMBlock和ROMBlock

RAMBlock最后在代码中体现就是一个全局变量(存放在栈Ram中),ROMBlock在代码中体现就是一个const 全局变量(存放在Data Flash中)。RamBlock是一定会有的,Rom Block是可配置的。其中最主要的就是default value的配置。

方式1配置RAMBlock和ROMBlock:

方式1是SWC通过NvM Block Needs直接访问NvM,如果配置了Default Value就配置了ROMBlock。

21af5d24-2a7f-11ee-a368-dac502259ad0.png

图5:NvM Block Needs配置RAM和ROM Block

方式2配置RAMBlock和ROMBlock:

方式2是SWC通过NonvolatileMemoryBlock间接访问NvM,Rom Block通过勾选来配置,InitValue也就是Default value也可配置。

21e64d0c-2a7f-11ee-a368-dac502259ad0.png

图5:NonvolatileMemoryBlock配置RAM和ROM Block

RAMBlock对应的代码:

VAR(Nvdata_PortName, RTE_VAR_INIT) Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName;

ROMBlock对应的代码:

CONST(Nvdata_PortName, RTE_CONST_DEFAULT_RTE_CDATA_GROUP) Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName_ROM_NVBlockDescriptor_PortName = {
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U
};

关于Default Value:

22117446-2a7f-11ee-a368-dac502259ad0.png

如SWS_NvM_00388所诉,在ECU启动阶段,如果配置了ROMBlock,NvM_ReadAll会把ROMblock中的default value拷贝到RAMBlock。

22411eb2-2a7f-11ee-a368-dac502259ad0.png

如SWS_NvM_00085所述,如果没有配置ROMBlock,则RAMBlock的值需要应用来保证。在Davinci Developer中可以配置RAM Block的Init Value,也可以让RAMBlock有一个初始值。

如果,我们既没有配置RAMBlock的Initvalue,也没有配置ROMBlock,也从没有写过NvBlock,那么我们第一次去读的RAMBlock是.BSS段的一个全局变量(未初始化的全局变量在.BSS段),而MCU上电后会对.BSS段作清零的操作,也就是说我们会读到0。

3. 应用SWC读写NVM过程

SWC通过NonvolatileMemoryBlock读NvM Ram Block:SWC就是读一个名为Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName的全局变量,也就是RAMBlock。

FUNC(Std_ReturnType, RTE_CODE) Rte_Read_SWC_Pp_NvData_PortName_Rx_Element_NvData_PortName(P2VAR(uint8, AUTOMATIC, RTE_SWC_APPL_VAR) data) /* PRQA S 1505, 3206 */ /* MD_MSR_Rule8.7, MD_Rte_3206 */
{
  Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */
  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
  Rte_MemCpy(data, Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */
  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
  return ret;
}

SWC通过NonvolatileMemoryBlock写NvM Ram Block:SWC就是写一个名为Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName的全局变量,也就是RAMBlock。同时会设置一个更新Flag,SetEvent触发一个OSTask事件。

FUNC(Std_ReturnType, RTE_CODE) Rte_Write_SWC_Pp_NvData_PortName_Tx_Element_NvData_PortName(P2CONST(uint8, AUTOMATIC, RTE_SWC_APPL_DATA) data) /* PRQA S 1505, 2982 */ /* MD_MSR_Rule8.7, MD_Rte_2982 */
{
  Std_ReturnType ret = RTE_E_OK; /* PRQA S 2981 */ /* MD_MSR_RetVal */
  Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
  Rte_MemCpy(Rte_NonVolatileMemoryBlock_NVBlockDescriptor_PortName, data, sizeof(NvData_PortName)); /* PRQA S 0314, 0315, 0316 */ /* MD_Rte_0314, MD_Rte_0315, MD_Rte_0316 */
  Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 1U;
  Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
  /* scheduled trigger for runnables: NonVolatileMemoryBlockTriggerRunnable */
  (void)SetEvent(AplTask_10ms_Core0, Rte_Ev_Run_NonVolatileMemoryBlock_NonVolatileMemoryBlockTriggerRunnable); /* PRQA S 3417 */ /* MD_Rte_Os */
  return ret;
}

NonvolatileMemoryBlock的Runnable被Event事件激活调用NvM_WriteBlock:

RTE_LOCAL FUNC(void, RTE_CODE) NonVolatileMemoryBlockTriggerRunnable(void)
{
  if (Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName == 1U)
  {
    NvM_RequestResultType NvM_ErrorStatus = 0;
    (void)NvM_GetErrorStatus(NvMConf_NvMBlockDescriptor_NonVolatileMemoryBlockNVBlockDescriptor_PortName, &NvM_ErrorStatus);
    if (NvM_ErrorStatus != NVM_REQ_PENDING)
  {
    Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
    Rte_OsApplication_QM_Core0_DirtyFlags.Rte_DirtyFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 0;
    Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
    (void)NvM_WriteBlock(NvMConf_NvMBlockDescriptor_NonVolatileMemoryBlockNVBlockDescriptor_PortName, NULL_PTR);
  }
  else
  {
    Rte_DisableOSInterrupts(); /* PRQA S 1881, 4558 */ /* MD_Rte_Os, MD_Rte_Os */
    Rte_NvBlockPendingFlags.Rte_NvBlockPendingFlag_NonVolatileMemoryBlock_NVBlockDescriptor_PortName = 1U;
    Rte_EnableOSInterrupts(); /* PRQA S 1881, 4558, 2983 */ /* MD_Rte_Os, MD_Rte_Os, MD_Rte_2983 */
    }
  }
}

NvM_WriteBlock调用NvM_QueueJob将Job排队:

FUNC(Std_ReturnType, NVM_PUBLIC_CODE) NvM_WriteBlock(NvM_BlockIdType BlockId, P2CONST(void, AUTOMATIC, NVM_APPL_DATA) NvM_SrcPtr)
{
    Std_ReturnType returnValue = E_NOT_OK;
    uint8 detErrorId = NVM_E_NO_ERROR;


    const NvM_RamMngmtPtrType NvM_RamMngmt_ptloc = NvM_GetMngmtAreaPtr(BlockId);
    if(NvM_WriteProtectionChecks(NvM_RamMngmt_ptloc) == TRUE) /* SBSW_NvM_FuncCall_PtrParam_BlockMngmtArea */
    {
    /* PRQA S 0311, 0316 1 */ /* MD_NvM_11.5_CastLossOfConst, MD_NvM_11.5_JobQueue_CastVoidPtrToObjPtr */
    if (NvM_QueueJob(BlockId, NVM_INT_FID_WRITE_BLOCK, (NvM_RamAddressType)NvM_SrcPtr)) /* SBSW_NvM_FuncCall_PtrParam_QueueJob */
    {
if(NvM_SrcPtr==NULL_PTR)
    {
NvM_EnterCriticalSection();
NvM_RamMngmt_ptloc->NvRamAttributes_u8|=(NVM_STATE_VALID_SET|NVM_STATE_CHANGED_SET);/*SBSW_NvM_AccessBlockManagementArea*/
NvM_ExitCriticalSection();
    }
    returnValue = E_OK;
  }
}


return returnValue;
} 

NvM_QueueJob会判断队列是否已经Full,如果Full则Job被丢弃,如果没有Full,则Job入队列:

FUNC(boolean, NVM_PRIVATE_CODE) NvM_QueueJob(NvM_BlockIdType BlockId,
NvM_InternalServiceIdType ServiceId,
NvM_RamAddressType RamAddress
)
{
  boolean retVal = FALSE;
  boolean queueFull;
  boolean blockAlreadyPending;
  /* get block management area */
  const NvM_RamMngmtPtrType ramMngmtPtr =
  ((BlockId & NVM_DCM_BLOCK_OFFSET) != 0u) ? (&NvM_DcmBlockMngmt_t) : (&NvM_BlockMngmtArea_at[BlockId]);
  #if(NVM_JOB_PRIORISATION == STD_ON)
  const uint8 priority = (uint8)NvM_BlockDescriptorTable_at[NVM_BLOCK_FROM_DCM_ID(BlockId)].BlockPrio_u8;
  /* NvM_HighPrioQueue is only the right queue if block has an immediate priority, current job is a
  write-job and requested block is not a DCM-Block. Otherwise NvM_NormalPrioQueue is right queue. */
  P2VAR(NvM_JobQueueType, AUTOMATIC, NVM_PRIVATE_DATA) usedQueue =
  ((priority == 0u) && (ServiceId == NVM_INT_FID_WRITE_BLOCK) && ((BlockId & NVM_DCM_BLOCK_OFFSET) == 0u)) ?
  (&NvM_HighPrioQueue) : (&NvM_NormalPrioQueue);
  #else
  P2VAR(NvM_JobQueueType, AUTOMATIC, NVM_PRIVATE_DATA) usedQueue = &NvM_NormalPrioQueue;
  #endif
  /* #200 critical section (Reason: During accessing the job queue, it shall not be possible to access it from another task) */
  NvM_EnterCriticalSection();
  /* check queue fill status before queuing the block! */
  queueFull = (usedQueue->EmptyList == NVM_LIST_END);
  blockAlreadyPending = (ramMngmtPtr->NvRamErrorStatus_u8 == NVM_REQ_PENDING);
  /* #210 queue is not full and the requested block isn't already pending */
  if((queueFull == FALSE) && (blockAlreadyPending == FALSE))
  {
    /* #211 find next free element in queue */
    const NvM_QueueEntryRefType elem = NvM_QueuePop(&usedQueue->EmptyList); /* SBSW_NvM_FuncCall_PtrParam_Queue */
    CONSTP2VAR(NvM_QueueEntryType, AUTOMATIC, NVM_PRIVATE_DATA) elemPtr = &NvM_JobQueue_at[elem];
    /* #212 setup and queue NvM job */
    elemPtr->BlockId   = BlockId; /* SBSW_NvM_AccessJobQueue */
    elemPtr->RamAddr_t = RamAddress; /* SBSW_NvM_AccessJobQueue */
    elemPtr->ServiceId = ServiceId; /* SBSW_NvM_AccessJobQueue */
    #if(NVM_JOB_PRIORISATION == STD_ON)
    elemPtr->JobPrio = priority; /* SBSW_NvM_AccessJobQueue */
    #endif
    NvM_QueuePush(&usedQueue->SrvList, elem); /* SBSW_NvM_FuncCall_PtrParam_Queue */
    /* #213 set the block status to NVM_REQ_PENDING */
    ramMngmtPtr->NvRamErrorStatus_u8 = NVM_REQ_PENDING; /* SBSW_NvM_AccessBlockManagementArea */
    /* block queued and pending, return successfully */
    retVal = TRUE;
    }
  return retVal;
}

综上所述,SWC读写NvM接口的时候,其实读写的是一个Ram Block的全局变量。调用写NvM的接口时会触发NonvolatileMemoryBlock的NonVolatileMemoryBlockTriggerRunnableOs调用,NonVolatileMemoryBlockTriggerRunnable根据Block的写Flag调用NvM_WriteBlock,NvM_WriteBlock中调用NvM_QueueJobNvM_QueueJob根据队列是否Full来将Job入队列。

也就是说,如果有SWC一直在频繁的调用写NvM的接口,就会导致NvM的队列Full,导致其他的SWC的写NvM Block的请求被丢弃,最终对外表现是NvM存不进去。

Ps: 本人就遇到过队列大小配的太小,导致SWC的NvM写请求被丢弃的问题。。。

4. 问题回答

问题1:通过RTE接口连续读写NVMBlock会影响其他Block的读写吗?

答:会。如果SWC连续写NvM Block,且NvM模块的队列大小配置太小,就会导致NvM模块的队列Full后SWC的写请求被丢弃。

问题2:没有配置NVMRom Block的default value且没有写过NVM Block,通过RTE接口去读NVMBlock读到的是什么值?

答:要看有没有配置NvM Ram Block的InitValue。如果配置NvM Ram Block的InitValue,那么读到的就是NvM Ram Block的InitValue,如果没有配置,读到的就是0。

问题3:Fee模块中的Block的长度更改会是的NVM Block在Flash中重排吗?中间插入NVMBlock了?

答:还没研究透彻,请关注本公众号的后续文章。

5.总结

搞清楚了NVM的基本概念后,配置都比较容易。难的是出现问题后怎么查问题,因为NvM和Fee/EA,Fls/EEProm模块的实现还是很复杂的,常见的问题如下:

nSWC开发者抱怨NvM数据存不进去

nSWC开发者抱怨NvM数据在ECU复位变成了默认值

nSWC开发者抱怨NvM数据在ECU复位后改成了异常值

如果,存储协议栈配置本身没有问题,常见的原因如下:

nNvM队列配置太小,以及SWC在频繁的请求写NvM

nSWC在下电前把自己的Block写成了默认值,这个时候,我们可以通过修改NvM Block的Default Value为另一个值来证明不是NvM本身的问题,是SWC自己写了个Default value。

n用来接收NvM读数据的SWC的全局变量复位后并不是直接从NvM读取数据,而是从Back Ram(复位后内容不清除)中读取数据,Back Ram异常后导致接收NvM数据的全局变量内容错乱。

如果不是以上的问题,那就可能是NvM本身或者ECU系统出问题了,这就需要深入分析NvM源码加调试了。





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RAM
    RAM
    +关注

    关注

    7

    文章

    1321

    浏览量

    113706
  • AUTOSAR
    +关注

    关注

    9

    文章

    329

    浏览量

    21130
  • ecu
    ecu
    +关注

    关注

    14

    文章

    821

    浏览量

    53883
  • NVM
    NVM
    +关注

    关注

    1

    文章

    37

    浏览量

    19053
  • Flash单片机
    +关注

    关注

    0

    文章

    111

    浏览量

    9294

原文标题:AUTOSAR架构下NVM Block连续写及Default Value问题分析

文章出处:【微信号:汽车电子嵌入式,微信公众号:汽车电子嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    NVRAM Manager(NVM)模块详细介绍

    存储协议栈负责ECU中非易失性数据的存储管理。存储协议栈的分享包括NVM、MemI、Ea、Fea、Eep、Fls模块的详细介绍及代码分析,具体的项目实战请关注本号的后续文章,本篇为NVRAM Manager(NVM)模块详细介绍
    发表于 09-06 09:16 4759次阅读

    NVRAM Manager(NVM)模块详细介绍

    存储协议栈负责ECU中非易失性数据的存储管理。存储协议栈的分享包括NVM、MemI、Ea、Fea、Eep、Fls模块的详细介绍及代码分析,具体的项目实战请关注本号的后续文章,本篇为NVRAM Manager(NVM)模块详细介绍
    发表于 09-15 11:43 4297次阅读

    错误7发生于Get LV Class Default Value.vi

    本帖最后由 路的追逐 于 2015-12-30 11:28 编辑 我的程序关于报表生成的,在开发环境可以运行,生成EXE后运行系统报错。“错误7发生于Get LV Class Default Value.vi”但依赖关系里是有这个Vi一起打包的,请问这是怎么回事?
    发表于 12-14 16:39

    DEFAULT强制IDELAY_VALUE为0的FIXED和DEFAULT之间的区别是什么?

    为什么,DEFAULT强制IDELAY_VALUE为0的FIXED和DEFAULT之间的区别是什么?如果我想能够使用inc端口,我认为这会迫使我进入VARIABLE,对吧?SIM_TAP_DELAY有哪些单位
    发表于 07-25 13:49

    怎么使用程序存储器作为NVM

    您好,我在MCU上使用程序内存的一部分作为NVM(非易失性存储器)。我已经设法和读,但是现在我面临的问题是,我想避免编译器覆盖我用于NVM的程序内存空间。MCU是PIC32 MX230F064 D。程序存储器的最后一页是
    发表于 09-18 10:31

    如何将NVM示例的读取/写入区域从32KB更改为4KB?

    pic32mx_u***_sk2as,NVM驱动器设置为动态的。这个例子进行擦除和32K随机操作从NVM媒体启动地址(0x9D010000)开始的NVM内存区域。一系列的确认动作后,
    发表于 03-25 10:41

    怎么读写NVM

    我正在运行一个PIC32 MX795,使用MPLAB 8.70。我正在尝试给NVM一个值,然后再读取它。这是我的代码:#define NVM_PROGRAM_PAGE 0x9D007C00
    发表于 04-01 09:04

    怎么一个文件保存在内部NVM

    HI论坛,我一直试图一个文件保存在内部NVM。与此并行,我的UC被配置为USB MSD。这很好,我甚至可以文件。问题是我必须断开设备与USB的连接并重新连接才能看到文件中的变化。从FS库中,我
    发表于 04-06 10:49

    如何用应用程序函数的当前值更新NVM

    我想知道对擦除功能的时序效果。我的测试是在FSM中实现以下循环(我正在使用以太网启动器工具包II,PIC32MX795F512L设备):同时(1)擦写一个内存值到NVM等待命令完成更新内存值,每秒打印
    发表于 05-04 14:30

    NVM是什么

    NVM是什么?
    发表于 12-30 07:02

    嵌入式NVM在电源管理中的应用

    转向更为逻辑的NVM 尽管当今的设计工程师可以选择多种NVM,但是,具有低成本、高性能和应用灵活性的嵌入式NVM却很少。对于某些应用目标,排除了许多选择的可能性。例如
    发表于 08-05 10:06 877次阅读

    什么是NVM

    非易失性存储器   NVM是指非易失性存储器,目前在智能卡上采用的主要包括:EEPROM和Flash。 NVM通常用来存放程序和数据,对于智能卡而言,大多把应用程序和数据、文件
    发表于 08-05 10:08 2.2w次阅读

    IntelliJ IDEA Default Keymap

    IntelliJ IDEA Default Keymap
    发表于 07-12 16:05 0次下载

    AUTOSAR NvM Block的Native、Redundant和Dataset有什么区别?

    Native数据是NVM块中存储的原始数据,是应用程序需要读写的数据。Native数据只在NVM块中存储一份,如果数据损坏或丢失,将无法恢复。因此,在写入Native数据时,需要确保数据的可靠性和一致性。
    的头像 发表于 04-06 10:29 1927次阅读

    rust语言基础学习: Default trait

    Default trait 顾名思义是默认值,即Rust为特定类型实现 Default 特性时,可以为该类型赋予了可选的默认值。
    的头像 发表于 05-22 16:16 862次阅读