SPI Flash数据移位
来源:互联网 发布:骑士数据 编辑:程序博客网 时间:2024/05/18 01:40
背景
C6678外挂了一片SPI接口的Nor Flash,型号为Micron N25Q128A13BSF404F,其容量为128Mbit,由于电平匹配问题中间使用了一片EPLD作电平转换,将6678的1.8V电平逻辑转换为3.3V。
问题描述
开发和调试很顺利,在完成软件概要设计后约一周内就完成了所有编码和部分测试工作。但是在测试过程中发现当SPI的时钟配高一些(50MHz)的时候,就会出现Flash初始化不通过,具体现象是读取ID不正确,与正确的ID总是移位1个比特。当把SPI时钟调低到20MHz后又恢复正常,而在30~40MHz左右时又总是一会儿正常一会儿错误。
分析排查
这时先怀疑芯片不支持这么高时钟速率,然而查手册发现其中明确提到最高支持时钟速率为108MHz。然后又询问硬件设计人员物料来源,得知通过正常途径采购,芯片本身应该没有什么问题。最后问题应该还是归结到软件问题上。
先查SPI驱动中对分频的配置,仔细对比手册没有找到问题。然后用示波器测量时钟引脚频率,仍然正常。测量读ID时主机发送的命令信号,依然正常。再测量不同频率下6678的接收引脚信号,在频率逐渐提高过程中时钟采样沿居然逐渐接近了数据波形的边沿处!最终40MHz时完全采在了前一个bit的后部,结果当然会移位1个比特。
根据这个测量结果仔细分析,终于找到了其中的原因。原来是中间的EPLD在捣鬼,信号经过它时除了电平转换,还会有一定的时延效应,正是这个时延导致了数据错误。详细分析如下。
理论分析
SPI总线由SPICS、SPICLK、SPISIMO和SPISOMI组成,其中前三根由6678驱动,后一根由N25Q驱动。假设信号经过EPLD的时延是Δt,以6678输出CS的时刻为基准,t时刻SPICLK信号开始有效。
当Δt=0时正常时序如图中的时序1所示,SPISIMO和SPISOMI在SPICLK的上升沿数据有效,6678和N25Q均能采样得到正确数据。
当Δt>0时如图中的时序2所示。由于SPICS、SPICLK、SPISIMO的时延相等相抵消,在SPICLK上升沿N25Q仍能采得正确数据,即主机向从机发送数据不受影响。
此时从机刚刚收到时钟信号,因此触发其发出SPISOMI的输出也才刚刚开始,比正常时间顺延Δt。此信号经过EPLD再回到6678端时再次顺延Δt,而6678端的其他三根信号无时延,两者相差达到2Δt。若此时间大于半个时钟周期,则采样将产生不稳定,甚至错位。实际信号并非陡峭边沿,因此对Δt要求更高。
理论分析完毕,接下来要实测来证实理论。用示波器的两个通道分别测量EPLD两端的SPICLK信号,结果两通道上信号的时间差约4ns,双向达到8ns,且信号边沿形状较差。因此SPI时钟周期不应低于16ns,即62.5MHz,实际测试时钟频率在35MHz时可以正确传输数据,到达40MHz以上时传输失败。证实了理论分析。
解决方案
最后在Flash驱动中将时钟频率限制在25MHz以下,规避了这个问题。
- SPI Flash数据移位
- STM32F10X SPI操作flash MX25L64读写数据
- STM32F10X SPI操作flash MX25L64读写数据
- sTM32F10X SPI操作flash MX25L64读写数据
- MT7688 SPI 数据移位问题 SPI控制器驱动更改 openwrt(linux-3.18.29)
- SPI Flash
- SPI-Flash
- STM32上SPI+DMA实现大批量读取flash数据
- STM32上SPI+DMA实现大批量读取flash数据
- 总线flash和spi flash
- spi flash 驱动
- spi FLASH 问答
- FLASH读写----SPI
- SPI Flash Parts
- Linux SPI FLASH DRIVER
- spi flash控制驱动
- SPI FLASH 驱动
- SPI flash学习
- <iOS>多线程GCD
- Volley Session的小结
- Ubuntu12.04配置LAMP 环境
- Spring Security教程(10)---- 自定义登录成功后的处理程序及修改默认验证地址
- notification
- SPI Flash数据移位
- linux命令总结1129
- iOS两个应用程序之间的跳转和传值
- STM_HAL: assert_param 与 assert_failed函数
- C#一样格式类型互转
- oracle数据库体系结构
- butter高通滤波
- 磁条磁道介绍
- Please ensure that adb is correctly located at .... and can be executed