AUTOSAR架构下NvM源码详细分析

  如下图所示,用户通过Davinci Configurator静态配置NvM模块,NvM扣扣通过队列机制缓存NvM User的Job请求(Read/Write/Erase…),NvM模块Runnable查询状态满足条件后调用MemIf的接口来请求底层执行动作。底层在完成任务后调用JoNotification的Callback通知到NvM告知上一次Job的执行结果。

  

  通过Davinci Configurator配置完成NvM模块后,NvM_Cfg.c会生成一个名为NvM_BlockDescriptorTable_at的配置表,里面包含了每个Block的静态配置,比较重要的是Ram Block的地址,Rom Block的地址,Job Notification等。NvM模块在处理Job时,会查询这个配置表来找到对应Block的配置内容,执行对应的操作。

  NvM_Cfg.h配置了一些全局属性的打开或者关闭,最重要的是每个Block描述符,Block描述符ID也就是Block在NvM_BlockDescriptorTable_at配置表中的数组下标。

  NvM_Qry.c文件种定义了一个名为NvM_QueryTable_ap的NvM状态查询表,这是一个函数指针数组,里面的每个成员都是一个函数签名为NvM_QryFctPtrType的函数指针,NvM调用NvM_QueryTable_ap表种的各个函数来查询相应状态。

  

  NvM_Act.c文件种定义了一个名为NvM_ActionTable_ap的NvM动作执行表,这是一个函数指针数组,里面的每个成员都是一个函数签名为NvM_ NvM_ActFctPtrType的函数指针,NvM调用NvM_ActionTable_ap表中的各个函数来查询执行相应动作。

  

  NvM_JobProc.c里面定义了一个名为NvM_StateDescrTable_at的状态迁移表。表中的每个元素是一个类型为NvM_StateDescrType的结构体成员。

  

  

  NvM_ApiFlags_u8:?多块请求相关的全局变量,NvM_Init后初始化为0

  

  NvM_CurrentJob_t: NvM模块正在处理的Job相关信息

  

  

  NvM_Init后,没有Job请求,NvM_CurrentJob_t.JobServiceId_t = NVM_INT_FID_NO_JOB_PENDING

  NvM_CurrentBlockInfo_t: 当前处理的Block信息信息

  

  

  NvM_Init后NvM_CurrentBlockInfo_t结构体变量种的内容基本都是清零状态。

  NvM_TaskState_t, NvM_JobMainState_t, NvMJobSubState_t三个全局变量用于MainFunction中三个有限状态机的流转。

  

  

  NvM_JobQueue_at:?用于管理队列使用情况的结构体数组。

  

  

  NvM_Init后NvM_JobQueue_at所有成员建立连接(模拟链表的PreElementPt和NextElementPt)。

  NvM_NormalPrioQueue: 用来标记下一个要被处理的Job,以及下一个可以使用的空队列元素。

  

  

  NvM_Init后,没有要处理的Job,同时数组下标为0的NvM_JobQueue_at元素为空,可以使用。

  NvM_BlockMngmtArea_at:用来记录每一个Block的状态

  

  

  NvM_InternalBuffer_au8是Davinci根据用户配置在NvM_Cfg.c中自动生成的一个很大的数组(能缓存所有Block的数据)。

  最后NvM调用底层的MemIf_Write接口传入的DataBufferPtr就是NvM_InternalBuffer_au8的基地址。

  

  

  

  

  SWC写NvM Block的过程可以参考

  SWC调用RTE接口写NvM数据后,写请求的Job会入NvM的队列。

  

  

  NvM_MainFunction中调用NvM_Fsm在轮询三个状态机。

  NvM_TaskState_t当前在IDLE状态,执行NvM_QryNormalPrioJob和NvM_QryTrue查询

  

  

  

  执行NvM_ActGetNormalPrioJob和NvM_ActInitMainFsm动作

  

  

  NvM_TaskState_t状态切换到到NVM_STATE_NORMAL_PRIO_JOB状态,同时把NvM_JobMainState_t状态切换到NVM_STATE_WRITE_COPY_BUFFER_DATA状态。

  

  NvM_JobMainState_t当前状态为NVM_STATE_WRITE_COPY_BUFFER_DATA,执行NvM_QryDataCopyBusy没满足条件

  

  NvM_JobMainState_t当前状态为NVM_STATE_WRITE_COPY_BUFFER_DATA执行第二组查询

  

  执行NvM_QryFalse查询,第二组查询也不满足

  

  执行第三组查询NvM_QryIsDataIntegrityAlgorithmConfigured和NvM_QryTrue,都满足条件。

  

  

  执行第一个动作NvM_ActSetupDataIntegrityGeneration

  

  执行第二个动作NvM_ActNop

  

  NvM_JobMainState_t的状态机执行完,切换到NVM_STATE_WRITE_GENERATE_DATA_INTERGRITY_INFORMATION状态

  

  NvM_JobSubState_t当前状态为NVM_STATE_FSM_FINISHED

  执行第一组的第一个查询:NvM_QryTrue返回TRUE

  执行第一组的第而个查询:NvM_QryTrue返回TRUE

  动作都为NvM_ActNop

  第一组状态机执行完之后:

  

  NvM_TaskState_t

  第一组的第一个状态状态查询:NvM_QryMainFsmRunning 返回TRUE

  第一组的第二个状态状态查询:NvM_QryTrue 返回TRUE

  满足查询

  第一个执行动作:NvM_ActNop

  第二个执行动作:NvM_ActNop

  NvM_JobMainState_t

  第一组的第一个查询动作:NvM_QryIsDataIntegrityJobPending 返回FALSE

  由于返回FALSE,执行第二组查询

  第二组的第一个查询动作:?NvM_QryIsDataIntegrityJobFinishedSuccessful ?返回TRUE

  第二组的第二个查询动作:NvM_QryTrue 返回TRUE

  执行动作:

  NvM_ActExportDataIntegrityInformation

  NvM_ActNop

  由于状态机器太多,不再往下分析,我们到最后想知道的Action处打个断点:当NvM_JobMainState_t切换为NVM_WRITE_READABILITY_CHECK_SECONDARY_BLOCK后会执行NvM_MemIfAbstraction_Write的Action,也就是会调用MemIf_Write将Job写请求和数据传递到Fee模块。

  

  Fee在完成Job的写任务后,会调用NvM_JobEndNotification,这样才能知道上一次的Job请求已经处理完毕。

  

  NvM模块处理完一个Job任务后,同样会调用Rte_NvMNotifyJobFinished_xxx通知到使用NvM服务的SWC。

  

  a.用户配置NvM_BlockDescriptorTable_at表,NvM模块根据NvM_StateDescrTable_at状态描述表去查询NvM_QueryTable_ap状态表,根据查询结果,调用NvM_ActionTable_ap动作表里面的Action执行动作并切换状态。

  b. 底层Fee/Fls模块完成Job后通过Notification的回调告知NvM模块,NvM模块完成一个Job的状态切换并通知到SWC。

  c.?我们在Debug时可以查看NvM_BlockMngmtArea_at全局变量来看每一个Block有没有Error发生,通过NvM_NormalPrioQueue变量来看当前队列是否已经被Job被占满(Full)了,以及当前正在处理的是哪一个Job。

  d.?通过研究源码,我们能更快的定位和分析问题,也能学习Vector专家们的代码风格,比如NvM模块的队列实现就可以深入研究下。

  e. 整个存储协议栈只有NvM模块有队列缓存Job的机制,其他模块(MemIf, Fee/EA, Fls/Eeprom)都是一个Job一个Job的处理。

  存储协议栈源码分析下集预告,Fee模块的磨损均匀机制,基于TC3xx芯片的Fls驱动分析……

  End

  「汽车电子嵌入式在CSDN上同步推出AUTOSAR精进之路专栏,本专栏每个模块完全按实际项目中开发及维护过程来详细介绍。模块核心概念介绍、实际需求描述、实际工程配置、特殊需求介绍及背后原理、实际工程使用经验总结。目的是让读者看完每一个章节后能理解原理后根据需求完成一个模块的配置或者解决一个问题。」

  点击文章最后左下角的阅读原文可以获取更多信息

  或者复制如下链接到浏览器获取更多信息

  https://blog.csdn.net/qq_36056498/article/details/132125693