/** * * 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 XSpiPs * device driver in polled mode. This function writes and reads data * from a serial flash. * * @param SpiPtr is a pointer to the SPI driver instance to use. * * @param SpiDeviceId is the Instance Id of SPI in the system. * * @return * - XST_SUCCESS if successful * - XST_FAILURE if not successful * * @note * * 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 SpiPsFlashPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId) { int Status; u8 *BufferPtr; u8 UniqueValue; u32 Count; XSpiPs_Config *SpiConfig; /* * Initialize the SPI driver so that it's ready to use */ SpiConfig = XSpiPs_LookupConfig(SpiDeviceId); if (NULL == SpiConfig) { return XST_FAILURE; } Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig, SpiConfig->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform a self-test to check hardware build */ Status = XSpiPs_SelfTest(SpiInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Set the SPI device as a master with manual start and manual * chip select mode options */ XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MANUAL_START_OPTION | \ XSPIPS_MASTER_OPTION | XSPIPS_FORCE_SSELECT_OPTION); /* * Set the SPI device pre-scalar to divide by 8 */ XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_8); memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * 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 < MAX_DATA; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue); } /* * Set the flash chip select */ XSpiPs_SetSlaveSelect(SpiInstancePtr, FLASH_SPI_SELECT); /* * Read the flash Id */ Status = FlashReadID(); if (Status != XST_SUCCESS) { xil_printf("SPI Flash Polled Example Read ID Failed\r\n"); return XST_FAILURE; } /* * Erase the flash */ FlashErase(SpiInstancePtr); TestAddress = 0x0; /* * Write the data in the write buffer to TestAddress in serial flash */ FlashWrite(SpiInstancePtr, TestAddress, MAX_DATA, WRITE_CMD); /* * Read the contents of the flash from TestAddress of size MAX_DATA * using Normal Read command */ FlashRead(SpiInstancePtr, TestAddress, 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)) { return XST_FAILURE; } } memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * 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 < MAX_DATA; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue); } /* * Set the SPI device as a master with auto start and manual * chip select mode options */ XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION | \ XSPIPS_FORCE_SSELECT_OPTION); /* * Erase the flash */ FlashErase(SpiInstancePtr); TestAddress = 0x0; /* * Write the data in the write buffer to TestAddress in serial flash */ FlashWrite(SpiInstancePtr, TestAddress, MAX_DATA, WRITE_CMD); /* * Read the contents of the flash from TestAddress of size MAX_DATA * using Normal Read command */ FlashRead(SpiInstancePtr, TestAddress, 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)) { 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 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 XSpiPs * device driver in interrupt mode. This function writes and reads data * from a serial flash. * * @param IntcInstancePtr is a pointer to Interrupt Controller instance. * * @param SpiInstancePtr is a pointer to the SPI driver instance to use. * * @param SpiDeviceId is the Instance Id of SPI in the system. * * @param SpiIntrId is the Interrupt Id for SPI in the system. * * @param None. * * @return * - XST_SUCCESS if successful * - XST_FAILURE if not successful * * @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 SpiPsFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr, u16 SpiDeviceId, u16 SpiIntrId) { int Status; u8 *BufferPtr; u8 UniqueValue; u32 Count; u32 MaxSize = MAX_DATA; u32 ChipSelect = FLASH_SPI_SELECT_1; XSpiPs_Config *SpiConfig; if (XGetPlatform_Info() == XPLAT_ZYNQ_ULTRA_MP) { MaxSize = 1024 * 10; ChipSelect = FLASH_SPI_SELECT_0; /* Device is on CS 0 */ SpiIntrId = XPAR_XSPIPS_0_INTR; } /* * Initialize the SPI driver so that it's ready to use */ SpiConfig = XSpiPs_LookupConfig(SpiDeviceId); if (NULL == SpiConfig) { return XST_FAILURE; } Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig, SpiConfig->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform a self-test to check hardware build */ Status = XSpiPs_SelfTest(SpiInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Connect the Spi device to the interrupt subsystem such that * interrupts can occur. This function is application specific */ Status = SpiPsSetupIntrSystem(IntcInstancePtr, SpiInstancePtr, SpiIntrId); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup the handler for the SPI that will be called from the * interrupt context when an SPI status occurs, specify a pointer to * the SPI driver instance as the callback reference so the handler is * able to access the instance data */ XSpiPs_SetStatusHandler(SpiInstancePtr, SpiInstancePtr, (XSpiPs_StatusHandler) SpiPsHandler); /* * Set the SPI device as a master with manual start and manual * chip select mode options */ XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MANUAL_START_OPTION | \ XSPIPS_MASTER_OPTION | XSPIPS_FORCE_SSELECT_OPTION); /* * Set the SPI device pre-scalar to divide by 8 */ XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_8); memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * 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 < MaxSize; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue); } /* * Assert the flash chip select */ XSpiPs_SetSlaveSelect(SpiInstancePtr, ChipSelect); /* * Read the flash ID */ Status = FlashReadID(SpiInstancePtr); if (Status != XST_SUCCESS) { xil_printf("SPI FLASH Interrupt Example Read ID Failed\r\n"); return XST_FAILURE; } /* * Erase the flash */ FlashErase(SpiInstancePtr); /* * Write the data in the write buffer to TestAddress in serial flash */ FlashWrite(SpiInstancePtr, TestAddress, MaxSize, WRITE_CMD); /* * Read the contents of the flash from TestAddress of size MAX_DATA * using Normal Read command */ FlashRead(SpiInstancePtr, TestAddress, MaxSize, 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 < MaxSize; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue)) { return XST_FAILURE; } } /* * Set the SPI device as a master with auto start and manual * chip select mode options */ XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION | \ XSPIPS_FORCE_SSELECT_OPTION); memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * 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 < MaxSize; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue); } /* * Erase the flash */ FlashErase(SpiInstancePtr); /* * Write the data in the write buffer to TestAddress in serial flash */ FlashWrite(SpiInstancePtr, TestAddress, MaxSize, WRITE_CMD); /* * Read the contents of the flash from TestAddress of size MAX_DATA * using Normal Read command */ FlashRead(SpiInstancePtr, TestAddress, MaxSize, 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 < MaxSize; Count++, UniqueValue++) { if (BufferPtr[Count] != (u8)(UniqueValue)) { return XST_FAILURE; } } SpiPsDisableIntrSystem(IntcInstancePtr, SpiIntrId); return XST_SUCCESS; }
/** * This function is used to initialize the qspi controller and driver * * @param None * * @return None * *****************************************************************************/ u32 XFsbl_Qspi32Init(u32 DeviceFlags) { XQspiPsu_Config *QspiConfig; u32 Status = XFSBL_SUCCESS; QspiPsuInstancePtr = &QspiPsuInstance; /** * Initialize the QSPI driver so that it's ready to use */ QspiConfig = XQspiPsu_LookupConfig(QSPI_DEVICE_ID); if (NULL == QspiConfig) { Status = XFSBL_ERROR_QSPI_INIT; XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_INIT\r\n"); goto END; } Status = XQspiPsu_CfgInitialize(QspiPsuInstancePtr, QspiConfig, QspiConfig->BaseAddress); if (Status != XST_SUCCESS) { Status = XFSBL_ERROR_QSPI_INIT; XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_INIT\r\n"); goto END; } /* * Set Manual Start */ XQspiPsu_SetOptions(QspiPsuInstancePtr, XQSPIPSU_MANUAL_START_OPTION); /* * Set the pre-scaler for QSPI clock */ XQspiPsu_SetClkPrescaler(QspiPsuInstancePtr, XQSPIPSU_CLK_PRESCALE_8); XQspiPsu_SelectFlash(QspiPsuInstancePtr, XQSPIPSU_SELECT_FLASH_CS_LOWER, XQSPIPSU_SELECT_FLASH_BUS_LOWER); /* * Configure the qspi in linear mode if running in XIP * TBD */ switch (XPAR_PSU_QSPI_0_QSPI_MODE) { case XQSPIPSU_CONNECTION_MODE_SINGLE: { XFsbl_Printf(DEBUG_INFO,"QSPI is in single flash connection\r\n"); } break; case XQSPIPSU_CONNECTION_MODE_PARALLEL: { XFsbl_Printf(DEBUG_INFO,"QSPI is in Dual Parallel connection\r\n"); } break; case XQSPIPSU_CONNECTION_MODE_STACKED: { XFsbl_Printf(DEBUG_INFO,"QSPI is in Dual Stack connection\r\n"); }break; default: { Status = XFSBL_ERROR_INVALID_QSPI_CONNECTION; XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_INVALID_QSPI_CONNECTION\r\n"); goto END; }break; } /** * add code for 1x, 2x and 4x * */ ReadCommand = QUAD_READ_CMD_32BIT; /** * Read Flash ID and extract Manufacture and Size information */ Status = FlashReadID(QspiPsuInstancePtr); if (Status != XFSBL_SUCCESS) { goto END; } /** * add code: For a Stacked connection, read second Flash ID */ if ((XPAR_PSU_QSPI_0_QSPI_MODE == XQSPIPSU_CONNECTION_MODE_PARALLEL) || (XPAR_PSU_QSPI_0_QSPI_MODE == XQSPIPSU_CONNECTION_MODE_STACKED) ) { QspiFlashSize = 2 * QspiFlashSize; } END: return Status; }
void main(void) { // XBYTE[0xB091]=0x01; // 1.8v/3.3v regulator turn on XBYTE[0xB092]=0x78; // 3.2V & 2.0V // XBYTE[0xB093]=0x00; // LVR=2.4V // DSP initial XBYTE[0xB010]&=0xFE; // Disable DSP clock, Jimi 080729 for pop noise as 1st time play XBYTE[0xB002]&=0xFE; // Release DSP Reset, Jimi 080729 for pop noise as 1st time play XBYTE[0xB08a]|=0x08; //(JC)MCU:audio DAC on XBYTE[0xB08a]|=0x10; //(JC)MCU:Headphone driver on XBYTE[0xB08a]|=0x20; //(JC)MCU:Headphone driver DD comm-mode bias o/p XBYTE[0xB0ED]|=0x02; //(Jimi 091027)Audio DA zero cross reset bypass on XBYTE[0xB0C1]=0xB0; //(Jimi 091027)Pre-mux , post-mux and internal XCK select XBYTE[0xB0C4]=2; //(Jimi 091027)LCH speaker volume(i.e LCH OP Gain) XBYTE[0xB0C5]=2; //(Jimi 091027)RCH speaker volume(i.e RCH OP Gain) //SAR ADC init XBYTE[0xB05E] = 0; // disable SAR FS clock XBYTE[0xB05F] = 0x5F; // SAR clock = 12MHz/16/6 = 125kHz = 8us //-------------------------------------------- // gbt_Force_USB_FullSpeed =FALSE; gbt_USB_Detected = 0; gc_CardDetect = 0x00 ; gc_CardExist = 0x00 ; // bit 0 : Nand Flash bit 1: SD_Card gc_CardType = 0x01 ; // default Flash Interface gc_CardChangeStage =0x00; // bit 0 : Nand bit 1 : SD_Card gw_FileSkipNumber=0; gb_TriggerFileSkip=0; gb_FindFile=0; gbt_Support_Dummy_Capacity =0; // default disable dummy capacity function gc_bCBWLUN=0; gbt_enableCDROM =0; //09/04/24,joyce gc_CDROM_Size=0 ; init_system(); USB_PlugDetect(); // Detect USB plug //----------------------------------------------// Initial Flash module Init_Flash_Reg(); Init_Flash_Variable(); //-------------- Need search Bank,Dsp ,hzk block info ,first---------// FDBP.cFDev = 0; XBYTE[0xB40F] = FDBP.cFDev; FlashReadID(); Flash_State_Initial(); Search_BankCode_Block(); InitFlash(); Timer0_init(); XBYTE[0xB09F]|=0x06;//(JC)Vref Fast setup mode 'n Internal reference voltage power control gc_Vrefinit_Timer=60; XBYTE[0xB421]=0x13; // dbprintf("tftinit\n"); TFT_init(); #ifdef CAR_48 XBYTE[0xB102]|=0x3C; #else XBYTE[0xB102] |= 0x01; #endif // dbprintf("tftinit end\n"); TFT_PowerOnlogo(); if(gbt_USB_Detected) { USB_Task(); } gb_Host_Exist=1; gb_SD_Exist=1; if(!Host_DetectDevice()) { if(!Host_Initial()) { gc_CurrentCard = CURRENT_MEDIA_HOST; gb_FindFlag = 0; } else { gc_CurrentCard=0; } } else { if(SD_Card_Detect()) { if(SD_Identification_Flow()) { gc_CardExist |=0x02; gc_CurrentCard=2; } else { gc_CurrentCard=0; gc_CardExist &=0xFD; gb_FindFlag = 0; } } else { gb_SD_Exist=0; gc_CurrentCard = 0; } } XBYTE[0xB400] =0x01; XBYTE[0xB010]&=0xFE; // Disable DSP clock, Jimi 080729 for pop noise as 1st time play XBYTE[0xB002]&=0xFE; // Release DSP Reset, Jimi 080729 for pop noise as 1st time play XBYTE[0xB08a]|=0x08;//(JC)MCU:audio DAC on XBYTE[0xB08a]|=0x10;//(JC)MCU:Headphone driver on XBYTE[0xB08a]|=0x20;//(JC)MCU:Headphone driver DD comm-mode bias o/p //SAR ADC init XBYTE[0xB05E] = 0; // disable SAR FS clock XBYTE[0xB05F] = 0x5f; // SAR clock = 12MHz/16/6 = 125kHz = 8us Get_LogData_PageIndex(); //chiayen0808 USER_LogFile_ReadWrite(0);//use reserveblock for log if((gw_FM_frequency<875) || (gw_FM_frequency>1080)) { gw_FM_frequency=875; } FM_initial(); FM_drive(); gc_SetNumber = gw_PagesPerBlock >> 2; //1set=4pages for dir management, Ching 080816 //20090107 chiayen add gc_SetIndex = 0; //Ching 080816 //20090107 chiayen add USER_GetUISetIndex(); //for DIR table index //20090107 chiayen add gb_FindFlag = 0; if (DOS_Initialize()) //20090803 chiayen modify { gdw_HOSTStartSectorRead=0xFFFFFFF0; if(gc_CurrentCard==CURRENT_MEDIA_HOST) { if(SD_Card_Detect()) { gb_SD_Exist=1; if(SD_Identification_Flow()) { gc_CardExist |=0x02; gc_CurrentCard=2; } else { DEVICE_REG[0x00]= 0x01; gc_CurrentCard=0; gc_CardExist &=0xFD; gb_FindFlag = 0; } } else { DEVICE_REG[0x00]= 0x01; gb_SD_Exist=0; gc_CurrentCard = 0; } } else { DEVICE_REG[0x00]= 0x01; //20090730 chiayen add gc_CurrentCard=0; gc_CardExist &=0xFD; gb_FindFlag = 0; InitFlash(); } DOS_Initialize(); } gc_CurrentCard_backup=gc_CurrentCard; //20090803 chiayen move here gs_File_FCB[0].dw_FDB_StartCluster = gdw_DOS_RootDirClus; DOS_Search_File(C_File_All|C_Cnt_FileNo, C_MusicFileType, C_CmpExtName|C_Next);//(JC)count music file no. in root ir_init(); EA = 1; gc_Task_Current=C_Task_Play; gc_Task_Next=C_Task_Play; gc_PhaseInx=0; gw_init_needed=0xffff; Detect_USB(); Polling_TaskEvents(); if(gc_Task_Current!=gc_Task_Next) { gc_Task_Current=gc_Task_Next; } while(1) { switch(gc_Task_Current) { case C_Task_Play: Play_Task(); break; case C_Task_USB: USB_Task(); break; case C_Task_Dir: //20090107 chiayen add Dir_Task(); break; case C_Task_Jpeg: //20090107 chiayen add Jpeg_Task(); break; case C_Task_Mjpeg: //20090107 chiayen add Mjpeg_Task(); break; case C_Task_PlayMenu: //20090107 chiayen add // PlayMenuProcess(); break; case C_Task_PlayMenu_IR: //20090107 chiayen add // PlayMenuProcess_IR(); break; case C_Task_Setting: //20090107 chiayen add SetupMenuProcess(); break; case C_Task_Menu: MainMenuProcess(); break; case C_Task_PowerOff: PowerOffProcess(); break; } } }