最近在玩zynq petalinux时发现了一个蛋疼的BUG,我的板子使用的是W25Q256芯片,32MB容量,被我分成了u-boot,env,kernel,rootfs几个mtd块,其中的rootfs是放在flash末尾,也就是超过了spiflash一半(16MB),当系统正常启动后,挂载rootfs时始终不成功,并且使用flash_erase   /dev/mtd3  这种命令对rootfs区域进行擦除时竟然把flash前面部分的u-boot和kernel给擦掉了,心里一万个MLGB,又是xilinx官方驱动有坑了,没办法,只能去啃官方代码了

首先,分析现象,启动kernel正常,而且kernel有一部分也超过了16MB地址,因此u-boot应该没问题,问题出在kernel mtd或者qspi flash驱动内。w25q芯片默认使用的是3个字节地址寻址,3个字节最大只能16MB,因此要寻址超过16MB时需要增长寻址位数,在w25q256中增加寻址位数有两种方式,一种是直接切换为4直接寻址,有专门的命令切换,切换后读写命令都使用4直接地址。第二种是使用EAR寄存器,读写数据时还是使用3字节地址,但是通过EAR寄存器可以切换读写的是低16M还是高16M

经过一番艰苦的debug分析,最终定位到了内核mtd驱动层的xxxxx/linux-xlnx/drivers/mtd/spi-nor/spi-nor.c文件内,在int spi_nor_scan函数中,xilinx官方竟然强制把qspi驱动限制死了3字节地址模式,看不懂他这种骚操作是什么意思,怪不得我即使给W25q256 的属性里面添加了4字节地址支持的属性也无效

......if (nor->addr_width) {/* already configured from SFDP */} else if (info->addr_width) {nor->addr_width = info->addr_width;} else if (mtd->size > 0x1000000) {
#ifdef CONFIG_OF                                //关键在这里,xilinx判断设备树种的qspi 描述np_spi = of_get_next_parent(np);if (of_property_match_string(np_spi, "compatible","xlnx,zynq-qspi-1.0") >= 0) {int status;nor->addr_width = 3;                //强制使用了3字节地址模式set_4byte(nor, info, 0);status = read_ear(nor, info);if (status < 0)dev_warn(dev, "failed to read ear reg\n");elsenor->curbank = status & EAR_SEGMENT_MASK;} else {
#endif/** enable 4-byte addressing* if the device exceeds 16MiB*/nor->addr_width = 4;if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||info->flags & SPI_NOR_4B_OPCODES)spi_nor_set_4byte_opcodes(nor, info)
......

后来想想,xilinx这样做应该是想通过ear寄存器来操作读写,不想直接切换成4字节地址,后面继续分析也验证了这个想法,看下面的代码就清楚了,只不过不知道xilinx是忘了改还是瞧不起WINBON,在判断是否操作EAR寄存器时漏掉了一个WINBON判断,导致我使用W25q256时这个判断就失效了,从而导致高16MB的flash读写出错,具体修改看下面的代码注释就知道了

static int spi_nor_write_ear(struct spi_nor *nor, u32 ear)
{u8 code = SPINOR_OP_WREAR;u8 addr;int ret;struct mtd_info *mtd = &nor->mtd;if (mtd->size <= (0x1000000) << nor->shift)return 0;ear = ear % (u32)mtd->size;addr = ear >> 24;if (!nor->isstacked && addr == nor->curbank)return 0;if (nor->isstacked && mtd->size <= 0x2000000)return 0;if (nor->jedec_id == CFI_MFR_AMD)code = SPINOR_OP_BRWR;if (nor->jedec_id == CFI_MFR_ST ||nor->jedec_id == CFI_MFR_MACRONIX ||nor->jedec_id == SNOR_MFR_ISSI ||nor->jedec_id == SNOR_MFR_WINBOND) {     //WINBON是我加的,原本是没有的write_enable(nor);code = SPINOR_OP_WREAR;}nor->bouncebuf[0] = addr;if (nor->spimem) {struct spi_mem_op op =SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1),SPI_MEM_OP_NO_ADDR,SPI_MEM_OP_NO_DUMMY,SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1));ret = spi_mem_exec_op(nor->spimem, &op);} else {ret =  nor->write_reg(nor, code, nor->bouncebuf, 1);}nor->curbank = addr;return ret;
}static int read_ear(struct spi_nor *nor, struct flash_info *info)
{int ret;u8 code;/* This is actually Spansion */if (JEDEC_MFR(info) == CFI_MFR_AMD)code = SPINOR_OP_BRRD;/* This is actually Micron */else if (JEDEC_MFR(info) == CFI_MFR_ST ||JEDEC_MFR(info) == CFI_MFR_MACRONIX ||JEDEC_MFR(info) == SNOR_MFR_ISSI ||JEDEC_MFR(info) == SNOR_MFR_WINBOND)        //WINBON是我加的,原本是没有的code = SPINOR_OP_RDEAR;elsereturn -EINVAL;if (nor->spimem) {struct spi_mem_op op =SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1),SPI_MEM_OP_NO_ADDR,SPI_MEM_OP_NO_DUMMY,SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));ret = spi_mem_exec_op(nor->spimem, &op);} else {ret = nor->read_reg(nor, code, nor->bouncebuf, 1);}if (ret < 0) {pr_err("error %d reading EAR\n", ret);return ret;}return nor->bouncebuf[0];
}

按照上面的代码注释添加WINBON的判断后重新编译下载启动都正常了,后面查看了petalinux2020.2的代码,发现这个bug还是存在,难道就没人在zynq上用超过16M的spiflah?

关于xilinx zynq petalinux 使用32MB(W25Q256)的SPI FLSH无法正常读写16M以上内存的BUG的调试过程相关推荐

  1. zynq petalinux编译系统启动文件实战应用

    前序:ZYNQ系统移植可以有三种系统: 第一种是linaro,我移植过的版本linaro2010~linaro2016,它的交叉编译器是arm-xilinx-linux-gnueabi-,不支持在线编 ...

  2. Xilinx zynq的资料获取总结

    Xilinx zynq zc702开发: 一.zynq开发整个生态系统搭建: 1.基础资料获取: https://github.com/Xilinx/           (包括:交叉编译工具,lin ...

  3. Xilinx Zynq开发教程

    作者 QQ群:852283276 微信:arm80x86 微信公众号:青儿创客基地 B站:主页 https://space.bilibili.com/208826118 Xilinx Zynq介绍 芯 ...

  4. Xilinx Zynq UltraScale+ MPSoC 介绍

    文章目录 简介 软件架构 petalinux工具 开发环境搭建 简介 MYC-CZU3EG 是深圳市米尔科技有限公司推出的一款以 Xilinx XCZU3EG 作为核心的嵌入式核心板. 采用了 Xil ...

  5. Xilinx zynq USB开发

    如何区分/dev/input/event cat /proc/bus/input/devices Xilinx zynq USB开发 https://blog.csdn.net/Zhu_Zhu_200 ...

  6. Xilinx ZYNQ MPSOC 多核高性能计算平台

    Xilinx ZYNQ MPSOC 多核高性能计算平台 转自:微信公众号 FPGA渠道及方案一站式服务商 本平台搭载16nm工艺的ZYNQ UltraScale XCZU15EG-2FFVB1156 ...

  7. ZYNQ petalinux中PCIE读写NVME固态硬盘

    一,环境搭建 1,安装Petalinux插件:将所需的依赖库都先安装(参考UG1144文档要求) sudo apt-get install tofrodos iproute2 gawk sudo ap ...

  8. ZYNQ petalinux系统启动文件固化到FLASH

    首先明确:petalinux启动文件从FLASH启动系统,也就是将启动文件放入FLASH中. 1,vivado配置: 2,导入硬件后配置petalinux source /opt/Xilinx/Viv ...

  9. Xilinx Zynq 7000 安装Linux 系统

    Xilinx Zynq 7000 安装Linux 系统 介绍 1 准备工作 2 工具的安装 2.1 支持库的安装 2.2 PetaLinux的安装 3 搭建硬件系统 3.1 建立工程 3.2 添加IP ...

最新文章

  1. spring boot原理_SpringBoot-02-原理初探之主启动类
  2. 使用js命名空间进行模块式开发
  3. mysql作为kafka生产者_Kafka之生产者
  4. java 及时释放内存_JMM(一):初识Java内存模型
  5. linux samba服务器
  6. 调试利器:浏览器 Logger
  7. [POJ3252]Round Number(数位dp)
  8. 斯坦福完全可解释深度神经网络:你需要用决策树搞点事
  9. 搭建微信令牌中控服务器,使用ThinkJs搭建微信中控服务的实现方法
  10. python定义类的程序_python扫码签到程序python中如何定义类
  11. ICCV 2019 中国论文数量超美国,商汤57篇论文入选!
  12. 实习成长之路:MySQL八:普通索引和唯一索引,应该怎么选择?
  13. 注意!思科Aironet 1830和1850系列存在硬编码密码,请尽快修复!
  14. 云路php解密网站源码_云路PHP解密-免费PHP文件解密工具
  15. mac卸载java1.7_Mac 下安装、卸载Java 7
  16. 定义fact(n)函数,调用函数,返回值
  17. 1247:河中跳房子
  18. Hive性能调优之推测执行
  19. mysql根据id取模备份_MySQL中取模运算的正负与被模数的符号相同
  20. numeric比较大小 数据库_数据库基础知识个人整理版-强烈推荐

热门文章

  1. freeglut_光照设置_材质设置_笔记与心得
  2. 8051单片机的内核的结构及运行过程解析
  3. C#开发WINCE系统的PDA程序,GetSystemMetrics获取屏幕长宽以达到自适应分辨率
  4. 一文让你通俗易懂的理解正交变换和正交矩阵
  5. 从“及其所之既倦”到“吾生也有涯,而知也无涯”
  6. 信息安全意识培训详解
  7. EDIUS设置3D转场的方法
  8. 哀思著名力学家钱伟长先生
  9. 从程序员到产品经理 第四章:敏捷开发和项目管理
  10. 文件包含漏洞1 | iwebsec