小模块例程:qspi_w25qxx - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

zynq

  • mb_zynq_periph_test
  • 经过测试和翻阅手册,发现AXI QSPI这个IP,不支持QPI模式,只支持SPI/DSPI/QSPI模式
  • 但不确定在XIP模式,是否支持QPI? 待测试。
  • 测试过程发现了一个很奇特的事情:0x06与0x20指令,会间隔好几个ms;但是0x06与0x02或0x32指令之间,只有几十us。这可能是AXI QSPI硬件的行为,也就是page program之前的准备时间要很长

一些指令的定义

#define COMMAND_PAGE_PROGRAM		0x02 /* Page Program command */
#define COMMAND_QUAD_WRITE		0x32 /* Quad Input Fast Program */
#define COMMAND_RANDOM_READ		0x03 /* Random read command */
#define COMMAND_DUAL_READ		0x3B /* Dual Output Fast Read */
#define COMMAND_DUAL_IO_READ		0xBB /* Dual IO Fast Read */
#define COMMAND_QUAD_READ		0x6B /* Quad Output Fast Read */
#define COMMAND_QUAD_IO_READ		0xEB /* Quad IO Fast Read */
#define	COMMAND_WRITE_ENABLE		0x06 /* Write Enable command */
#define COMMAND_SECTOR_ERASE		0xD8 /* Sector Erase command */
#define COMMAND_BULK_ERASE		0xC7 /* Bulk Erase command */
#define COMMAND_STATUSREG_READ		0x05 /* Status read command */

/**
 * This definitions specify the EXTRA bytes in each of the command
 * transactions. This count includes Command byte, address bytes and any
 * don't care bytes needed.
 */
#define READ_WRITE_EXTRA_BYTES		4 /* Read/Write extra bytes */
#define	WRITE_ENABLE_BYTES		1 /* Write Enable bytes */
#define SECTOR_ERASE_BYTES		4 /* Sector erase extra bytes */
#define BULK_ERASE_BYTES		1 /* Bulk erase extra bytes */
#define STATUS_READ_BYTES		2 /* Status read bytes count */
#define STATUS_WRITE_BYTES		2 /* Status write bytes count */

读写测试qspi flash的主程序

#include "COMMON.h"

typedef struct{
	u8 txbuf[32];
	u8 rxbuf[32];
	u8 length;
}t_buf;

t_buf WriteBuffer[]={
    //s1: read id
	{{0x90},{0x00},6},
	{{0x9f},{0x00},8},
	{{0x4b},{0x00},13},

	//s2: sector erase
	{{0x06},{0x00},1},
	{{0x20,0x00,0x00,0x10},{0x00},4},
	{{0xff},{0x00},0}, //length=0 => delay_ms

	//s3: page program
	{{0x06},{0x00},1},
	{{0x02,0x00,0x00,0x10,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88},{0x00},12},
	{{0xff},{0x00},0}, //length=0 => delay_ms

	//s4: spi/dspi/qspi read
	{{0x0b,0x00,0x00,0x10},{0x00},14},
	{{0x3b,0x00,0x00,0x10},{0x00},14},
	{{0x6b,0x00,0x00,0x10},{0x00},14},

	//s5: sector erase
	{{0x06},{0x00},1},
	{{0x20,0x00,0x00,0x10},{0x00},4},
	{{0xff},{0x00},0}, //length=0 => delay_ms

	//s6: qspi program
	{{0x06},{0x00},1},
	{{0x32,0x00,0x00,0x10,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x11,0x22},{0x00},12},
	{{0xff},{0x00},0}, //length=0 => delay_ms

	//s7: qspi read
	{{0x6b,0x00,0x00,0x10},{0x00},14},
	{{0xbb,0x00,0x00,0x10},{0x00},14},
	{{0xeb,0x00,0x00,0x10},{0x00},14},

	//s8: enter qpi mode (QE=1), 貌似不支持
//	{{0x38},{0x00},1},   //not support
//	{{0x01,0x00,0x02},{0x00},3},
//	{{0xA3,0x00,0x00,0x00},{0x00},4},
//
//	//s9: sector erase
//	{{0x06},{0x00},1},
//	{{0x20,0x00,0x00,0x10},{0x00},4},
//	{{0xff},{0x00},0}, //length=0 => delay_ms
//
//	//s10: qpi read
//	{{0x0b,0x00,0x00,0x10},{0x00},14},
//
//	//s11: qpi program
//	{{0x06},{0x00},1},
//	{{0x02,0x00,0x00,0x10,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11},{0x00},12},
//	{{0xff},{0x00},0}, //length=0 => delay_ms
//
//	//s12: qpi read
//	{{0xbb,0x00,0x00,0x10},{0x00},14},
//	{{0xeb,0x00,0x00,0x10},{0x00},14},
};



void print_buffer(u8 *pdata, int length)
{
	for(int i=0; i<length; i++){
		xil_printf("pdata[%d]=%x\r\n", i, pdata[i]);
	}
	xil_printf("********************\r\n");
}

int main(void)
{

	//初始化通用中断控制器
	ScuGic_Init();

	//初始化AXI_SPI0,设为主机模式
	AXI_SPI_Init(&AXI_SPI0, XPAR_SPI_1_DEVICE_ID, XSP_MASTER_OPTION);

	//初始化私有定时器中断,定时间隔100ms
	ScuTimer_Int_Init(100000);

	for(int i=0; i<sizeof(WriteBuffer)/sizeof(*WriteBuffer); i++){
		if(WriteBuffer[i].length==0){
			usleep(WriteBuffer[i].txbuf[0]*1000);
			continue;
		}

		AXI_SPI_Transfer(&AXI_SPI0, 0, WriteBuffer[i].rxbuf, WriteBuffer[i].txbuf, WriteBuffer[i].length);
		xil_printf("Exec CMD=%x\r\n\r\n", WriteBuffer[i].txbuf[0]);
		print_buffer(WriteBuffer[i].rxbuf, WriteBuffer[i].length);
	}


	while(1) {
		//刷新间隔由私有定时器中断控制,中断服务函数在ISR.c中
		if(Refresh_Flag) {
			Refresh_Flag = 0;

			//xil_printf("timer run!\r\n");
		}
	}

	return 0;
}

附录

  • 模块框图 image

  • 引脚约束

#create_clock -period 20.000 -name sys_clk [get_ports sys_clk]
#set_property -dict {PACKAGE_PIN N18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
#set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]

set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports uart_rxd]
set_property -dict {PACKAGE_PIN G15 IOSTANDARD LVCMOS33} [get_ports uart_txd]

set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports {key_tri_io[0]}]
set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports {key_tri_io[1]}]

set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports {led_tri_io[0]}]
set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports {led_tri_io[1]}]
set_property -dict {PACKAGE_PIN H18 IOSTANDARD LVCMOS33} [get_ports pwm]
#set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports {iic_gpio[0]}]

set_property -dict {PACKAGE_PIN E19 IOSTANDARD LVCMOS33} [get_ports i2c1_scl_io]
set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS33} [get_ports i2c1_sda_io]

set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports i2c2_scl_io]
set_property -dict {PACKAGE_PIN P16 IOSTANDARD LVCMOS33} [get_ports i2c2_sda_io]

# for qspi w25qxx
set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {qspi_ss_io[0]}]
set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports qspi_sck_io]
set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS33} [get_ports qspi_io0_io]
set_property -dict {PACKAGE_PIN F19 IOSTANDARD LVCMOS33} [get_ports qspi_io1_io]
set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS33} [get_ports qspi_io2_io]
set_property -dict {PACKAGE_PIN J20 IOSTANDARD LVCMOS33} [get_ports qspi_io3_io]

set_property SLEW FAST [get_ports qspi_io0_io]
set_property SLEW FAST [get_ports qspi_io1_io]
set_property SLEW FAST [get_ports qspi_io2_io]
set_property SLEW FAST [get_ports qspi_io3_io]
set_property SLEW FAST [get_ports qspi_sck_io]

set_property PULLUP true [get_ports i2c2_scl_io]
set_property PULLUP true [get_ports i2c2_sda_io]


# for my w25qxx
#set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {spi_ss_io[0]}]
#set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS33} [get_ports spi_sck_io]
#set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS33} [get_ports spi_io0_io]
#set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports spi_io1_io]

#set_property SLEW FAST [get_ports spi_io0_io]
#set_property SLEW FAST [get_ports spi_io1_io]
#set_property SLEW FAST [get_ports spi_sck_io]

# for st7789
set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {spi_ss_io[0]}]
set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports spi_sck_io]
set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports spi_io0_io]
set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports spi_io1_io]

set_property SLEW FAST [get_ports spi_io0_io]
set_property SLEW FAST [get_ports spi_io1_io]
set_property SLEW FAST [get_ports spi_sck_io]

set_property -dict {PACKAGE_PIN T17 IOSTANDARD LVCMOS33} [get_ports {spi_rst_dc_tri_io[0]}]
set_property -dict {PACKAGE_PIN R16 IOSTANDARD LVCMOS33} [get_ports {spi_rst_dc_tri_io[1]}]

测试结果

Exec CMD=90

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=0
pdata[4]=EF
pdata[5]=15
********************
Exec CMD=9F

pdata[0]=0
pdata[1]=EF
pdata[2]=40
pdata[3]=16
pdata[4]=0
pdata[5]=0
pdata[6]=0
pdata[7]=0
********************
Exec CMD=4B

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=0
pdata[4]=0
pdata[5]=DE
pdata[6]=67
pdata[7]=70
pdata[8]=D8
pdata[9]=7
pdata[10]=F
pdata[11]=33
pdata[12]=24
********************
Exec CMD=6

pdata[0]=0
********************
Exec CMD=20

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=0
********************
Exec CMD=6

pdata[0]=0
********************
Exec CMD=2

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=0
pdata[4]=0
pdata[5]=0
pdata[6]=0
pdata[7]=0
pdata[8]=0
pdata[9]=0
pdata[10]=0
pdata[11]=0
********************
Exec CMD=B

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=0
pdata[4]=0
pdata[5]=11
pdata[6]=22
pdata[7]=33
pdata[8]=44
pdata[9]=55
pdata[10]=66
pdata[11]=77
pdata[12]=88
pdata[13]=FF
********************
Exec CMD=3B

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=0
pdata[4]=0
pdata[5]=0
pdata[6]=11
pdata[7]=22
pdata[8]=33
pdata[9]=44
pdata[10]=55
pdata[11]=66
pdata[12]=77
pdata[13]=88
********************
Exec CMD=6B

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=C
pdata[4]=CC
pdata[5]=CC
pdata[6]=CC
pdata[7]=CC
pdata[8]=11
pdata[9]=22
pdata[10]=33
pdata[11]=44
pdata[12]=55
pdata[13]=66
********************
Exec CMD=6

pdata[0]=0
********************
Exec CMD=20

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=0
********************
Exec CMD=6

pdata[0]=0
********************
Exec CMD=32

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=C
pdata[4]=A
pdata[5]=B
pdata[6]=C
pdata[7]=D
pdata[8]=E
pdata[9]=F
pdata[10]=1
pdata[11]=2
********************
Exec CMD=6B

pdata[0]=0
pdata[1]=0
pdata[2]=0
pdata[3]=C
pdata[4]=CC
pdata[5]=CC
pdata[6]=CC
pdata[7]=CC
pdata[8]=AA
pdata[9]=BB
pdata[10]=CC
pdata[11]=DD
pdata[12]=EE
pdata[13]=FF
********************
Exec CMD=BB

pdata[0]=1
pdata[1]=0
pdata[2]=0
pdata[3]=10
pdata[4]=0
pdata[5]=AA
pdata[6]=BB
pdata[7]=CC
pdata[8]=DD
pdata[9]=EE
pdata[10]=FF
pdata[11]=11
pdata[12]=22
pdata[13]=FF
********************
Exec CMD=EB

pdata[0]=D
pdata[1]=0
pdata[2]=0
pdata[3]=10
pdata[4]=0
pdata[5]=CC
pdata[6]=CC
pdata[7]=AA
pdata[8]=BB
pdata[9]=CC
pdata[10]=DD
pdata[11]=EE
pdata[12]=FF
pdata[13]=11
********************

测试波形

image image image image image image image image image image image