/****************************************************************************** * * This function reads serial flash ID connected to the SPI interface. * * @param None. * * @return * - XST_SUCCESS if successful * - XST_FAILURE if not successful * * @note None. * ******************************************************************************/ static int FlashReadID(XSpiPs *SpiInstance) { u8 Index; u8 ByteCount = 4; u8 SendBuffer[8]; u8 RecvBuffer[8]; SendBuffer[0] = READ_ID; SendBuffer[1] = 0; SendBuffer[2] = 0; SendBuffer[3] = 0; for(Index=0; Index < ByteCount; Index++) { SendBuffer[4 + Index] = 0x00; } TransferInProgress = TRUE; XSpiPs_Transfer(SpiInstance, SendBuffer, RecvBuffer, (4 + ByteCount)); while (TransferInProgress); for(Index=0; Index < ByteCount; Index++) { xil_printf("ID : %0x\r\n", RecvBuffer[4 + Index]); } return XST_SUCCESS; }
/****************************************************************************** * * This function reads from the serial flash connected to the * SPI interface. * * @param SpiPtr is a pointer to the SPI driver component to use. * @param Address contains the address to read data from in the flash. * @param ByteCount contains the number of bytes to read. * @param Command is the command used to read data from the flash. SPI * device supports one of the Read, Fast Read, Dual Read and Fast * Read commands to read data from the flash. * * @return None. * * @note None. * ******************************************************************************/ static void FlashRead(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command) { /* * Setup the write command with the specified address and data for the * flash */ WriteBuffer[COMMAND_OFFSET] = Command; WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16); WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8); WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF); /* * Send the read command to the flash to read the specified number * of bytes from the flash, send the read command and address and * receive the specified number of bytes of data in the data buffer */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, WriteBuffer, ReadBuffer, ByteCount + OVERHEAD_SIZE); /* * Wait for the transfer on the SPI bus to be complete before * proceeding */ while (TransferInProgress); }
/****************************************************************************** * * This function reads from the serial EEPROM connected to the SPI interface. * * @param SpiPtr is a pointer to the SPI driver instance to use. * @param Address contains the address to read data from in the EEPROM. * @param ByteCount contains the number of bytes to read. * @param Buffer is a buffer to read the data into. * * @return None. * * @note None. * ******************************************************************************/ void EepromRead(XSpiPs *SpiPtr, u16 Address, int ByteCount, EepromBuffer Buffer) { /* * Setup the write command with the specified address and data for the * EEPROM */ Buffer[COMMAND_OFFSET] = READ_CMD; Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8); Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF); /* * Send the read command to the EEPROM to read the specified number * of bytes from the EEPROM, send the read command and address and * receive the specified number of bytes of data in the data buffer */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, Buffer, &Buffer[DATA_OFFSET], ByteCount + OVERHEAD_SIZE); /* * Wait for the transfer on the SPI bus to be complete before proceeding */ while (TransferInProgress); }
/****************************************************************************** * * * This function erases the sectors in the serial flash connected to the * SPI interface. * * @param SpiPtr is a pointer to the SPI driver component to use. * * @return None. * * @note None. * ******************************************************************************/ static void FlashErase(XSpiPs *SpiPtr) { u8 WriteEnableCmd = { WRITE_ENABLE_CMD }; u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */ /* must send 2 bytes */ u8 WriteStatusCmd[] = { WRITE_STATUS_CMD, 0x0 }; u8 FlashStatus[2]; /* * Send the write enable command to the flash so that it can be * written to, this needs to be sent as a seperate transfer * before the erase */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); /* * Wait for the transfer on the SPI bus to be complete before * proceeding */ while (TransferInProgress); /* * Wait for write enable command to the flash to be completed */ while (1) { /* * Poll the status register of the device to determine * when it completes, by sending a read status command * and receiving the status byte */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus, sizeof(ReadStatusCmd)); /* * Wait for the transfer on the SPI bus to be complete * before proceeding */ while (TransferInProgress); /* * If the status indicates the write is done, then stop * waiting; if a value of 0xFF in the status byte is * read from the device and this loop never exits, the * device slave select is possibly incorrect such that * the device status is not being read */ if ((FlashStatus[1] & 0x02) == 0x02) { break; } } /* * Clear write protect bits using write status command to the flash * this needs to be sent as a seperate transfer before the erase */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, WriteStatusCmd, NULL, sizeof(WriteStatusCmd)); /* * Wait for the transfer on the SPI bus to be complete before * proceeding */ while (TransferInProgress); /* * Check for write status command to the flash to be completed */ while (1) { /* * Poll the status register of the device to determine * when it completes, by sending a read status command * and receiving the status byte */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus, sizeof(ReadStatusCmd)); /* * Wait for the transfer on the SPI bus to be complete * before proceeding */ while (TransferInProgress); /* * If the status indicates the write is done, then stop * waiting; if a value of 0xFF in the status byte is * read from the device and this loop never exits, the * device slave select is possibly incorrect such that * the device status is not being read */ if ((FlashStatus[1] & 0x1C) == 0x0) { break; } } /* * Send the write enable command to the flash so that it can be * written to, this needs to be sent as a seperate transfer * before the erase */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); /* * Wait for the transfer on the SPI bus to be complete before * proceeding */ while (TransferInProgress); /* * Wait for write enable command to the flash to be completed */ while (1) { /* * Poll the status register of the device to determine * when it completes, by sending a read status command * and receiving the status byte */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus, sizeof(ReadStatusCmd)); /* * Wait for the transfer on the SPI bus to be complete * before proceeding */ while (TransferInProgress); /* * If the status indicates the write is done, then stop * waiting; if a value of 0xFF in the status byte is * read from the device and this loop never exits, the * device slave select is possibly incorrect such that * the device status is not being read */ if ((FlashStatus[1] & 0x02) == 0x02) { break; } } /* * Setup the bulk erase or chip-erase command */ WriteBuffer[COMMAND_OFFSET] = CHIP_ERASE_CMD; /* * Send the bulk erase command; no receive buffer is specified * since there is nothing to receive */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, WriteBuffer, NULL, 1); while (TransferInProgress); /* * Wait for the erase command to the flash to be completed */ while (1) { /* * Poll the status register of the device to determine * when it completes, by sending a read status command * and receiving the status byte */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus, sizeof(ReadStatusCmd)); /* * Wait for the transfer on the SPI bus to be complete * before proceeding */ while (TransferInProgress); /* * If the status indicates the write is done, then stop * waiting; if a value of 0xFF in the status byte is * read from the device and this loop never exits, the * device slave select is possibly incorrect such that * the device status is not being read */ if ((FlashStatus[1] & 0x01) == 0) { break; } } }
/****************************************************************************** * * * This function writes to the serial flash connected to the SPI interface. * The flash contains a 256 byte write buffer which can be filled and then a * write is automatically performed by the device. All the data put into the * buffer must be in the same page of the device with page boundaries being on * 256 byte boundaries. * * @param SpiPtr is a pointer to the SPI driver component to use. * @param Address contains the address to write data to in the flash. * @param ByteCount contains the number of bytes to write. * @param Command is the command used to write data to the flash. SPI * device supports only Page Program command to write data to the * flash. * * @return None. * * @note None. * ******************************************************************************/ static void FlashWrite(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command) { u8 WriteEnableCmd = { WRITE_ENABLE_CMD }; u8 WriteDisableCmd = { WRITE_DISABLE_CMD }; u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */ u8 FlashStatus[2]; u32 Temp = 0; u32 TempAddress = Address; u8 TempBuffer[5]; if (Command == WRITE_CMD) { for (Temp = 0; Temp < ByteCount ; Temp++, TempAddress++) { /* * Send the write enable command to the flash so * that it can be written to, this needs to be sent * as a seperate transfer before the write */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); /* * Wait for the transfer on the SPI bus to be complete before * proceeding */ while (TransferInProgress); /* * Setup the write command with the specified address * and data for the flash */ TempBuffer[COMMAND_OFFSET] = Command; TempBuffer[ADDRESS_1_OFFSET] = (u8)((TempAddress & 0xFF0000) >> 16); TempBuffer[ADDRESS_2_OFFSET] = (u8)((TempAddress & 0xFF00) >> 8); TempBuffer[ADDRESS_3_OFFSET] = (u8)(TempAddress & 0xFF); TempBuffer[DATA_OFFSET] = WriteBuffer[DATA_OFFSET + Temp]; /* * Send the write command, address, and data to the * flash to be written, no receive buffer is specified * since there is nothing to receive */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, TempBuffer, NULL, 5); while (TransferInProgress); /* * Wait for the write command to the flash to be , * completed it takes some time for the data to be * written */ while (1) { /* * Poll the status register of the flash to * determine when it completes, by sending * a read status command and receiving the * status byte */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus, sizeof(ReadStatusCmd)); /* * Wait for the transfer on the SPI bus * to be complete before proceeding */ while (TransferInProgress); /* * If the status indicates the write is done, * then stop waiting, if a value of 0xFF in * the status byte is read from the device * and this loop never exits, the device slave * select is possibly incorrect such that the * device status is not being read */ if ((FlashStatus[1] & 0x01) == 0) { break; } } TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, &WriteDisableCmd, NULL, sizeof(WriteDisableCmd)); /* * Wait for the transfer on the SPI bus to be complete * before proceeding */ while (TransferInProgress); } } }
/****************************************************************************** * * * This function writes to the serial EEPROM connected to the SPI interface. * This function is not designed to be a driver to handle all * the conditions of the EEPROM device. The EEPROM contains a 32 byte write * buffer which can be filled and then a write is automatically performed by * the device. All the data put into the buffer must be in the same page of * the device with page boundaries being on 32 byte boundaries. * * @param SpiPtr is a pointer to the SPI driver instance to use. * @param Address contains the address to write data to in the EEPROM. * @param ByteCount contains the number of bytes to write. * @param Buffer is a buffer of data to write from. * * @return None. * * @note None. * ******************************************************************************/ void EepromWrite(XSpiPs *SpiPtr, u16 Address, u8 ByteCount, EepromBuffer Buffer) { u8 WriteEnableCmd = { WRITE_ENABLE_CMD }; u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */ u8 EepromStatus[2]; int DelayCount = 0; /* * Send the write enable command to the SEEPOM so that it can be * written to, this needs to be sent as a seperate transfer before * the write */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd)); /* * Wait for the transfer on the SPI bus to be complete before proceeding */ while (TransferInProgress); /* * Setup the write command with the specified address and data for the * EEPROM */ Buffer[COMMAND_OFFSET] = WRITE_CMD; Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8); Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF); /* * Send the write command, address, and data to the EEPROM to be * written, no receive buffer is specified since there is nothing to * receive */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, Buffer, NULL, ByteCount + OVERHEAD_SIZE); while (TransferInProgress); /* * Wait for a bit of time to allow the programming to occur as reading * the status while programming causes it to fail because of noisy power * on the board containing the EEPROM, this loop does not need to be * very long but is longer to hopefully work for a faster processor */ while (DelayCount++ < 10000) { } /* * Wait for the write command to the EEPROM to be completed, it takes * some time for the data to be written */ while (1) { /* * Poll the status register of the device to determine when it * completes by sending a read status command and receiving the * status byte */ TransferInProgress = TRUE; XSpiPs_Transfer(SpiPtr, ReadStatusCmd, EepromStatus, sizeof(ReadStatusCmd)); /* * Wait for the transfer on the SPI bus to be complete before * proceeding */ while (TransferInProgress); /* * If the status indicates the write is done, then stop waiting, * if a value of 0xFF in the status byte is read from the * device and this loop never exits, the device slave select is * possibly incorrect such that the device status is not being * read */ if ((EepromStatus[1] & 0x03) == 0) { break; } } }