ZYNQ裸机-使用AXI QSPI读写超过16MiB Flash的问题(已解决)

一、AXI QSPI的模式

1.PL端配置:

记得接中断引脚,虽然代码里没用,但是似乎涉及到一些状态机,会导致返回值错误

2.PS端初始化:


int hal_axi_spi_init(XSpi *xspi, uint16_t dev_id, uint8_t slave_id)
{
	int Status;
	XSpi_Config *xspi_cfg;

	xspi_cfg = XSpi_LookupConfig(dev_id);
	if (xspi_cfg == NULL) {
		return XST_DEVICE_NOT_FOUND;
	}

	/* 初始化控制器 */
	Status = XSpi_CfgInitialize(xspi, xspi_cfg,
			xspi_cfg->BaseAddress);
	if (Status != XST_SUCCESS) {
		return Status;
	}

	/* 硬件自检 */
	Status = XSpi_SelfTest(xspi);
	if (Status != XST_SUCCESS) {
		return Status;
	}

	/* 验证SPI模式是否为Quad模式 */
	if (xspi->SpiMode != XSP_QUAD_MODE) {
		return XST_FLASH_NOT_SUPPORTED;
	}

	/* 配置控制器选项 */
	Status = XSpi_SetOptions(xspi,
			XSP_MASTER_OPTION |
			XSP_MANUAL_SSELECT_OPTION);
	if(Status != XST_SUCCESS) {
		return Status;
	}

	/* 设置从设备选择 */
	Status = XSpi_SetSlaveSelect(xspi, 1 << slave_id);
	if(Status != XST_SUCCESS)
	{
		return Status;
	}

	/* 启动SPI控制器 */
	Status = XSpi_Start(xspi);
	if(Status != XST_SUCCESS) {
		return Status;
	}

	/* 禁用中断以使用轮询模式 */
	XSpi_IntrGlobalDisable(xspi);

	return XST_SUCCESS;
}

3.此时QSPI的模式:Quad Output

也就是命令和地址发送使用1线,数据收发使用4线;

 

二、读写w25q256之类大容量flash,Xilinx的坑

(笔者多次提到的,xilinx坑爹的印度程序老哥,能用就行,从不多测试 TAT )

1.xilinx的例程

默认只支持3Byte地址模式,使用指令0x6B读取,0x32写入,0x20擦除;

这是笔者测试完成的,3Byte读写擦的,部分关键代码:

(这里有个疑惑,为什么要用0x01 00 02,设置quad模式,这和手册上的完全对不上)


int qspi_w25qxx_init(QSPI_W25QXX_T *qspi_w25qxx,
				int (*qspi_transf)(uint8_t *tx, uint8_t *rx, uint16_t len),
				void (*delay)(uint32_t us))
{
	memset(qspi_w25qxx, 0, sizeof(QSPI_W25QXX_T));

	qspi_w25qxx->hal.qspi_transf = qspi_transf;
	qspi_w25qxx->hal.delay = delay;
	qspi_w25qxx->status.error = 0;

	// reboot
//	qspi_w25qxx_reboot(qspi_w25qxx);

	// enable QSPI 4 line (QUAD) mode
	qspi_w25qxx_quad_en(qspi_w25qxx);

	// enable 4byte address mode
#if ADDR4BYTE_EN
	qspi_w25qxx_addr4byte_en(qspi_w25qxx);
#endif

	// read ID
	qspi_w25qxx_read_id(qspi_w25qxx);

	//check
	if((qspi_w25qxx->reg.id & 0x00EF0000) != 0x00EF0000)
	{
		//Quad mode error
		qspi_w25qxx->status.error |= 1<<(0);
	}
	if((qspi_w25qxx->reg.state[1] & 0x02) == 0)
	{
		//Quad mode error
		qspi_w25qxx->status.error |= 1<<(1);
	}
//	if((qspi_w25qxx->reg.state[2] & 0x01) == 0)
//	{
//		//4Byte Addr mode err
//		qspi_w25qxx->status.error |= 1<<(2);
//	}

	return qspi_w25qxx->status.error;
}


static void qspi_w25qxx_quad_en(QSPI_W25QXX_T *qspi_w25qxx)
{
	qspi_w25qxx_write_en(qspi_w25qxx);

    qspi_w25qxx->buf.tx[0] = 0x01;
    qspi_w25qxx->buf.tx[1] = 0x00;
    qspi_w25qxx->buf.tx[2] = 0x02;  // Status Register-2的QE位(Bit 1)
    qspi_w25qxx_transf(qspi_w25qxx, qspi_w25qxx->buf.tx, NULL, 3, TIMEOUT_MAX_US);

    qspi_w25qxx->buf.tx[0] = READ_REG_2_CMD;
    qspi_w25qxx->buf.tx[1] = 0x00;
    qspi_w25qxx_transf(qspi_w25qxx, qspi_w25qxx->buf.tx, qspi_w25qxx->buf.rx, 2, 0);
	qspi_w25qxx->reg.state[1] = qspi_w25qxx->buf.rx[1];
}

2.针对4Byte模式的修正

(2025-4-10,zzl:目前这个我还没测试通过,后续测试成功后,我把代码放在这里)

如果需要使用4Byte地址模式,应该使用0x6C读取,0x34写入,0x21擦除;

 

(2025-5-21,zzl:测试了几天,实在无法兼容Quad模式,改用Standard模式,裸机和petalinux都正常了)

引脚用Q0 Q1 CLK CS即可,flash手册和zynq的io设置都有标注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值