/** * * This function waits till the Serial Flash is ready to accept next command. * * @param None. * * @return XST_SUCCESS if successful else XST_FAILURE. * * @note This function reads the status register of the Serial Flash and waits till the WIP bit of the status register becomes 0. * ******************************************************************************/ int IsfWaitForFlashNotBusy(void) { int Status; u8 StatusReg; while(1) { /* * Get the Status Register. */ Status = XIsf_GetStatus(&Isf, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Check if the flash is ready to accept the next command. * If so break. */ StatusReg = ReadBuffer[BYTE2]; if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { break; } } return XST_SUCCESS; }
/** * * This function waits till the Intel Serial Flash is ready to accept next * command. * * @param None * * @return XST_SUCCESS if successful else XST_FAILURE. * * @note This function reads the Status Register of the Serial Flash and * waits till the WIP bit of the Status Register becomes 0. * ******************************************************************************/ int IsfWaitForFlashNotBusy(void) { int Status; u8 StatusReg; while(1) { /* * Get the Status Register. */ TransferInProgress = TRUE; Status = XIsf_GetStatus(&Isf, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is in progress. */ while(TransferInProgress); /* * Check if there are any errors in the transaction. */ if(ErrorCount != 0) { return XST_FAILURE; } /* * Check if the flash is ready to accept the next command. */ StatusReg = ReadBuffer[BYTE2]; if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { /* * If there were errors return XST_FAILURE. */ if (StatusReg & (XISF_SR_PROG_FAIL_MASK | XISF_SR_ERASE_FAIL_MASK)) { return XST_FAILURE; } break; } } return XST_SUCCESS; }
/** * * This function waits till the Serial Flash is ready to accept next command. * * @param None * * @return XST_SUCCESS if successful else XST_FAILURE. * * @note None. * ******************************************************************************/ static int IsfWaitForFlashNotBusy() { int Status; u8 StatusReg; u8 ReadBuffer[2]; while(1) { /* * Get the Status Register. */ TransferInProgress = TRUE; Status = XIsf_GetStatus(&Isf, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check for any errors. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Check if the Serial Flash is ready to accept the next * command. If so break. */ StatusReg = ReadBuffer[BYTE2]; if(StatusReg & XISF_SR_IS_READY_MASK) { break; } } return XST_SUCCESS; }
/** * * This function initializes the instance structure with the device geometry of * the Atmel Serial Flash if it is an Atmel device. * * @param InstancePtr is a pointer to the XIsf instance. * @param BufferPtr is a pointer to the memory where the device info of * the Serial Flash is present. * * @return - XST_SUCCESS if device information matches the JEDEC * information of the Atmel Serial Flash. * - XST_FAILURE if the device information doesn't match with Atmel * Serial Flash. * * @note None * ******************************************************************************/ static int AtmelFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) { int Status; u32 Index; u8 StatusRegister; u8 NumOfDevices; u8 ManufacturerID; ManufacturerID = BufferPtr[BYTE2]; if (ManufacturerID == XISF_MANUFACTURER_ID_ATMEL) { /* * For Atmel Serial Flash the device code is the 3rd byte of the * JEDEC info. */ InstancePtr->DeviceCode = BufferPtr[BYTE3]; /* * Get the Status Register contents. * The IsReady is temporarily made TRUE to fetch the Status * Register contents. */ InstancePtr->IsReady = TRUE; Status = XIsf_GetStatus(InstancePtr, BufferPtr); InstancePtr->IsReady = FALSE; if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait until the transfer is complete. */ do { #ifndef XPAR_XISF_INTERFACE_PSQSPI Status = InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr, InstancePtr->SpiSlaveSelect); #else Status = InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr); #endif } while(Status == XST_DEVICE_BUSY); if (Status != XST_SUCCESS) { return XST_FAILURE; } StatusRegister = BufferPtr[BYTE2]; /* * Get the Address mode from the Status Register of the Serial * Flash. */ InstancePtr->AddrMode = StatusRegister & XISF_SR_ADDR_MODE_MASK; /* * Update the Serial Flash instance structure with device * geometry. */ NumOfDevices = sizeof(AtmelDevices) / sizeof(AtmelDeviceGeometry); for(Index = 0; Index < NumOfDevices; Index++) { if (InstancePtr->DeviceCode == AtmelDevices[Index]. DeviceCode) { /* * Default address mode device. */ if (InstancePtr->AddrMode == XISF_DEFAULT_ADDRESS) { InstancePtr->BytesPerPage = AtmelDevices [Index]. BytesPerPageDefaultMode; } else { /* * Power of 2 address mode device. */ InstancePtr->BytesPerPage = AtmelDevices [Index]. BytesPerPagePowerOf2Mode; } InstancePtr->PagesPerBlock = AtmelDevices[Index].PagesPerBlock; InstancePtr->BlocksPerSector = AtmelDevices[Index].BlocksPerSector; InstancePtr->NumOfSectors = AtmelDevices[Index].NumOfSectors; if (InstancePtr->BytesPerPage > XISF_BYTES1024_PER_PAGE ) { InstancePtr->ByteMask = XISF_BYTES2048_PER_PAGE_MASK; } else if (InstancePtr->BytesPerPage > XISF_BYTES512_PER_PAGE ) { InstancePtr->ByteMask = XISF_BYTES1024_PER_PAGE_MASK; } else if (InstancePtr->BytesPerPage > XISF_BYTES256_PER_PAGE ) { InstancePtr->ByteMask = XISF_BYTES512_PER_PAGE_MASK; } else { InstancePtr->ByteMask = XISF_BYTES256_PER_PAGE_MASK; } InstancePtr->IsReady = TRUE; } } } /* * If the device is not supported, return Failure. */ if (InstancePtr->IsReady != TRUE) { return XST_FAILURE; } return XST_SUCCESS; }
/** * * Main function to execute the Intel Serial Flash SPR example. * * @param None * * @return XST_SUCCESS if successful else XST_FAILURE. * * @note None * ******************************************************************************/ int main() { int Status; u32 Index; u32 Address; u8 StatusReg; XIsf_WriteParam WriteParam; XIsf_ReadParam ReadParam; /* * Initialize the SPI driver so that it's ready to use, * specify the device ID that is generated in xparameters.h. */ Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Connect the SPI driver to the interrupt subsystem such that * interrupts can occur. This function is application specific. */ Status = SetupInterruptSystem(&Spi); 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. */ XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); /* * Start the SPI driver so that interrupts and the device are enabled. */ XSpi_Start(&Spi); /* * Initialize the Serial Flash Library. */ Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Set The transfer Mode to Interrupt */ XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); /* * Perform the Write Enable operation. */ TransferInProgress = TRUE; Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Read the sector protection register. */ TransferInProgress = TRUE; Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Clear all the block protection bits in the sector protection register * value read above. */ WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & (~(XISF_SR_BLOCK_PROTECT_MASK)); /* * Write this value to the sector protection register to disable the * sector protection. */ TransferInProgress = TRUE; Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Specify the address in the Serial Flash for the Erase/Write/Read * operations. */ Address = ISF_TEST_ADDRESS; /* * Perform the Write Enable operation. */ TransferInProgress = TRUE; Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform the Sector Erase operation. */ TransferInProgress = TRUE; Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform the Write Enable operation. */ TransferInProgress = TRUE; Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * - Set the address within the Serial Flash where the data is to be * written. * - Set the number of bytes to be written to the Serial Flash. * - Write Buffer which contains the data to be written to the Serial * Flash. */ WriteParam.Address = Address; WriteParam.NumBytes = ISF_PAGE_SIZE; WriteParam.WritePtr = WriteBuffer; /* * Prepare the write buffer. Fill in the data need to be written into * Serial Flash. */ for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; } /* * Perform the Write operation. */ TransferInProgress = TRUE; Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform the Write Enable operation. */ TransferInProgress = TRUE; Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Read the sector protection register. */ TransferInProgress = TRUE; Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Set all the block protection bits in the sector protection register * value read above and write it back to the sector protection register. */ WriteBuffer[BYTE1] = ReadBuffer[BYTE2] | (XISF_SR_BLOCK_PROTECT_MASK); /* * Enable the sector protection. */ TransferInProgress = TRUE; Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform the Write Enable operation. */ TransferInProgress = TRUE; Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform the Sector Erase operation. This should not work as writes to * the Serial Flash are disabled. */ TransferInProgress = TRUE; Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Read the Status Register. */ TransferInProgress = TRUE; Status = XIsf_GetStatus(&Isf, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is in progress. */ while(TransferInProgress); /* * Check if there are any errors in the transaction. */ if(ErrorCount != 0) { return XST_FAILURE; } /* * Check if the erase fail flag is set in the status register. This flag * should be set as a sector erase operation was attempted when sector * protection was enabled. */ StatusReg = ReadBuffer[BYTE2]; if((StatusReg & XISF_SR_ERASE_FAIL_MASK) == 0) { return XST_FAILURE; } /* * Clear the status register fail flags in the Serial Flash status * register. */ TransferInProgress = TRUE; Status = XIsf_Ioctl(&Isf, XISF_IOCTL_CLEAR_SR_FAIL_FLAGS); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Read the Status Register. */ TransferInProgress = TRUE; Status = XIsf_GetStatus(&Isf, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is in progress. */ while(TransferInProgress); /* * Check if there are any errors in the transaction. */ if(ErrorCount != 0) { return XST_FAILURE; } /* * Check if the erase fail flag is clear in the status register. This * flag should be clear as a 'Clear SR Fail Flags' command has been * executed. */ StatusReg = ReadBuffer[BYTE2]; if((StatusReg & XISF_SR_ERASE_FAIL_MASK) != 0) { return XST_FAILURE; } /* * Read the sector protection register. */ TransferInProgress = TRUE; Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Clear all the block protection bits in the sector protection register * value read above and write it back to the sector protection register * to disable sector protection for all sectors. */ WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & ~(XISF_SR_BLOCK_PROTECT_MASK); /* * Disable the sector protection. */ TransferInProgress = TRUE; Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Wait till the Flash is not Busy. */ Status = IsfWaitForFlashNotBusy(); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * The following code Reads data from a Page in the Intel Serial Flash. */ /* * Set the * - Address in the Serial Flash where the data is to be read from. * - Number of bytes to be read from the Serial Flash. * - Read Buffer to which the data is to be read. */ ReadParam.Address = Address; ReadParam.NumBytes = ISF_PAGE_SIZE; ReadParam.ReadPtr = ReadBuffer; /* * Perform the read operation. */ TransferInProgress = TRUE; Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); if(Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait till the Transfer is complete and check if there are any errors * in the transaction. */ while(TransferInProgress); if(ErrorCount != 0) { return XST_FAILURE; } /* * Compare the data read against the data Written. */ for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != (u8)(Index + ISF_TEST_BYTE)) { return XST_FAILURE; } } return XST_SUCCESS; }