XilinxProcessorIPLib/drivers/qspips/examples/xqspips_dual_flash_stack_lqspi_example.c
int DualStackExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
{
	int Status;
	u8 UniqueValue;
	int Count;
	int Page;
	XQspiPs_Config *QspiConfig;


	/* Initialize the QSPI driver so that it's ready to use*/
	QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
	if (QspiConfig == NULL) {
		return XST_FAILURE;
	}

	Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
					QspiConfig->BaseAddress);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/* Perform a self-test to check hardware build*/
	Status = XQspiPs_SelfTest(QspiInstancePtr);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/* Check if two flash devices are connected in stacked mode*/
	if (QspiConfig->ConnectionMode != XQSPIPS_CONNECTION_MODE_STACKED) {
		xil_printf("QSPI not connected in Stacked Configuration \n");
		return XST_FAILURE;
	}

	XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
	/*
	 * Set the QSPI device as a master and enable manual CS, manual start
	 * and flash interface mode options and drive HOLD_B pin high.
	 */
	XQspiPs_SetOptions(QspiInstancePtr,  XQSPIPS_FORCE_SSELECT_OPTION |
					    XQSPIPS_MANUAL_START_OPTION |
					    XQSPIPS_HOLD_B_DRIVE_OPTION);

	/*
	 * Enable two flash memories, shared bus (NOT separate bus0,
	 * L_PAGE selected by default
	 */
	XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_WRITE);

	FlashReadID();

	FlashQuadEnable(QspiInstancePtr);

	/* Assert the Flash chip select.*/
	XQspiPs_SetSlaveSelect(QspiInstancePtr);

	/*
	 * Initialize the write buffer for a pattern to write to the Flash
	 * and the read buffer to zero so it can be verified after the read, the
	 * test value that is added to the unique value allows the value to be
	 * changed in a debug environment to guarantee
	 */
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
	     Count++, UniqueValue++) {
		WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
	}
	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));



	/* Erase the flash sectors*/
	FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);

	/*
	 * The two stacked 16MB memories are equivalent to one continuous 32MB.
	 * Write data to the two flash memories on the same bus one at a time,
	 * starting from TEST_ADDRESS. Flash_Write and Flash_Erase functions
	 * will select the lower or upper memory based on the address.
	 */
	for (Page = 0; Page < PAGE_COUNT; Page++) {
		FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
			   TEST_ADDRESS), PAGE_SIZE, WRITE_CMD);
	}



	/*
	 * Read from the two flash memories one after the other using
	 * LQSPI mode. The LQSPI controller takes care of selecting
	 * the lower or upper memory based on address bit 25.
	 */
	XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION);

	XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_QUAD_READ);

	Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
				   MAX_DATA);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
	     Count++, UniqueValue++) {

		if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {

			return XST_FAILURE;
		}
	}

	/*
	 * Set the QSPI device as a master and enable manual CS, manual start
	 * and flash interface mode options and drive HOLD_B pin high.
	 */
	XQspiPs_SetOptions(QspiInstancePtr,  XQSPIPS_FORCE_SSELECT_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION);

	/*
	 * Initialize the write buffer for a pattern to write to the Flash
	 * and the read buffer to zero so it can be verified after the read, the
	 * test value that is added to the unique value allows the value to be
	 * changed in a debug environment to guarantee
	 */
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
	     Count++, UniqueValue++) {
		WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
	}
	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));

	/* Erase the flash sectors*/
	FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);

	/*
	 * The two stacked 16MB memories are equivalent to one continuous 32MB.
	 * Write data to the two flash memories on the same bus one at a time,
	 * starting from TEST_ADDRESS. Flash_Write and Flash_Erase functions
	 * will select the lower or upper memory based on the address.
	 */
	for (Page = 0; Page < PAGE_COUNT; Page++) {
		FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
			   TEST_ADDRESS), PAGE_SIZE, WRITE_CMD);
	}

	/*
	 * Read from the two flash memories one after the other using
	 * LQSPI mode. The LQSPI controller takes care of selecting
	 * the lower or upper memory based on address bit 25.
	 */
	XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION);

	XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_QUAD_READ);


	Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
				   MAX_DATA);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
	     Count++, UniqueValue++) {

		if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
			return XST_FAILURE;
		}

	}

	return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver with two Flash devices in Stacked mode.
* This function writes data to the serial Flash in QSPI mode and
* reads data in Linear QSPI mode.
*
* @param        QspiInstancePtr is a pointer to the QSPIPS driver to use.
* @param        QspiDeviceId is the XPAR_<QSPIPS_instance>_DEVICE_ID value
*		from xparameters.h.
*
* @return	XST_SUCCESS if successful, else XST_FAILURE.
*
* @note		None.
*
*****************************************************************************/
The purpose of this function is to illustrate how to use the XQspiPs
device driver with two Flash devices in Stacked mode.
This function writes data to the serial Flash in QSPI mode and
reads data in Linear QSPI mode.
The purpose of this function is to illustrate how to use the XQspiPs device driver with two Flash devices in Stacked mode . This function writes data to the serial Flash in QSPI mode and reads data in Linear QSPI mode .
int DualStackExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
{
	int Status;
	u8 UniqueValue;
	int Count;
	int Page;
	XQspiPs_Config *QspiConfig;
	QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
	if (QspiConfig == NULL) {
		return XST_FAILURE;
	}
	Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
					QspiConfig->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	Status = XQspiPs_SelfTest(QspiInstancePtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	if (QspiConfig->ConnectionMode != XQSPIPS_CONNECTION_MODE_STACKED) {
		xil_printf("QSPI not connected in Stacked Configuration \n");
		return XST_FAILURE;
	}
	XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
	XQspiPs_SetOptions(QspiInstancePtr,  XQSPIPS_FORCE_SSELECT_OPTION |
					    XQSPIPS_MANUAL_START_OPTION |
					    XQSPIPS_HOLD_B_DRIVE_OPTION);
	XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_WRITE);
	FlashReadID();
	FlashQuadEnable(QspiInstancePtr);
	XQspiPs_SetSlaveSelect(QspiInstancePtr);
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
	     Count++, UniqueValue++) {
		WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
	}
	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
	FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
	for (Page = 0; Page < PAGE_COUNT; Page++) {
		FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
			   TEST_ADDRESS), PAGE_SIZE, WRITE_CMD);
	}
	XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION);
	XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_QUAD_READ);
	Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
				   MAX_DATA);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
	     Count++, UniqueValue++) {
		if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
			return XST_FAILURE;
		}
	}
	XQspiPs_SetOptions(QspiInstancePtr,  XQSPIPS_FORCE_SSELECT_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION);
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
	     Count++, UniqueValue++) {
		WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
	}
	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
	FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
	for (Page = 0; Page < PAGE_COUNT; Page++) {
		FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) +
			   TEST_ADDRESS), PAGE_SIZE, WRITE_CMD);
	}
	XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION);
	XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_QUAD_READ);
	Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS,
				   MAX_DATA);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
	     Count++, UniqueValue++) {
		if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
			return XST_FAILURE;
		}
	}
	return XST_SUCCESS;
}
int DualStackExample ( XQspiPs * QspiInstancePtr , u16 QspiDeviceId ) { int Status ; u8 UniqueValue ; int Count ; int Page ; XQspiPs_Config * QspiConfig ; QspiConfig = XQspiPs_LookupConfig ( QspiDeviceId ) ; if ( QspiConfig == NULL ) { return XST_FAILURE ; } Status = XQspiPs_CfgInitialize ( QspiInstancePtr , QspiConfig , QspiConfig -> BaseAddress ) ; if ( Status != XST_SUCCESS ) { return XST_FAILURE ; } Status = XQspiPs_SelfTest ( QspiInstancePtr ) ; if ( Status != XST_SUCCESS ) { return XST_FAILURE ; } if ( QspiConfig -> ConnectionMode != XQSPIPS_CONNECTION_MODE_STACKED ) { xil_printf ( " \n " ) ; return XST_FAILURE ; } XQspiPs_SetClkPrescaler ( QspiInstancePtr , XQSPIPS_CLK_PRESCALE_8 ) ; XQspiPs_SetOptions ( QspiInstancePtr , XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_MANUAL_START_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION ) ; XQspiPs_SetLqspiConfigReg ( QspiInstancePtr , DUAL_STACK_CONFIG_WRITE ) ; FlashReadID ( ) ; FlashQuadEnable ( QspiInstancePtr ) ; XQspiPs_SetSlaveSelect ( QspiInstancePtr ) ; for ( UniqueValue = UNIQUE_VALUE , Count = 0 ; Count < PAGE_SIZE ; Count ++ , UniqueValue ++ ) { WriteBuffer [ DATA_OFFSET + Count ] = ( u8 ) ( UniqueValue + Test ) ; } memset ( ReadBuffer , 0x00 , sizeof ( ReadBuffer ) ) ; FlashErase ( QspiInstancePtr , TEST_ADDRESS , MAX_DATA ) ; for ( Page = 0 ; Page < PAGE_COUNT ; Page ++ ) { FlashWrite ( QspiInstancePtr , ( ( Page * PAGE_SIZE ) + TEST_ADDRESS ) , PAGE_SIZE , WRITE_CMD ) ; } XQspiPs_SetOptions ( QspiInstancePtr , XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION ) ; XQspiPs_SetLqspiConfigReg ( QspiInstancePtr , DUAL_STACK_CONFIG_QUAD_READ ) ; Status = XQspiPs_LqspiRead ( QspiInstancePtr , ReadBuffer , TEST_ADDRESS , MAX_DATA ) ; if ( Status != XST_SUCCESS ) { return XST_FAILURE ; } for ( UniqueValue = UNIQUE_VALUE , Count = 0 ; Count < MAX_DATA ; Count ++ , UniqueValue ++ ) { if ( ReadBuffer [ Count ] != ( u8 ) ( UniqueValue + Test ) ) { return XST_FAILURE ; } } XQspiPs_SetOptions ( QspiInstancePtr , XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION ) ; for ( UniqueValue = UNIQUE_VALUE , Count = 0 ; Count < PAGE_SIZE ; Count ++ , UniqueValue ++ ) { WriteBuffer [ DATA_OFFSET + Count ] = ( u8 ) ( UniqueValue + Test ) ; } memset ( ReadBuffer , 0x00 , sizeof ( ReadBuffer ) ) ; FlashErase ( QspiInstancePtr , TEST_ADDRESS , MAX_DATA ) ; for ( Page = 0 ; Page < PAGE_COUNT ; Page ++ ) { FlashWrite ( QspiInstancePtr , ( ( Page * PAGE_SIZE ) + TEST_ADDRESS ) , PAGE_SIZE , WRITE_CMD ) ; } XQspiPs_SetOptions ( QspiInstancePtr , XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION ) ; XQspiPs_SetLqspiConfigReg ( QspiInstancePtr , DUAL_STACK_CONFIG_QUAD_READ ) ; Status = XQspiPs_LqspiRead ( QspiInstancePtr , ReadBuffer , TEST_ADDRESS , MAX_DATA ) ; if ( Status != XST_SUCCESS ) { return XST_FAILURE ; } for ( UniqueValue = UNIQUE_VALUE , Count = 0 ; Count < MAX_DATA ; Count ++ , UniqueValue ++ ) { if ( ReadBuffer [ Count ] != ( u8 ) ( UniqueValue + Test ) ) { return XST_FAILURE ; } } return XST_SUCCESS ; }
The purpose of this function is to illustrate how to use the XQspiPs
device driver with two Flash devices in Stacked mode.
The purpose of this function is to illustrate how to use the XQspiPs device driver with two Flash devices in Stacked mode .
/* Initialize the QSPI driver so that it's ready to use*/ /* Perform a self-test to check hardware build*/ /* Check if two flash devices are connected in stacked mode*/ /*
	 * Set the QSPI device as a master and enable manual CS, manual start
	 * and flash interface mode options and drive HOLD_B pin high.
	 */ /*
	 * Enable two flash memories, shared bus (NOT separate bus0,
	 * L_PAGE selected by default
	 */ /* Assert the Flash chip select.*/ /*
	 * Initialize the write buffer for a pattern to write to the Flash
	 * and the read buffer to zero so it can be verified after the read, the
	 * test value that is added to the unique value allows the value to be
	 * changed in a debug environment to guarantee
	 */ /* Erase the flash sectors*/ /*
	 * The two stacked 16MB memories are equivalent to one continuous 32MB.
	 * Write data to the two flash memories on the same bus one at a time,
	 * starting from TEST_ADDRESS. Flash_Write and Flash_Erase functions
	 * will select the lower or upper memory based on the address.
	 */ /*
	 * Read from the two flash memories one after the other using
	 * LQSPI mode. The LQSPI controller takes care of selecting
	 * the lower or upper memory based on address bit 25.
	 */ /*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */ /*
	 * Set the QSPI device as a master and enable manual CS, manual start
	 * and flash interface mode options and drive HOLD_B pin high.
	 */ /*
	 * Initialize the write buffer for a pattern to write to the Flash
	 * and the read buffer to zero so it can be verified after the read, the
	 * test value that is added to the unique value allows the value to be
	 * changed in a debug environment to guarantee
	 */ /* Erase the flash sectors*/ /*
	 * The two stacked 16MB memories are equivalent to one continuous 32MB.
	 * Write data to the two flash memories on the same bus one at a time,
	 * starting from TEST_ADDRESS. Flash_Write and Flash_Erase functions
	 * will select the lower or upper memory based on the address.
	 */ /*
	 * Read from the two flash memories one after the other using
	 * LQSPI mode. The LQSPI controller takes care of selecting
	 * the lower or upper memory based on address bit 25.
	 */ /*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */