• 465查看
  • 0回复

[底层软件] NvM调试小记——Write

[复制链接]


该用户从未签到

发表于 21-1-2024 10:58:52 | 显示全部楼层 |阅读模式

汽车零部件采购、销售通信录       填写你的培训需求,我们帮你找      招募汽车专业培训老师


01

NvM_Write概述

NvM的写入过程,即是上层通过调用NvM接口改变队列信息,之后

NvM_MainFunction()再去逐级往下调用Fee_MainFunction(),最终将源Ram数据拷贝到目标Dflash地址中去。

流程图如下:

NvM调试小记——Writew1.jpg

再附一个write过程的最底层接口调试图:

NvM调试小记——Writew2.jpg

接下来就是具体的写入过程。

02

关键变量

UDS中某个2E服务DID:

NvM调试小记——Writew3.jpg

NvM的请求队列:

NvM_Prv_Queue_ast[]

Fee的请求队列:

Fee_OrderFifo_st[]

Fee存储 读、写的状态机和其他信息:

Fee_RdWrOrder_st

Fee的工作状态机:

Fee_Rb_WorkingState_en

Fee上次读指令存储的信息:

Fee_GlobInfoLastRdHeader_st

写入的存储临时buffer:

Fee_llPageBuf_au32

03

写入过程

上层请求逻辑

其实应用层调用写入接口有2种,一种是仅请求状态,之后统一时间段存储(可以是休眠前):

NvM_SetRamBlockStatus(NvM_BlockIdTypeBlockId, boolean BlockChanged),

另一种则是目前项目使用的立即触发存储:

NvM_WriteBlock(NvM_BlockIdType BlockId, const void*NvM_SrcPtr)

从函数内容来看,基本上只是请求的类型不同。

函数会首先判断下请求的NvM block的lenth和buffer地址的有效性,之后调用NvM_Prv_Queue_EnqueueRequest(idQueue_uo,&BlockData_pcst>QueueEntry_st);

对队列进行赋值操作,如下图:

NvM调试小记——Writew4.jpg

这边还能看到一个细节信息,队列的最大值size_cu16为50,其实是与isolar中的配置是一致的。

NvM调试小记——Writew5.jpg

NvM_MainFunction()

和Read一样,以 NvM_Prv_Main_st.Activity_rAMwM_en为状态机跳转。

首先,NvM_Prv_MainFunctionArbitrate() 函数将 队列

NvM_Prv_Queues_ast的内容拷贝到NvM_Prv_Main_st 中,之后设置

JobData_st 。

经过函数 NvM_Prv_JobStart_Write()之后,再看下属性:

NvM调试小记——Writew6.jpg

这边会调用 Fee_Write()设置 Fee_OrderFifo_st[FEE_NVM_JOB],

NvM调试小记——Writew7.jpg

NvM调试小记——Writew8.jpg

那么之后的NvM_Prv_MainFunctionPollResult(), 只需要等待Fee的返回结果就可以了。

最后再执行 NvM_Prv_MainFunctionJobComplete() 、

NvM_Prv_MainFunctionResultEval()清空状态,完成本次写操作。

rba_FeeFs1_MainFunction()

NvM在改变Fee_orderFifo_st之后 ,FEE_mainfunction()就要出场工作了。

主函数以  为状态机工作。Fee通过执行 Fee_SearchNextOrder ()和Fee_LoadNextOrder() 来查找order和Fee block的属性。
之后,调用函数 Fee_HLWriteBlock(),(状态机Fee_RdWrOrder_st.Fee_HLWrBlock_en)。
写之前先要读,把当前dflash中最新的一块数据读出来,通过
Fee_LLSearchSpecifiedBlkHeader() ,流程跟readall中一致。
NvM调试小记——Writew9.jpg

然后计算当前待存储数据的Crc,

NvM调试小记——Writew10.jpg

如果crc和取读的内容一致,那么其实就不需要写入,直接返回上一级即可,如果需要写入那么就开始填充。这里可以看到除了CRC,数据段也填充了2位,这就是整个头了。

再附一下header的结构体:

NvM调试小记——Writew11.jpg

再往底层去,调用

Fee_LLWriteBlock(&Fee_GlobInfoLastRdHeader_st,

Fee_OrderFifo_st[Fee_idxActQueue_u8].DataBufferPtr_pu8);

(状态机:Fee_RdWrOrder_st.Fee_LLWrBlock_en)

计算存储所用空间,空间不够会触发erase的逻辑,下一篇做压力测试的时候再来调试。

如果空间是够用的,则调用 做真正的写动作,这里是先写了8个字节(1个page)。



整个Fls写过程的调试过程如下,

FEE_LL_WR_WRITEHEADER_E

NvM调试小记——Writew13.jpg

FEE_LL_WR_WRITEDATA_SEC_A_E

NvM调试小记——Writew14.jpg

NvM调试小记——Writew15.jpg

FEE_LL_WR_WAIT_WRITEHDRPG2_E

NvM调试小记——Writew16.jpg

最后的最后,清空状态,结束“写”动作。

NvM调试小记——Writew17.jpg

04

写在最后

那么看到这,其实内心还有2个疑问,Fee_Cache在上电后是如何确定的呢?dflash空间写满之后,又是如何擦除重新写的呢?下篇再调试研究下。

快速发帖

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|Archiver|汽车工程师之家 ( 渝ICP备18012993号-1 )

GMT+8, 1-2-2025 12:52 , Processed in 0.202691 second(s), 31 queries .

Powered by Discuz! X3.5

© 2001-2013 Comsenz Inc.