NVM存储失败问题

问题描述

车辆的行驶信息记录不下来,重新上电后行驶里程等相关信息被清零,低概率出现,低于千分之一。

问题复现

只要连续操作就会复现没有写入内存的问题,复现概率百分之一百。NVM模块配置了48个block,都是配置为标准优先级,里面有些block是Native Block,有些是Redundant Block,但无论连续写哪个block都会出现,所以排除不同block之间的区别。

功能设计

代码设计是使用NvM_WriteBlock接口把存储信息存储到FLASH当中。

分析问题

这个功能是内存管理功能,涉及应用层的逻辑,BSW层的NVM、MEMIF、FEE,MCAL层的FLS模块。

从上层开始排查,只要显示出行驶里程为非0就代表行驶里程的信息传递到了底层,根据客户反馈的现象排除了应用层的原因。

BSW层的NVM是最可能导致原因的模块,MEMIF和FEE配置过于简单,并不会导致问题产生,所以接下来重点排查NVM模块。

分析问题点1:Block类型

三种类型的block:Native Block、Redundant Block、 Dataset Block,三种都试过了,问题没有改善,跟复现出来的现象是对应的。

分析问题点2:JOB优先级

只有两个优先级:标准优先级和立即优先级。尝试改成立即优先级,也没有改善。

分析问题点3:取消校验和改变CRC类型

由于都是配置为有校验的,所以当数据跟之前一样的话就不能写入,看到网上也是建议取消这个功能,但isolar工具对代码没有改变,所以没有改善。

CRC类型有8/16/32位校验,均尝试过没有改善。

分析问题点4:同步机制

有显式同步和隐式同步,怀疑是使用显式同步的时候因为多了一步,数据同步卡在RAM block中了,导致在同步过程当中没有同步到最后的内存当中。

分析问题点5:通过测试代码触发

仅进行读写

编写测试代码,在10ms周期函数里面分开两步,并且循环执行

1.第1个10ms周期里面,调用NvM_WriteBlock接口,写入一个跟之前内容不同的数组。

2.第2个10ms周期里面,调用NvM_ReadBlock接口,并且对比读取出来和写进去的内容是否一致。

if(第1个10ms周期)
{
	创建一个内容跟之前内容都不一样的写入数组;
	NvM_WriteBlock(NvM_Block名称,&写入数组);
}
else if(第2个10ms周期)
{
	NvM_ReadBlock(NvM_Block名称,&读取数组);
	比较写入数组和读取数组内容是否一致并返回比较结果
}

每次运行一个循环就不会有问题,只要连续运行多次循环就会写着写着写不进去了,哪怕再怎么调用NvM_WriteBlock接口也无济于事。

添加写入完成标志位

在写入操作前添加读取完成标志位,如果没读取完成就等待下一个10ms,读取操作也是同理。

怀疑是因为多次循环的时候的时候,操作的速度太快了,导致JOB执行堵塞,为了监控操作执行是否结束需要找到有用的标志位。尝试过使用NvM_GetErrorStatus和NvM_Rb_GetStatus接口,返回的结果虽然正确但无法对本问题起到帮助。

在NvMSingleBlockCallback配置项当中添加回调函数。这个回调函数入参有ServiceId NVM服务ID和JobResult JOB执行结果,会在JOB执行完毕后进入,当“NVM服务ID为NVM_SERVICE_ID_WRITE_BLOCK”和“JOB执行结果为0”的时候就是写入完成。可以在里面判断,做一个写入完成标志位,读出完成也是同理。添加的时候注意isolar工具里面会对函数名称进行限制,我们需要根据规范来进行配置。

if(第1个10ms周期)
{
	if(读取完成)
	{
		创建一个内容跟之前内容都不一样的写入数组;
		NvM_WriteBlock(NvM_Block名称,&写入数组);
	}
}
else if(第2个10ms周期)
{
	if(写入完成)
	{
		NvM_ReadBlock(NvM_Block名称,&读取数组);
		比较写入数组和读取数组内容是否一致并返回比较结果
	}
}

这样就解决了写着写着写不进去的问题。

增加代码鲁棒性

原来的block是20字节的,加长到1024字节。循环执行操作的次数也从10次增加到1000次。

新的问题出现了:读取出来和写进去的内容不一致的时候,经过代码检查,发现JOB队列设计有问题,哪怕上一个JOB已经执行完成,新的JOB也排不进队列里面,返回NOT_OK,于是增加判断条件,当读写返回值为NOT_OK的时候,重新调用读写接口。

if(第1个10ms周期)
{
	if(读取完成 或者 写入失败)
	{
		创建一个内容跟之前内容都不一样的写入数组;
		写入返回值 = NvM_WriteBlock(NvM_Block名称,&写入数组);
		if(写入失败)
		{
			下一个10ms执行第1个10ms周期
		}
	}
}
else if(第2个10ms周期)
{
	if(写入完成 或者 读取失败)
	{
		读取返回值 = NvM_ReadBlock(NvM_Block名称,&读取数组);
		比较写入数组和读取数组内容是否一致;
		if(读取失败 或者 内容不一致)
		{
			下一个10ms执行第2个10ms周期
		}
	}
}

经过测试,问题被完美解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不吃鱼的羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值