/** * * This function does a selftest on the QSPI device and XQspiPs driver as an * example. The purpose of this function is to illustrate the usage of the * XQspiPs driver. * * * @param DeviceId is the XPAR_<QSPIPS_instance>_DEVICE_ID value from * xparameters.h * * @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful * * @note None * ****************************************************************************/ int QspiPsSelfTestExample(u16 DeviceId) { int Status; XQspiPs_Config *QspiConfig; /* * Initialize the QSPI device. */ QspiConfig = XQspiPs_LookupConfig(DeviceId); if (NULL == QspiConfig) { return XST_FAILURE; } Status = XQspiPs_CfgInitialize(&Qspi, QspiConfig, QspiConfig->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform a self-test to check hardware build. */ Status = XQspiPs_SelfTest(&Qspi); if (Status != XST_SUCCESS) { return XST_FAILURE; } return XST_SUCCESS; }
/** * * This function initializes the controller for the QSPI interface. * * @param None * * @return None * * @note None * ****************************************************************************/ u32 InitQspi(void) { XQspiPs_Config *QspiConfig; int Status; QspiInstancePtr = &QspiInstance; /* * Set up the base address for access */ FlashReadBaseAddress = XPS_QSPI_LINEAR_BASEADDR; /* * Initialize the QSPI driver so that it's ready to use */ QspiConfig = XQspiPs_LookupConfig(QSPI_DEVICE_ID); if (NULL == QspiConfig) { return XST_FAILURE; } Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig, QspiConfig->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Set Manual Chip select options and drive HOLD_B pin high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Set the prescaler for QSPI clock */ XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); /* * Read Flash ID and extract Manufacture and Size information */ Status = FlashReadID(); if (Status != XST_SUCCESS) { return XST_FAILURE; } if (XPAR_PS7_QSPI_0_QSPI_MODE == SINGLE_FLASH_CONNECTION) { fsbl_printf(DEBUG_INFO,"QSPI is in single flash connection\r\n"); /* * For Flash size <128Mbit controller configured in linear mode */ if (QspiFlashSize <= FLASH_SIZE_16MB) { LinearBootDeviceFlag = 1; /* * Enable linear mode */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Single linear read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, SINGLE_QSPI_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } else { /* * Single flash IO read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, SINGLE_QSPI_IO_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } } if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { fsbl_printf(DEBUG_INFO,"QSPI is in Dual Parallel connection\r\n"); /* * For Single Flash size <128Mbit controller configured in linear mode */ if (QspiFlashSize <= FLASH_SIZE_16MB) { /* * Setting linear access flag */ LinearBootDeviceFlag = 1; /* * Enable linear mode */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Dual linear read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } else { /* * Dual flash IO read */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_IO_CONFIG_QUAD_READ); /* * Enable the controller */ XQspiPs_Enable(QspiInstancePtr); } /* * Total flash size is two time of single flash size */ QspiFlashSize = 2 * QspiFlashSize; } /* * It is expected to same flash size for both chip selection */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_STACK_CONNECTION) { fsbl_printf(DEBUG_INFO,"QSPI is in Dual Stack connection\r\n"); QspiFlashSize = 2 * QspiFlashSize; /* * Enable two flash memories on separate buses */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_READ); } return XST_SUCCESS; }
/***************************************************************************** * * The purpose of this function is to illustrate how to use the XQspiPs * device driver in single, parallel and stacked modes using * flash devices greater than 128Mb. * This function reads and writes data in I/O mode. * * @param None. * * @return XST_SUCCESS if successful, else XST_FAILURE. * * @note None. * *****************************************************************************/ int QspiG128FlashExample(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 (NULL == QspiConfig) { 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; } /* * Set the pre-scaler for QSPI clock */ XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); /* * Set Manual Start and Manual Chip select options and drive the * HOLD_B high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_MANUAL_START_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); if(QspiConfig->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) { /* * Enable two flash memories, Shared bus (NOT separate bus), * L_PAGE selected by default */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_WRITE); } if(QspiConfig->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) { /* * Enable two flash memories on separate buses */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_WRITE); } /* * Assert the Flash chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); /* * Read flash ID and obtain all flash related information * It is important to call the read id function before * performing proceeding to any operation, including * preparing the WriteBuffer */ FlashReadID(QspiInstancePtr, WriteBuffer, ReadBuffer); /* * Initialize MaxData according to page size. */ MaxData = PAGE_COUNT * (Flash_Config_Table[FCTIndex].PageSize); /* * 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 < Flash_Config_Table[FCTIndex].PageSize; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test); } memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * Erase the flash. */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MaxData, WriteBuffer); /* * Write the data in the write buffer to the serial Flash a page at a * time, starting from TEST_ADDRESS */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, (Page * Flash_Config_Table[FCTIndex].PageSize) + TEST_ADDRESS, Flash_Config_Table[FCTIndex].PageSize, WRITE_CMD, WriteBuffer); } /* * I/O Read - for any flash size */ FlashRead(QspiInstancePtr, TEST_ADDRESS, MaxData, QUAD_READ_CMD, WriteBuffer, ReadBuffer); /* * 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 < MaxData; Count++, UniqueValue++) { if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * 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 < Flash_Config_Table[FCTIndex].PageSize; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test); } memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * Set Auto Start and Manual Chip select options and drive the * HOLD_B high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Erase the flash. */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MaxData, WriteBuffer); /* * Write the data in the write buffer to the serial Flash a page at a * time, starting from TEST_ADDRESS */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, (Page * Flash_Config_Table[FCTIndex].PageSize) + TEST_ADDRESS, Flash_Config_Table[FCTIndex].PageSize, WRITE_CMD, WriteBuffer); } /* * I/O Read - for any flash size */ FlashRead(QspiInstancePtr, TEST_ADDRESS, MaxData, QUAD_READ_CMD, WriteBuffer, ReadBuffer); /* * 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 < MaxData; 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 in Linear mode. This function writes data to the serial * FLASH in QSPI mode and reads data in Linear QSPI mode. * * @param None. * * @return XST_SUCCESS if successful, else XST_FAILURE. * * @note None. * *****************************************************************************/ int LinearQspiFlashExample(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 (NULL == QspiConfig) { 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; } /* * 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)); /* * Set the prescaler for QSPI clock */ XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); /* * Set Manual Start and Manual Chip select options and drive the * HOLD_B high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_MANUAL_START_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); FlashReadID(); /* * Erase the flash. */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); /* * Write the data in the write buffer to the serial FLASH a page at a * time, starting from TEST_ADDRESS */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE, WRITE_CMD); } /* * Read from the flash in LQSPI mode. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); 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; } } /* * 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)); /* * Set Auto Start and Manual Chip select options and drive the * HOLD_B high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Erase the flash. */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); /* * Write the data in the write buffer to the serial FLASH a page at a * time, starting from TEST_ADDRESS */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE, WRITE_CMD); } /* * Read from the flash in LQSPI mode. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); 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 in Linear mode. This function writes data to the serial * FLASH in QSPI mode and reads data in Linear QSPI mode. * * @param None. * * @return XST_SUCCESS if successful, else XST_FAILURE. * * @note None. * *****************************************************************************/ int LinearQspiFlashExample(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 (NULL == QspiConfig) { 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; } /* * Enable two flash memories on seperate buses */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_WRITE); /* * 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); XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); /* * 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)); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); /* * Erase the flash sectors */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); /* * Write data to the two flash memories on seperate buses, starting from * TEST_ADDRESS. This is same as writing to a single flash memory. The * LQSPI controller takes care of splitting the data words and writing * them to the two flash memories. The user needs to take care of the * address translation */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) + TEST_ADDRESS) / 2, PAGE_SIZE, WRITE_CMD); } /* * Read from the two flash memories on seperate buses in LQSPI mode. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_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] != WriteBuffer[DATA_OFFSET + (Count % PAGE_SIZE)]) { 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); /* * Write data to the two flash memories on seperate buses, starting from * TEST_ADDRESS. This is same as writing to a single flash memory. The * LQSPI controller takes care of splitting the data words and writing * them to the two flash memories. The user needs to take care of the * address translation */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) + TEST_ADDRESS) / 2, PAGE_SIZE, WRITE_CMD); } /* * Read from the two flash memories on seperate buses in LQSPI mode. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_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] != WriteBuffer[DATA_OFFSET + (Count % PAGE_SIZE)]) { return XST_FAILURE; } } return XST_SUCCESS; }
/***************************************************************************** * * The purpose of this function is to illustrate how to use the XQspiPs * device driver in interrupt mode. This function writes and reads data * from a serial FLASH. * * @param None. * * @return XST_SUCCESS if successful else XST_FAILURE. * * @note * * This function calls other functions which contain loops that may be infinite * if interrupts are not working such that it may not return. If the device * slave select is not correct and the device is not responding on bus it will * read a status of 0xFF for the status register as the bus is pulled up. * *****************************************************************************/ int QspiFlashIntrExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr, u16 QspiDeviceId, u16 QspiIntrId) { int Status; u8 *BufferPtr; 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 (NULL == QspiConfig) { 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; } /* * Connect the Qspi device to the interrupt subsystem such that * interrupts can occur. This function is application specific */ Status = QspiSetupIntrSystem(IntcInstancePtr, QspiInstancePtr, QspiIntrId); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup the handler for the QSPI that will be called from the * interrupt context when an QSPI status occurs, specify a pointer to * the QSPI driver instance as the callback reference so the handler is * able to access the instance data */ XQspiPs_SetStatusHandler(QspiInstancePtr, QspiInstancePtr, (XQspiPs_StatusHandler) QspiHandler); /* * Set Manual Start and Manual Chip select options and drive the * HOLD_B high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_MANUAL_START_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Set the operating clock frequency using the clock divider */ XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); /* * 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)); FlashReadID(); /* * Erase the flash. */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); /* * Write the data in the write buffer to the serial FLASH a page at a * time, starting from TEST_ADDRESS */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE, WRITE_CMD); } /* * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read * command. */ FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read * command */ memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, FAST_READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * Read the contents of the FLASH from TEST_ADDRESS, using Dual Read * command */ memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, DUAL_READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * Read the contents of the FLASH from TEST_ADDRESS, using Quad Read * command */ memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, QUAD_READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * Set Auto Start and Manual Chip select options and drive the * HOLD_B 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. */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); /* * Write the data in the write buffer to the serial FLASH a page at a * time, starting from TEST_ADDRESS */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE, WRITE_CMD); } /* * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read * command. */ FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read * command */ memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, FAST_READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * Read the contents of the FLASH from TEST_ADDRESS, using Dual Read * command */ memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, DUAL_READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } /* * Read the contents of the FLASH from TEST_ADDRESS, using Quad Read * command */ memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, QUAD_READ_CMD); /* * 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 */ BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE]; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { return XST_FAILURE; } } QspiDisableIntrSystem(IntcInstancePtr, QspiIntrId); return XST_SUCCESS; }
/** * The purpose of this function is to illustrate how to use the XQspiPs * device driver in interrupt mode. This function writes and reads data * from a serial FLASH. * * @return XST_SUCCESS if successful else XST_FAILURE. * * @note * * This function calls other functions which contain loops that may be infinite * if interrupts are not working such that it may not return. If the device * slave select is not correct and the device is not responding on bus it will * read a status of 0xFF for the status register as the bus is pulled up. * *****************************************************************************/ int QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr, u16 QspiDeviceId, u16 QspiIntrId) { u8 *BufferPtr; u8 UniqueValue; int Count; int Page; int Status; u32 Options; /* * Lookup the device configuration in the temporary CROM table. Use this * configuration info down below when initializing this component. */ ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId); if (ConfigPtr == NULL) { return XST_DEVICE_NOT_FOUND; } Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr, ConfigPtr->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Set the QSPI options */ Options = XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_MANUAL_START_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION; XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr, Options, XISF_SPI_PRESCALER); if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) { /* * Enable two flash memories, Shared bus * (NOT separate bus), L_PAGE selected by default */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_STACK_CONFIG_WRITE); } if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) { /* * Enable two flash memories on separate buses */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_WRITE); } /* Initialize the XILISF Library */ XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT, IsfWriteBuffer); /* * 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[Count] = (u8)(UniqueValue + Test_Polled); } memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA); if(Status != XST_SUCCESS){ return XST_FAILURE; } /* * Write the data in the write buffer to the serial FLASH a page at a * time, starting from TEST_ADDRESS */ for (Page = 0; Page < PAGE_COUNT; Page++) { Status = FlashWrite(&Isf, (Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE, XISF_QUAD_IP_PAGE_WRITE); if(Status != XST_SUCCESS){ return XST_FAILURE; } } /****************************************************** **********************NORMAL READ********************* ******************************************************/ /* * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read * command */ Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ); 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 */ BufferPtr = ReadBuffer; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { return XST_FAILURE; } } /****************************************************** **********************FAST READ*********************** ******************************************************/ /* * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read * command */ Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_FAST_READ); 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 */ BufferPtr = ReadBuffer; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { return XST_FAILURE; } } /****************************************************** ******************DUAL OP FAST READ******************* ******************************************************/ /* * Read the contents of the FLASH from TEST_ADDRESS, using DUAL OP * Fast Read command */ Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_DUAL_OP_FAST_READ); 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 */ BufferPtr = ReadBuffer; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { return XST_FAILURE; } } /****************************************************** ******************QUAD IO FAST READ******************* ******************************************************/ /* * Read the contents of the FLASH from TEST_ADDRESS, using QUAD IO * Fast Read command */ Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_QUAD_OP_FAST_READ); 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 */ BufferPtr = ReadBuffer; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { return XST_FAILURE; } } return XST_SUCCESS; }