Hi,
我在初始化flash为non-blocking后,使用blank check函数只会返回SUCCESS,不会像blocking模式时返回具体的状态。
在返回Success后再进行Read操作会进入Hard Fault错误。请问应该如何在non-blocking的work flash正确使用Check和read操作?
另外,手册中我没有找到关于擦除操作时间的说明,可否帮忙指出?
Thanks,
Hunt
已解决! 转到解答。
- 标签:
-
TRAVEO™ T2G
Hi Hunt,
再补充一下,我注意到您提到“在返回Success后再进行Read操作会进入Hard Fault错误”
无论在blocking还是non-blocking下,这个结果都是肯定的。因为blank check返回success意味着这个区域为空。读取空白区域会产生未定义的结果,因此MCU设计了这种情况下报错。
读取操作要对已写入的区域进行。写入操作写对空白区域进行。
work flash 擦除时间为80ms(典型值) 160 ms(最大值) 在 2 KB 分区 ;
5ms(典型值) 15 ms(最大值) 在 128 B 分区
Best Regards,
Finn
Hi Hunt,
我在测试的时候,没能复现出相同的问题。(使用例程 T2G_Sample_Driver_Library_7.3.0\tviibe1m\src\examples\flash\work\cm0_cm4_non_blocking )
non-blocking模式下,如果某区域已经写入了,blank check还是会返回false
如果先调用SectorErase,blankcheck是会返回success,但确实也是success了。再写入不会报错,写入后读取也不会报错。
您能再检查一下代码的逻辑吗?或者使用上面提到的SDL例程再试一下。
Best Regards,
Finn
Hi Hunt,
再补充一下,我注意到您提到“在返回Success后再进行Read操作会进入Hard Fault错误”
无论在blocking还是non-blocking下,这个结果都是肯定的。因为blank check返回success意味着这个区域为空。读取空白区域会产生未定义的结果,因此MCU设计了这种情况下报错。
读取操作要对已写入的区域进行。写入操作写对空白区域进行。
work flash 擦除时间为80ms(典型值) 160 ms(最大值) 在 2 KB 分区 ;
5ms(典型值) 15 ms(最大值) 在 128 B 分区
Best Regards,
Finn
Hi Finn,
谢谢您的详细解释,可否据此继续请教一下:
1. 读取或者写入前,如果扇区从未擦除过,此时checkblank返回true,此时可以写吗?
2. 如果对已写入区域再次进行了写操作,是会返回失败?还是跳入某个错误?这个错误能否设置处理函数,而不是hardfault这种不能恢复的错误?
3. 读取了blank的区域时,如果要产生错误,错误处理能否不是hardfault?而是可以自己写错误处理函数?这样程序就不用跑飞了
4. 擦除workflash时间和手册上比较接近,但写workflash,4字节写入实测时间大概是140~150us,和手册上30us典型值,60us最大值差异较大
5. 我们在调试时,曾出现程序跑到类似 Cy_SysLib_ProcessingFault或者Cy_SysLib_Halt函数里,也不清楚怎么进去的,我在想如何判断错误源,以及产生了错误后是否能恢复?比如写一个自己的错误处理函数
Hi
1. 如果blankcheck为true,可以写不可以读
2. 理论上不要写入已写入的区域。但是特例是写入了原值,比如本来是0A,再次写入了0A,不会出错。其他情况下,直接用新值覆写数据会产生未定义的结果,既不是原值也不是新值。但在我实际测试时,没有进入hardFault,只能通过观察workflash的值人为发现错误发生了。
3. 读取未写入的区域会进入hardFault,通过这句代码 FLASHC->unFLASH_CTL.stcField.u1WORK_ERR_SILENT = 1; 可以将错误屏蔽,这样程序就不会跑飞了,错误处理函数也不用了。但是读取空白区域的数据是随机的的,可能会在之后产生逻辑错误。
4. 您是如何测试这个时间的呢?我目前测试得到是115us左右,但是这包含了counter 的 trigger start和trigger stop的额外时间。
( Counter 数值为0xef , 231, 频率为2MHz,换算为时间大约115.5us )
5. 在3中提到,读取未写入区域产生hardFault,然后会进到你提到的这两个函数。屏蔽了错误应该就不会进来了。
Best Regards,
Finn
Hi Finn,
2. 对已写入区域重新写会变成未定义值,即改变了原来的值,请问这样设计是为了什么目的呢?一般认为写不进去,反馈错误提示就可以了
3. 添加FLASHC->unFLASH_CTL.stcField.u1WORK_ERR_SILENT = 1后,如果读取空白区域,“可能会在之后产生逻辑错误”是读取操作会产生逻辑错误?还是说使用数据因为是随机值,所以直接使用会产生逻辑错误(但不会进入某个hardfault)?
4. 时间测试,我是开了一个不产生中的的定时器,1us步进,读取两次计数值相减得到的执行时间
另外,昨晚我们测试时还发现一个情况:当擦除某个扇区完成后,程序将重新对其写入32字节数据,当前4个字节写入后,程序打算先check这4个被写入区域是否blank,然后读出对比写入的值是否正确,一旦check这4个字节(指定check的长度是1个word),就又进入了一个错误中断Cy_SysLiab_Halt,单步调试发现是执行到Cy_IPC_Drv_AcquireNotify()函数中第三行语句时发生的错误 base->unNOTIFY.u32Register = reg.u32Register;我们困惑的是,每次在写入前都检查了是否为blank,写入后读取时又检查了是否不为blank,但是还是出错,感觉这个有点怪异了
BR.
Hunt
Hi Hunt,
2. 写入时的错误覆写操作确实需要使用者自己来检查,手册上提到了 一定不能覆写已有的数据,但如果真的这么做了,芯片也没有设计报错,但错误的数据确实产生了。所以需要使用者自己写code时仔细检查。
3. 读取操作本身一定不产生错误了。但比如用户想要读取某个变量,用户以为是自己设定的123,但其实读到了随机的456,这样会导致用户之后的计算出错。并不是flash 报hardfault。
4. 我也是这么测试的。(在blocking模式下,因为这样更准确一些,写入函数一旦返回说明已经写入完成)
TCPWMx_GRPx_CNTx_COUNTER->unCOUNTER.u32Register = 0ul;
Cy_Tcpwm_TriggerStart(TCPWMx_GRPx_CNTx_COUNTER);
Cy_FlashWriteWork(i_addr, (uint32_t*)&programData[i_dataPos], CY_FLASH_DRIVER_BLOCKING);
Cy_Tcpwm_TriggerStopOrKill(TCPWMx_GRPx_CNTx_COUNTER);
在flash write前后开启和关闭定时器。测出来是115.5us。 但需要注意的是,flash write函数本身做了很多行的命令来配置写入操作,
这些命令也被计时进去了。所以导致结果偏高。实际使用的时候,这些配置也是必须的,所以实际使用中,可以按照100us来认为。或者说,实际写入时间 = 执行配置命令的时间 + flash本身写入的时间。
关于您最后说的这个问题,我没有成功复现。
就是说erase掉之后,再写入4个字节,然后blankcheck对吗?我这里测试blankcheck返回一个false,然后就正常结束了。没有产生任何错误。您可以再检查一下,如果还有问题可以附上问题代码
Best Regards,
Finn
Hi Hunt,
如果是这种情况,只能在while循环中将未使用的部分填充了
BR,
Finn
添加了FLASH->unFLASH_CTL.stcField.u1WORK_ERR_SILENT = 1;后,在擦除、写入、check这个顺序时,在checkblank步骤执行到Cy_IPC_Drv_AcquireNotify()函数最后一条语句时,就会进入 Cy_SysLiab_Halt中
刚测试了,还是这样
Hi Hunt,
您M0核开启了吗?现在的这些操作,跑在M0还是M4上呢?
BR,
Finn
Hi Hunt,
Sorry, 我找到调用关系了,blankcheck 调用了Cy_Srom_CallApi 然后需要锁定IPC(Inter-processor communication)以发送消息。
如果IPC超时锁不上,会导致time out错误,然后进入到Cy_SysLiab_Halt
这个的产生应该不是unFLASH_CTL.stcField.u1WORK_ERR_SILENT = 1;导致的,因为写ERR_SILENT寄存器不会影响到IPC访问。
请检查是否有其他代码,错误锁定了IPC未释放。
BR,
Finn