作者

QQ群:852283276
微信:arm80x86
微信公众号:青儿创客基地
B站:主页 https://space.bilibili.com/208826118

参考

zynq挂载32M qspi flash后不能复位的问题
2017.3 Zynq-7000 SoC: QSPI flash programming now requires that you specify an FSBL
AR# 70548 Zynq-7000 - QSPI programming in QSPI-boot mode
大于16MB的QSPI存放程序引起的ZYNQ重启风险
Topic: SPI Flash Unlock (Read 9479 times)

petalinux2019.1内核启动报错

boot扇区大小多加了一个0导致下面的报错,

[    7.630709] pc : add_mtd_device+0x34/0x308
[    7.634835] lr : add_mtd_partitions+0xb8/0xfc
[    7.639218] sp : ffffff80093cb630
[    7.642550] x29: ffffff80093cb630 x28: 0000000000000000 
[    7.647897] x27: 0000000000000000 x26: ffffff8009181820 
[    7.653244] x25: ffffff80091817b0 x24: 0000000000000003 
[    7.658591] x23: ffffffc03eb7f020 x22: 0000000000000002 
[    7.663938] x21: ffffffc007058160 x20: ffffffc03e522800 
[    7.669285] x19: ffffffc03e522800 x18: 0000000000000010 
[    7.674632] x17: 0000000000000000 x16: ffffffc03f342800 
[    7.679979] x15: 000000000000ad55 x14: ffffff8009148648 
[    7.685325] x13: 0000000000000001 x12: 00000000ffffffff 
[    7.690672] x11: ffffff8008b9ac90 x10: 0000000000000003 
[    7.696019] x9 : 0000000000000002 x8 : 0000000000000010 
[    7.701366] x7 : 0000000000000000 x6 : 0000000000000126 
[    7.706713] x5 : 00000000ad55ad55 x4 : 0000000000000000 
[    7.712060] x3 : ffffff8009181790 x2 : 0000000000000000 
[    7.717407] x1 : ffffffc03f342800 x0 : 0000000000000c00 
[    7.725720] Call trace:
[    7.731161]  add_mtd_device+0x34/0x308
[    7.737939]  add_mtd_partitions+0xb8/0xfc
[    7.744986]  parse_mtd_partitions+0x208/0x3f4
[    7.752405]  mtd_device_parse_register+0x3c/0x170
[    7.760160]  m25p_probe+0x11c/0x1f0
[    7.766658]  spi_mem_probe+0x6c/0xa0
[    7.773207]  spi_drv_probe+0x7c/0xd8
[    7.779704]  really_probe+0x1c8/0x280
[    7.786259]  driver_probe_device+0x54/0xe8
[    7.793212]  __device_attach_driver+0xb8/0xe8
[    7.800395]  bus_for_each_drv+0x78/0xc8
[    7.807028]  __device_attach+0xd4/0x130
[    7.813627]  device_initial_probe+0x10/0x18
[    7.820542]  bus_probe_device+0x90/0x98
[    7.827079]  device_add+0x334/0x608
[    7.833225]  spi_add_device+0xac/0x168
[    7.839596]  of_register_spi_device+0x214/0x320
[    7.846727]  spi_register_controller+0x290/0x618
[    7.853805] ata2: SATA link down (SStatus 0 SControl 330)
[    7.853928]  zynqmp_qspi_probe+0x3f4/0x530
[    7.861922] ata1: SATA link down (SStatus 0 SControl 330)
[    7.868534]  platform_drv_probe+0x50/0xa0
[    7.868537]  really_probe+0x1c8/0x280
[    7.868543]  driver_probe_device+0x54/0xe8
[    7.895684]  __device_attach_driver+0xb8/0xe8
[    7.902465]  bus_for_each_drv+0x78/0xc8
[    7.908688]  __device_attach+0xd4/0x130
[    7.914867]  device_initial_probe+0x10/0x18
[    7.921368]  bus_probe_device+0x90/0x98
[    7.927477]  deferred_probe_work_func+0x6c/0xa0
[    7.934310]  process_one_work+0x1e4/0x340
[    7.940587]  worker_thread+0x248/0x488
[    7.946621]  kthread+0x124/0x128
[    7.952092]  ret_from_fork+0x10/0x18
[    7.957922] ---[ end trace 2efc48a93a7bfe37 ]---
[    7.964827] ------------[ cut here ]------------
[    7.971690] kernel BUG at fs/sysfs/file.c:328!
[    7.978356] Internal error: Oops - BUG: 0 [#1] SMP
[    7.985372] Modules linked in:
[    7.990608] CPU: 3 PID: 60 Comm: kworker/3:1 Tainted: G        W         4.19.0-xilinx-v2019.1 #1
[    8.001688] Hardware name: xlnx,zynqmp (DT)
[    8.008053] Workqueue: events deferred_probe_work_func
[    8.015359] pstate: 40000005 (nZcv daif -PAN -UAO)
[    8.022283] pc : sysfs_create_file_ns+0x8c/0x98
[    8.028924] lr : sysfs_create_files+0x3c/0xb8
[    8.035351] sp : ffffff80093cb5e0
[    8.040713] x29: ffffff80093cb5e0 x28: 0000000000000000 
[    8.048089] x27: 0000000000000000 x26: ffffff8009181820 
[    8.055454] x25: ffffff80091817b0 x24: 0000000000000003 
[    8.062832] x23: ffffffc03eb7f020 x22: ffffffc03e5229a0 
[    8.070209] x21: ffffff8009148648 x20: 0000000000000000 
[    8.077589] x19: ffffffc03e5229a0 x18: 0000000000000010 
[    8.084956] x17: 0000000000000000 x16: ffffffc03f342800 
[    8.092322] x15: 000000000000ad55 x14: ffffff8009148648 
[    8.099690] x13: 0000000000000001 x12: 00000000ffffffff 
[    8.107054] x11: ffffff8008b9ac90 x10: 0000000000000003 
[    8.114414] x9 : 0000000000000002 x8 : 0000000000000010 
[    8.121770] x7 : 0000000000000000 x6 : 0000000000000126 
[    8.129120] x5 : 00000000ad55ad55 x4 : 0000000000000000 
[    8.136466] x3 : 0000000000000000 x2 : 0000000000000000 
[    8.143798] x1 : ffffff80091817e0 x0 : ffffffc03e5229a0 
[    8.151143] Process kworker/3:1 (pid: 60, stack limit = 0x(____ptrval____))
[    8.160186] Call trace:
[    8.164705]  sysfs_create_file_ns+0x8c/0x98
[    8.170985]  sysfs_create_files+0x3c/0xb8
[    8.177086]  mtd_add_partition_attrs+0x20/0x48
[    8.183615]  add_mtd_partitions+0xc0/0xfc
[    8.189704]  parse_mtd_partitions+0x208/0x3f4
[    8.196155]  mtd_device_parse_register+0x3c/0x170
[    8.202959]  m25p_probe+0x11c/0x1f0
[    8.208536]  spi_mem_probe+0x6c/0xa0
[    8.214199]  spi_drv_probe+0x7c/0xd8
[    8.219845]  really_probe+0x1c8/0x280
[    8.225583]  driver_probe_device+0x54/0xe8
[    8.231770]  __device_attach_driver+0xb8/0xe8
[    8.238219]  bus_for_each_drv+0x78/0xc8
[    8.240186] random: fast init done
[    8.244146]  __device_attach+0xd4/0x130
[    8.255541]  device_initial_probe+0x10/0x18
[    8.261813]  bus_probe_device+0x90/0x98
[    8.267739]  device_add+0x334/0x608
[    8.273309]  spi_add_device+0xac/0x168
[    8.279143]  of_register_spi_device+0x214/0x320
[    8.285765]  spi_register_controller+0x290/0x618
[    8.292477]  zynqmp_qspi_probe+0x3f4/0x530
[    8.298648]  platform_drv_probe+0x50/0xa0
[    8.304721]  really_probe+0x1c8/0x280
[    8.310433]  driver_probe_device+0x54/0xe8
[    8.316572]  __device_attach_driver+0xb8/0xe8
[    8.322976]  bus_for_each_drv+0x78/0xc8
[    8.328865]  __device_attach+0xd4/0x130
[    8.334744]  device_initial_probe+0x10/0x18
[    8.340974]  bus_probe_device+0x90/0x98
[    8.346853]  deferred_probe_work_func+0x6c/0xa0
[    8.353443]  process_one_work+0x1e4/0x340
[    8.359506]  worker_thread+0x248/0x488
[    8.365299]  kthread+0x124/0x128
[    8.370564]  ret_from_fork+0x10/0x18
[    8.376169] Code: a94153f3 a9425bf5 a8c47bfd d65f03c0 (d4210000) 
[    8.384335] ---[ end trace 2efc48a93a7bfe38 ]---
[  115.440205] random: crng init done

xilinx_spi 87000000.axi_quad_spi: can’t setup spi1.0, status -13

petalinux2017.2的代码,spi-nor报错xilinx_spi 87000000.axi_quad_spi: can't setup spi1.0, status -13,定位代码,

//drivers\spi\spi-xilinx.c 809
ret = spi_register_master(master);
if (ret) {
	dev_err(&pdev->dev, "spi_register_master failed\n");
	goto clk_unprepare_all;
}
//drivers\spi\spi.c 2182
of_register_spi_devices(ctlr);
//drivers\spi\spi.c 1682
spi = of_register_spi_device(ctlr, nc);
//drivers\spi\spi.c
rc = spi_add_device(spi);
if (rc) {
	dev_err(&ctlr->dev, "spi_device register error %pOF\n", nc);
	goto err_of_node_put;
}
//drivers\spi\spi.c 544
status = spi_setup(spi);
if (status < 0) {
	dev_err(dev, "can't setup %s, status %d\n",
			dev_name(&spi->dev), status);
	goto done;
}
//drivers\spi\spi.c 2761
if (spi->controller->setup)
	status = spi->controller->setup(spi);
//drivers\spi\spi-xilinx.c 378
static int xspi_setup(struct spi_device *qspi)
{
	int ret;
	struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master);

	if (qspi->master->busy)
		return -EBUSY;

	ret = pm_runtime_get_sync(xqspi->dev);
	if (ret < 0)
		return ret;

	ret = xspi_setup_transfer(qspi, NULL);
	pm_runtime_put_sync(xqspi->dev);

	return ret;
}

定位到代码pm_runtime_get_sync的参数xqspi->dev错误,上面列出的代码是已经修正的版本,这个问题Xilinx官方也已经做出了修正。

CONFIG_MTD_SPI_NOR_USE_4K_SECTORS

根据spi_nor_ids指示芯片是否支持4K扇区,开启这个宏之后,擦除扇区大小就是4K,此处和UBIFS可能会产生不兼容,项目中开启这个宏是因为制作FPGA Golden Image时前4K用作跳转头,为了可方便的更改跳转头,且项目不使用UBIFS(目前仅在nand上有UBIFS使用经验),后期将去除这个使能,保证UBIFS的正确使用。

ZC706 S25FL128SAGMFIR01

petalinux2015.2.1的m25p80.cm25p_ids没有s25fl128s,导致内核直接不scan了,而spi-nor.c支持s25fl128s{"s25sl12800"}, {"s25sl12801"}, {"s25fl128s"},这里请看清楚一个是sl,一个是fl

128MB以上qspi flash重启失败

3字节寻址模式,bootrom不会设置bank寄存器,如果cold reset,flash自然会处于BOOTROM认识的状态,但是warm reset时,如果之前切换到别的bank或者进入4Bytes模式,就会导致BOOTROM找不到正确的景象,从而启动失败。这是由血泪教训验证出来的。所以软件在主动复位之前,一定要把flash设置为默认的模式;如果系统外接了硬件看门狗,看门狗也reset要一并拉到flash的reset引脚上,

static void m25p_s25fl256s_reset(struct spi_device *spi)
{
    struct m25p *flash = spi_get_drvdata(spi);
        flash->command[0] = 0xf0;  //reset command
        spi_write(flash->spi, flash->command, 1); 
        printk(KERN_INFO "reset qspi flash\n");
        return;
}
static struct spi_driver m25p80_driver = {
    .driver = {
        .name   = "m25p80",
        .owner  = THIS_MODULE,
    },
    .id_table   = m25p_ids,
    .probe  = m25p_probe,
    .remove = m25p_remove,
        .shutdown = m25p_s25fl256s_reset,
    /* REVISIT: many of these chips have deep power-down modes, which
     * should clearly be entered on suspend() to minimize power use.
     * And also when they're otherwise idle...
     */
};

国产zynq

改成qspix4模式在跑,复旦微的两片在高温下可能会出现读写问题。

qspi flash下载失败

XIL_CSE_ZYNQ_UBOOT_QSPI_FREQ_HZ

If you have issues programming the FLASH in Vivado 2017.3 or 2017.4, add the following environment variable.(The ENV variable is not required for 2018.1):XIL_CSE_ZYNQ_UBOOT_QSPI_FREQ_HZ = 10000000, This will force the mini-uBoot to set the QSPI device clock to 10 MHz.
Note: depending on your FSBL design, you might see a different QSPI clock on your hardware.

AR# 51063 14.1 Zynq-7000 - Why is QSPI programming not working when the feedback clock is used?

To program QSPI reliably with a clock that is greater than FQSPICLK2:

Ensure that the MIO[8] (qspi_sclk_fb_out) is floated or connected to a pull-up/pull-down resistor on the PCB, and that the Quad-SPI external loopback is be enabled. MIO[8] must be free of any additional loading.
To program QSPI reliably with a QSPI Clock that is less than FQSPICLK2:

Ensure that the operating frequency (QSPI interface clock) is lower than FQSPICLK2 (see DS187).
Make sure QSPI external loopback is disabled (see qspi.LPBK_DLY_ADJ register in the Zynq TRM).
Disabling the feedback mode allows MIO[8] to be used with additional loading.

AR# 51248 Zynq-7000 - ZC702 支持什么 QSPI 时钟模式/速度?

由于 MIO8 引脚连接于装入程序并用于GPIO,ZC702 仅支持 <40MHz QSPI 时钟运行。这意味着当 MIO8 用于其它用途,不可使用反馈时钟模式。

qspi flash读写错误

在linux上尝试用fw_printenv获取环境变量发现crc错误,用dd+hexdump和uboot下读取的flash分区比较(uboot env print可显示环境变量的大小),发现有个别数据读取错误,这里使用了冗余环境变量分区,前面的9485 e1f7指示当前分区是否是有效的环境变量分区。

root@mwm:~# dd if=/dev/mtd1 of=1.txt bs=8K count=1
root@mwm:~# hexdump 1.txt 

ZynqMP> env print
autoload=no
baudrate=115200
Environment size: 7198/131067 bytes
ZynqMP> md.w ${clobstart} 0x2000            
10000000: 9485 e1f7 6101 7475 6c6f 616f 3d64 6f6e    .....autoload=no

设备树配置

spi@ff0f0000 {
	u-boot,dm-pre-reloc;
	compatible = "xlnx,zynqmp-qspi-1.0";
	status = "okay";
	clock-names = "ref_clk", "pclk";
	interrupts = <0x0 0xf 0x4>;
	interrupt-parent = <0x4>;
	num-cs = <0x1>;
	reg = <0x0 0xff0f0000 0x0 0x1000 0x0 0xc0000000 0x0 0x8000000>;
	#address-cells = <0x1>;
	#size-cells = <0x0>;
	#stream-id-cells = <0x1>;
	iommus = <0xe 0x873>;
	power-domains = <0x1e>;
	clocks = <0x3 0x35 0x3 0x1f>;
	is-dual = <0x1>;
	spi-rx-bus-width = <0x4>;
	spi-tx-bus-width = <0x4>;

	flash@0 {
		compatible = "n25q512a", "micron,m25p80";
		spi-tx-bus-width = <0x1>;
		spi-rx-bus-width = <0x4>;
		reg = <0x0>;
		#address-cells = <0x1>;
		#size-cells = <0x1>;
		/*spi-max-frequency = <0x66ff300>;*/
		spi-max-frequency = <0x337F980>;

		partition@0x00000000 {
			label = "boot";
			reg = <0x0 0x100000>;
		};

将总线频率降低一半,数据读取正确,rx-bus-width还是保持为4。

写保护

去除写保护,

#include "xparameters.h"
#include "xspi.h"
#include "xspi_l.h"

#define SPI_WREN            0x06
#define   SPI_WRSR            0x01
#define SPI_RDSR1            0x05
#define RDSR1_BYTES            2
#define WREN_BYTES            1
#define WRSR_BYTES            2

#define SPI_SELECT            0x01
#define BUSY_MASK            0x01

int main(void){
   XSpi Spi;
   u8 WriteBuffer[4];
   u8 ReadBuffer[4];
   int Status;

   XSpi_Config *ConfigPtr;
   ConfigPtr = XSpi_LookupConfig(XPAR_SPI_0_DEVICE_ID);
   if (ConfigPtr == NULL)
      return XST_DEVICE_NOT_FOUND;

   Status = XSpi_CfgInitialize(&Spi, ConfigPtr, ConfigPtr->BaseAddress);
   if (Status != XST_SUCCESS)
      return XST_FAILURE;

   Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
         XSP_MANUAL_SSELECT_OPTION);
   if(Status != XST_SUCCESS)
      return XST_FAILURE;

   Status = XSpi_SetSlaveSelect(&Spi, SPI_SELECT);
   if(Status != XST_SUCCESS)
      return XST_FAILURE;

   XSpi_Start(&Spi);            // Start
   XSpi_IntrGlobalDisable(&Spi);   // Pooled mode

   // Wait till ready

   WriteBuffer[0] = SPI_RDSR1;
   do{
      XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, RDSR1_BYTES);
   }
   while((ReadBuffer[1] & BUSY_MASK)==BUSY_MASK);

   // Send Write Enable
   WriteBuffer[0] = SPI_WREN;   // Write enable
   XSpi_Transfer(&Spi, WriteBuffer, NULL, WREN_BYTES);
   // Write 0 to Status Register
   WriteBuffer[0] = SPI_WRSR;   // Write Status Register
   WriteBuffer[1] = 0x00;      // Clear all bits
   XSpi_Transfer(&Spi, WriteBuffer, NULL, WRSR_BYTES);

   return 0;
}
Logo

更多推荐