Xilinx zynq zynqmp qspi
qspi flash读写错误在linux上尝试用fw_printenv获取环境变量发现crc错误,用dd+hexdump和uboot下读取的flash分区比较(uboot env print可显示环境变量的大小),发现有个别数据读取错误,这里使用了冗余环境变量分区,前面的9485 e1f7指示当前分区是否是有效的环境变量分区。root@mwm:~# dd if=/dev/mtd1 of=1....
作者
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.c
的m25p_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;
}
更多推荐
所有评论(0)