最近在支持一个i.mx rt1170欧美客户,客户项目里选用了来自micron的四线nor flash - mt25ql256aba8e12-0aat作为启动设备,一般读写倒是没有问题,但是在 segger j-flash下烧写遇到了特定区域内校验失败的问题。
从本人过往丰富的flash支持经验来看,亚太区客户一般选用issi(芯成)/winbond(华邦)/mxic(旺宏)/gigadevices(兆易创新) 的flash比较多,个人对这些厂商flash可以说是门清了。这个欧美客户选用的是不太熟的micron(镁光)产品,借着这个问题,正好带大家一起稍微深入地了解下micron flash产品。
一、引出客户问题
首先是复现下客户的问题,找块mimxrt1170-evk开发板,将板载其他厂商flash换成这颗mt25ql256aba8e12-0aat(因为是t-pbga24封装,所以需要放到原来的 octalflash位置——u21),然后将sdk_2.11.1_mimxrt1170-evkoardsevkmimxrt1170driver_examplesflexspi orpolling_transfer例程稍作适配性修改,主要是将customlut里的命令表按micron数据手册命令表做调整(全用了四字节地址命令),然后跑了一下例程发现基本的flash读写擦操作没有问题(默认操作的是0x14000处的sector),这表明硬件修改没有问题。
const uint32_t customlut[custom_lut_length] = { /* fast read quad mode - sdr */ [4 * nor_cmd_lut_seq_idx_read_fast_quad] = flexspi_lut_seq(kflexspi_command_sdr, kflexspi_1pad, 0xec, kflexspi_command_raddr_sdr, kflexspi_4pad, 0x20), [4 * nor_cmd_lut_seq_idx_read_fast_quad + 1] = flexspi_lut_seq(kflexspi_command_dummy_sdr, kflexspi_4pad, 0x0a, kflexspi_command_read_sdr, kflexspi_4pad, 0x04), /* erase sector */ [4 * nor_cmd_lut_seq_idx_erasesector] = flexspi_lut_seq(kflexspi_command_sdr, kflexspi_1pad, 0xdc, kflexspi_command_raddr_sdr, kflexspi_1pad, 0x20), /* page program - quad mode */ [4 * nor_cmd_lut_seq_idx_pageprogram_quad] = flexspi_lut_seq(kflexspi_command_sdr, kflexspi_1pad, 0x34, kflexspi_command_raddr_sdr, kflexspi_1pad, 0x20), [4 * nor_cmd_lut_seq_idx_pageprogram_quad + 1] = flexspi_lut_seq(kflexspi_command_write_sdr, kflexspi_4pad, 0x04, kflexspi_command_stop, kflexspi_1pad, 0x00),};
接下来就是按客户操作流程来复现segger j-flash烧写校验失败问题,客户其实是尝试烧写全部32mb数据来查看j-flash及其配套下载算法能否适用这颗flash,这里就用《超级下载算法rt-ufl v1.0》,经过测试,确实复现了客户的问题。
经过反复测试,定位了问题是这颗micron32mb的flash前3/4 区域(0x0 - 0x17fffff)是没问题的,但是在后1/4区域(0x1800000 - 1ffffff)均会出现校验错误(j-flash软件里看擦写操作是能进行的,但后面发现其实根本没有正常擦写)。
二、micron flash有什么不同?
在分析客户问题之前,我们先来简单认识一下这颗micron nor flash,经过浏览micron的官网以及这颗flash的数据手册,发现它确实跟其他厂商的nor flash设计有点区别。
首先是flash容量,其他厂商一般都是能够提供从512kb到2gb全范围的flash产品,但是micron串行nor flash最小容量就是128mb,果然是国际memory大厂,设计就是豪横。
但是从flash作为xip启动设备角度而言,128mb其实挺多的,普通的嵌入式项目没有这么大的代码存储需求。
其次是nor flash里的高频问题 《qe bit 设计》,一般flash的io2/3引脚复用功能都是通过内部状态寄存器里的qe位来控制,qe关闭则io2/3是reset#/hold#/wp#功能:如果qe开启则io2/3用于数据传输(这种情况下才可以用quad i/o相关命令)。
然而micron flash根本就没有qe位控制,io2/3功能主要靠当前命令类型来决定:如果是single spi或者dual i/o spi命令,则io2/3是reset#/hold#/wp#功能;如果是quad i/o spi命令,则io2/3 用于传输数据。
其它设计上的区别就不再详细展开了,等用到具体功能查看数据手册再去了解对比。
三、找到问题原因
现在来分析客户问题,flash的后1/4区域在j-flash下校验错误,那我们先修改 polling_transfer例程去操作0x1800000之后的sector,发现确实跑不过。
如果不是flash介质问题,也不是读写擦命令问题,那只能有一种解释,那就是 flash里这个区域被保护了,flash里是有非易失寄存器可以设置软件保护的,但是默认应该是全部区域不保护,而第一小节里我们先跑了polling_transfer例程验证 flash读写,那大概率这个例程里有修改flash内部寄存器操作,经过排查定位到了flexspi_nor_enable_quad_mode() 函数。
#define flash_quad_enable 0x40uconst uint32_t customlut[custom_lut_length] = { /* enable quad mode */ [4 * nor_cmd_lut_seq_idx_writestatusreg] = flexspi_lut_seq(kflexspi_command_sdr, kflexspi_1pad, 0x01, kflexspi_command_write_sdr, kflexspi_1pad, 0x04),};int main(void){ // 代码省略 /* enter quad mode. */ status = flexspi_nor_enable_quad_mode(example_flexspi); if (status != kstatus_success) { return status; } // 代码省略
第二小节介绍里我们知道micron flash是没有qe位设计的,因此 flexspi_nor_enable_quad_mode() 函数在这里是多余的,这个函数是将0x40写入到了命令标号为0x01的status register(这个操作适用于issi flash),我们在数据手册里找到这个寄存器定义,发现被置位的bit 6是块保护控制位bp[3:0]里的最高位,并且 bp[3:0]设置是非易失性的(断电不丢失)。
再进一步往下找bp[3:0]设置与flash空间对应关系,发现4'b1000设置就是保护后1/4区域里的所有block,至今似乎真相大白了。
为了验证这个发现,我们需要将statusregister重设为0x00,然后再用j-flash烧写一次,这时候校验失败问题消失了,一切恢复正常。
一点小体会
回顾这个故事,如果事先不用polling_transfer例程去操作一次flash,或者即使跑了例程但事先意识到了micron flash没有qe设计而删除flexspi_nor_enable_quad_mode() 函数,也就无法复现客户问题了,这也是本次故事里最神奇的地方,我和客户犯了同样的失误,也许这就是缘分?
模块化代码的设计思路,开发思想和独立模块开发模型
中国军用宽带移动通信行业发展如何?
光鋐公布2019年10月营收 今年整体LED产业仍有供过于求的风险
店铺手机展示架--手机防盗器的方案开发
电源管理IC的选用标准
Segger J-Flash下烧写遇到特定区域内校验失败的问题
lm567的典型应用电路
冷原子领域专用激光光源(589/671/680/780/795/852/894 nm)
介绍一块钴酸锂为正极材料的锂离子软包电池
镭拓科普1500w手持激光焊接机价格差异在冷却方式的区别
安规电容能去除电源滤波是真的吗?
是德科技发布CyPerf 2.0软件解决方案
充电桩外壳粘接固定,使用什么密封胶能得到理想效果
关于智能城市所拥有的机遇分析和介绍
RAPIDS cuML中的输入输出可配置性
全球制造业亮红灯 下半年“宽松潮”来势更猛?
关于USB充电的详细解析
高增益波导缝隙定向天线设计及测试结果
RISC-V中开发Java是一种什么体验?
汽车产业转型升级:腾讯正研发车载微信 阿里组建汽服新零售