/********************************************************** **Name: ModuleSelectModeEntryCheck **Function: Confirm whether you can enter module select mode **Input: none **Output: none **********************************************************/ void ModuleSelectModeEntryCheck(void) { gb_FirstPowerUpFlag=1; //FirstPowerUp FlashRead(EEPROM_FirstAddr, gb_RxData); if(gb_RxData[0]==0x5A) //Power on ,config default parameter { gb_FreqBuf_Addr=gb_RxData[1]; gb_RateBuf_Addr=gb_RxData[2]; gb_PowerBuf_Addr=gb_RxData[3]; gb_FdevBuf_Addr=gb_RxData[4]; gb_BandBuf_Addr=gb_RxData[5]; gb_Modem_Addr_Backup=gb_Modem_Addr=gb_RxData[6]; gb_SystemMode=gb_RxData[8]; } else { gb_FreqBuf_Addr=0; gb_RateBuf_Addr=1; gb_PowerBuf_Addr=0; gb_FdevBuf_Addr=0; gb_BandBuf_Addr=0; gb_Modem_Addr_Backup=gb_Modem_Addr=0; gb_SystemMode=C_SysMode_Modem; //RF select modem mode } InitSystemParameter(); }
ReturnType FlashSingleProgram(udword udAddrOff,uCPUBusType ucValue) /**************************************************************************** * INPUT(S) : * OUTPUT(S) : * DESIGN DOC. : * FUNCTION DESCRIPTION : * ****************************************************************************/ { uCPUBusType val; OS_Use(&mSemaFlashDrv); FlashWrite( 0x00555, (uCPUBusType)CMD(0x00AA) ); /* 1st cycle */ FlashWrite( 0x002AA, (uCPUBusType)CMD(0x0055) ); /* 2nd cycle */ FlashWrite( 0x00555, (uCPUBusType)CMD(0x00A0) ); /* Program command */ FlashWrite( udAddrOff,ucValue ); /* Program value */ FlashDataToggle(); val = FlashRead( udAddrOff ); if (val != ucValue) { return Flash_OperationTimeOut; } OS_Unuse(&mSemaFlashDrv); return Flash_Success; }
/** * @brief 数据设置读取 */ void SaveRead(void) { S_Flash_Read lRead; lRead.Addr.Start = CONFIG_FLASH_SAVE_ADDR_START; lRead.Addr.End = lRead.Addr.Start + sizeof(sSave); lRead.Array = sSave; FlashRead(&lRead); }
ReturnType FlashDataToggle( void ) /**************************************************************************** * INPUT(S) : * OUTPUT(S) : * DESIGN DOC. : * FUNCTION DESCRIPTION : * ****************************************************************************/ { uCPUBusType ucVal1, ucVal2; FlashTimeOut(0); while(FlashTimeOut(120) != Flash_OperationTimeOut) { ucVal2 = FlashRead( ANY_ADDR ); ucVal1 = FlashRead( ANY_ADDR ); if( (ucVal1&CMD(0x0040)) == (ucVal2&CMD(0x0040)) ) { return Flash_Success; } if( (ucVal2&CMD(0x0020)) != CMD(0x0020) ) { continue; } ucVal1 = FlashRead( ANY_ADDR ); ucVal2 = FlashRead( ANY_ADDR ); if( (ucVal2&CMD(0x0040)) == (ucVal1&CMD(0x0040)) ) { return Flash_Success; } else { eiErrorInfo.sprRetVal=FlashSpec_ToggleFailed; return Flash_SpecificError; } } return Flash_OperationTimeOut; }
/** * Read data from Factory partition of Flash. * Backward compatibility to origin caller and convention. * 1. If you want to read data from Factory, converts absolute address of flash to * relative address regards to Factory partition and call FactoryRead() instead. * 2. If you want to read raw data from anywhere in flash, call FlashRead() instead. * 3. If you read data not in 0x40000~0x4FFFF, this function print warning message * and call FlashRead() instead. */ int FRead(const unsigned char *buf, int addr, int count) { if (!buf || addr < 0 || count <=0) return -1; /* If address fall in old Factory partition, call FactoryRead() instead. */ if (addr >= OFFSET_MTD_FACTORY && (addr + count) <= (OFFSET_MTD_FACTORY + SPI_PARALLEL_NOR_FLASH_FACTORY_LENGTH)) { return FactoryRead(buf, addr - OFFSET_MTD_FACTORY, count); } fprintf(stderr, "%s: Read data out of factory region or cross old factory boundary. (addr 0x%x count 0x%x)\n", __func__, addr, count); return FlashRead(buf, addr, count); }
static DWORD* AllocXIPLoc(void) { DWORD *pMem; DWORD dwBlockStart; DWORD dwBlockLen; FlashInit(TRUE); FlashGetBlockInfo((LPVOID)pdwXIPLoc, &dwBlockStart, &dwBlockLen); pMem = (DWORD *) malloc(dwBlockLen * sizeof(BYTE)); if (NULL == pMem) { return 0; } FlashRead((LPVOID)pdwXIPLoc, (LPVOID)pMem, dwBlockLen); return pMem; }
ReturnType FlashBlockErase(uBlockType ublBlockNr) /**************************************************************************** * INPUT(S) : * OUTPUT(S) : * DESIGN DOC. : * FUNCTION DESCRIPTION : * ****************************************************************************/ { ReturnType rRetVal = Flash_Success; /* Holds return value: optimistic initially! */ OS_Use(&mSemaFlashDrv); FlashWrite( 0x00555, (uCPUBusType)CMD(0x00AA) ); FlashWrite( 0x002AA, (uCPUBusType)CMD(0x0055) ); FlashWrite( 0x00555, (uCPUBusType)CMD(0x0080) ); FlashWrite( 0x00555, (uCPUBusType)CMD(0x00AA) ); FlashWrite( 0x002AA, (uCPUBusType)CMD(0x0055) ); FlashWrite( BlockOffset[ublBlockNr], (uCPUBusType)CMD(0x0030) ); FlashTimeOut(0); while( !(FlashRead( BlockOffset[ublBlockNr] ) & CMD(0x0008) ) ) { if (FlashTimeOut(5) == Flash_OperationTimeOut) { FlashWrite( ANY_ADDR, (uCPUBusType)CMD(0x00F0) ); /* Use single instruction cycle method */ return Flash_OperationTimeOut; } } if( FlashDataToggle() != Flash_Success ) { FlashWrite( ANY_ADDR, (uCPUBusType)CMD(0x00F0) ); /* Use single instruction cycle method */ rRetVal=Flash_BlockEraseFailed; } OS_Unuse(&mSemaFlashDrv); return rRetVal; }
///////////////////////////////////////////////////// // // FlashReadConfig(void) // // read READBUF bytes data from flash // store data in global variable pcContentBuf[READBUF] // // Return Value: // 0:Error // 1:Succssed // ////////////////////////////////////////////////////// int FlashReadConfig() { unsigned long offset; // where the value come from char rdata[READBUF]; int tmp,rtn,i; int flashfd; // no use memset(rdata, 0, READBUF); rtn=FlashRead(offset, rdata,READBUF); if( rtn < 0 ) { printf("Flash read fail\n"); return 0; } else { //printf("Flash read %d bytes\n", rtn); for(i=0; i<rtn; i++) pcContentBuf[i]=rdata[i]; return 1; } }
/***************************************************************************** * * 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; }
int main(void) { Initialize(); sprintf(text,"\r\n\r\nHypnocube FLASH destroyer %d.%d\r\n",VERSION>>4, VERSION&15); PrintSerial(text); sprintf(text,"Testing %d frames of %d bytes each.\r\n",FRAMES,WORDS_PER_FRAME*4); PrintSerial(text); sprintf(text,"Flash starts at 0x%08x.\r\n",FlashData); PrintSerial(text); int frame = 0; int ramFrame = -1; int i; uint32_t errors = 0; WriteCoreTimer(0); while (1) { uint32_t startOffset = WORDS_PER_FRAME*frame; if (ramFrame != frame) { InitRamFrame(); ramFrame = frame; } ++passes[frame]; // message for start uint32_t time = ReadCoreTimer(); sprintf(text,"Pass %d, frame %d, offset %08x, time %08x, errors %d\r\n", passes[frame],frame,startOffset,time,errors ); PrintSerial(text); // erase frame if (!FlashErase(startOffset,WORDS_PER_FRAME)) PrintSerial("ERROR: flash erase failed.\r\n"); // check all entries are FLASH_ERASED_WORD_VALUE for (i = 0; i < WORDS_PER_FRAME; ++i) { uint32_t word = FlashRead(startOffset+i); if (ramBufferErased[i] != word) { // an error, output, and set buffer OutputError('E',startOffset+i,word,ramBufferErased[i]); ramBufferErased[i] = word; ++errors; } } // write all ~FLASH_ERASED_WORD_VALUE for (i = 0; i < WORDS_PER_FRAME; ++i) { if (!FlashWrite(startOffset+i,~(FLASH_ERASED_WORD_VALUE))) { snprintf(text,TEXT_SIZE,"ERROR: flash write failed ar offset %08X.\r\n",startOffset+i); PrintSerial(text); } } // check all entries are FLASH_ERASED_WORD_VALUE for (i = 0; i < WORDS_PER_FRAME; ++i) { uint32_t word = FlashRead(startOffset+i); if (ramBufferWritten[i] != word) { // an error, output, and set buffer OutputError('W',startOffset+i,word,ramBufferWritten[i]); ramBufferWritten[i] = word; ++errors; } } // check if frame changed uint8_t byte; if (UARTReadByte(&byte)) { snprintf(text,TEXT_SIZE,"Command received %c [%02x].\r\n",byte,byte); PrintSerial(text); if ('0' <= byte && byte <= FRAMES+'0'-1) { // change frame frame = byte-'0'; snprintf(text,TEXT_SIZE,"Switching to frame %d.\r\n",frame); PrintSerial(text); } if (byte == 'q') break; } } PrintSerial("Quitting...\r\n"); return 0; }
/***************************************************************************** * * 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 XSpiPs * 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 SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr, u16 SpiDeviceId, u16 SpiIntrId) { int Status; u8 *BufferPtr; u8 UniqueValue; u32 Count; XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */ u32 TempAddress; u32 MaxSize = MAX_DATA; u32 ChipSelect = FLASH_SPI_SELECT_1; 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; } /* * Lookup the device configuration in the temporary CROM table. Use this * configuration info down below when initializing this component. */ ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId); if (ConfigPtr == NULL) { return XST_DEVICE_NOT_FOUND; } XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr, ConfigPtr->BaseAddress); /* Initialize the XILISF Library */ XIsf_Initialize(&Isf, SpiInstancePtr, ChipSelect, IsfWriteBuffer); XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE); /* * Connect the Spi device to the interrupt subsystem such that * interrupts can occur. This function is application specific */ Status = SpiSetupIntrSystem(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 */ XIsf_SetStatusHandler(&Isf, SpiInstancePtr, (XSpiPs_StatusHandler) SpiHandler); memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* Unprotect Sectors */ FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG); FlashErase(&Isf, TEST_ADDRESS, MaxSize); /* * 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 */ TempAddress = TEST_ADDRESS; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MaxSize; Count++, UniqueValue++, TempAddress++) { WriteBuffer[0] = (u8)(UniqueValue); FlashWrite(&Isf, TempAddress, 1, XISF_WRITE); } /* * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read * command */ FlashRead(&Isf, TEST_ADDRESS, MaxSize, XISF_READ); /* * 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; } } SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId); return XST_SUCCESS; }
int main(int argc, char *argv[]) { int opt; char options[] = "r:w:f:l:o:c:?"; int fd, method; unsigned char buffer[FLASH_MAX_RW_SIZE]; int i=0; unsigned int *src; unsigned int *dst; unsigned int value; unsigned int bytes; unsigned int start_addr; unsigned int end_addr; if (argc < 3) { show_usage(); return 0; } while ((opt = getopt (argc, argv, options)) != -1) { switch (opt) { case 'r': dst = (unsigned int *)buffer; src = (unsigned int *)strtol(optarg, NULL, 16); method = FLASH_IOCTL_READ; break; case 'w': dst = (unsigned int *)strtol(optarg, NULL, 16); method = FLASH_IOCTL_WRITE; break; case 'f': start_addr=strtol(optarg, NULL, 16); method = FLASH_IOCTL_ERASE; break; case 'l': end_addr=strtol(optarg, NULL, 16); method = FLASH_IOCTL_ERASE; break; case 'c': bytes=strtol(optarg,NULL,10); if(bytes > FLASH_MAX_RW_SIZE) { printf("Too many bytes - %d > %d bytes\n", bytes, FLASH_MAX_RW_SIZE); return 0; } break; case 'o': value=strtol(optarg, NULL, 16); break; case '?': show_usage(); } } switch(method) { case FLASH_IOCTL_READ: if(FlashRead(dst,src, bytes)<0) { printf("READ: Out of scope\n"); } else { for(i=0; i<bytes; i++) { printf("%X: %X\n", ((unsigned int)src)+i, buffer[i]); } } break; case FLASH_IOCTL_WRITE: if(FlashWrite(&value, dst, 1)<0) { printf("WRITE: Out of scope\n"); } else { printf("Write %0X to %0X\n", value, dst); } break; case FLASH_IOCTL_ERASE: if(end_addr<start_addr) { printf("ERASE: End addr MUST bigger than Start addr\n"); break; } if(FlashErase(start_addr, end_addr)<0) { printf("ERASE: Out of scope\n"); } else { printf("Erase Addr From %0X To %0X\n",start_addr, end_addr); } break; } return 0; }
/******************************************************************************* Function: ReturnType Flash( InstructionType insInstruction, ParameterType *fp ) Arguments: insInstruction is an enum which contains all the available Instructions of the SW driver. fp is a (union) parameter struct for all Flash Instruction parameters Return Value: The function returns the following conditions: Flash_AddressInvalid, Flash_MemoryOverflow, Flash_PageEraseFailed, Flash_PageNrInvalid, Flash_SectorNrInvalid, Flash_FunctionNotSupported, Flash_NoInformationAvailable, Flash_OperationOngoing, Flash_OperationTimeOut, Flash_ProgramFailed, Flash_SpecificError, Flash_Success, Flash_WrongType Description: This function is used to access all functions provided with the current Flash device. Pseudo Code: Step 1: Select the right action using the insInstruction parameter Step 2: Execute the Flash memory Function Step 3: Return the Error Code *******************************************************************************/ ReturnType Flash( InstructionType insInstruction, ParameterType *fp ) { ReturnType rRetVal; ST_uint8 ucStatusRegister; ST_uint16 ucDeviceIdentification; #ifdef USE_JEDEC_STANDARD_TWO_BYTE_SIGNATURE ST_uint8 ucManufacturerIdentification; #endif switch (insInstruction) { case WriteEnable: rRetVal = FlashWriteEnable( ); break; case WriteDisable: rRetVal = FlashWriteDisable( ); break; case ReadDeviceIdentification: rRetVal = FlashReadDeviceIdentification(&ucDeviceIdentification); (*fp).ReadDeviceIdentification.ucDeviceIdentification = ucDeviceIdentification; break; #ifdef USE_JEDEC_STANDARD_TWO_BYTE_SIGNATURE case ReadManufacturerIdentification: rRetVal = FlashReadManufacturerIdentification(&ucManufacturerIdentification); (*fp).ReadManufacturerIdentification.ucManufacturerIdentification = ucManufacturerIdentification; break; #endif case ReadStatusRegister: rRetVal = FlashReadStatusRegister(&ucStatusRegister); (*fp).ReadStatusRegister.ucStatusRegister = ucStatusRegister; break; case WriteStatusRegister: ucStatusRegister = (*fp).WriteStatusRegister.ucStatusRegister; rRetVal = FlashWriteStatusRegister(ucStatusRegister); break; case Read: rRetVal = FlashRead( (*fp).Read.udAddr, (*fp).Read.pArray, (*fp).Read.udNrOfElementsToRead ); break; case FastRead: rRetVal = FlashFastRead( (*fp).Read.udAddr, (*fp).Read.pArray, (*fp).Read.udNrOfElementsToRead ); break; case PageProgram: rRetVal = FlashProgram( (*fp).PageProgram.udAddr, (*fp).PageProgram.pArray, (*fp).PageProgram.udNrOfElementsInArray ); break; case SectorErase: rRetVal = FlashSectorErase((*fp).SectorErase.ustSectorNr ); break; case SubSectorErase: rRetVal = FlashSubSectorErase((*fp).SubSectorErase.ustSectorNr ); break; case BulkErase: rRetVal = FlashBulkErase( ); break; #ifndef NO_DEEP_POWER_DOWN_SUPPORT case DeepPowerDown: rRetVal = FlashDeepPowerDown( ); break; case ReleaseFromDeepPowerDown: rRetVal = FlashReleaseFromDeepPowerDown( ); break; #endif case Program: rRetVal = FlashProgram( (*fp).Program.udAddr, (*fp).Program.pArray, (*fp).Program.udNrOfElementsInArray); break; default: rRetVal = Flash_FunctionNotSupported; break; } /* EndSwitch */ return rRetVal; } /* EndFunction Flash */
/** * 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; }
bool IMI::FlightDownload(Port &port, const RecordedFlightInfo &flight_info, Path path, OperationEnvironment &env) { if (!_connected) return false; MessageParser::Reset(); Flight flight; if (!FlashRead(port, &flight, flight_info.internal.imi, sizeof(flight), env)) return false; FILE *fileIGC = _tfopen(path.c_str(), _T("w+b")); if (fileIGC == nullptr) return false; unsigned fixesCount = COMM_MAX_PAYLOAD_SIZE / sizeof(Fix); Fix *fixBuffer = (Fix*)malloc(sizeof(Fix) * fixesCount); if (fixBuffer == nullptr) return false; bool ok = true; WriteHeader(flight.decl, flight.signature.tampered, fileIGC); int noenl = 0; if ((flight.decl.header.sensor & IMINO_ENL_MASK) != 0) noenl = 1; unsigned address = flight_info.internal.imi + sizeof(flight); unsigned fixesRemains = flight.finish.fixes; while (ok && fixesRemains) { unsigned fixesToRead = fixesRemains; if (fixesToRead > fixesCount) fixesToRead = fixesCount; if (!FlashRead(port, fixBuffer, address, fixesToRead * sizeof(Fix), env)) ok = false; for (unsigned i = 0; ok && i < fixesToRead; i++) { const Fix *pFix = fixBuffer + i; if (IMIIS_FIX(pFix->id)) WriteFix(*pFix, false, noenl, fileIGC); } address = address + fixesToRead * sizeof(Fix); fixesRemains -= fixesToRead; if (env.IsCancelled()) // canceled by user ok = false; } free(fixBuffer); if (ok) WriteSignature(flight.signature, flight.decl.header.sn, fileIGC); fclose(fileIGC); if (!ok) File::Delete(Path(path)); return ok; }
int SpiFlashPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId) { u8 *BufferPtr; u8 UniqueValue; u32 Count; XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */ u32 TempAddress; /* * Lookup the device configuration in the temporary CROM table. Use this * configuration info down below when initializing this component. */ ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId); if (ConfigPtr == NULL) { return XST_DEVICE_NOT_FOUND; } XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr, ConfigPtr->BaseAddress); /* Initialize the XILISF Library */ XIsf_Initialize(&Isf, SpiInstancePtr, FLASH_SPI_SELECT, IsfWriteBuffer); memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* Unprotect Sectors */ FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG); FlashErase(&Isf, TEST_ADDRESS, MAX_DATA); /* * 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 */ TempAddress = TEST_ADDRESS; for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++, TempAddress++) { WriteBuffer[0] = (u8)(UniqueValue); FlashWrite(&Isf, TempAddress, 1, XISF_WRITE); } /* * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read * command */ FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ); /* * 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; }
//инициализация IAP. Поиск самого нового сектора для записи //В случае наличия сбойных секторов будет восстановлен предыдущий сохраненный сектор. Валидный сектор //должен иметь сигнатуру, счётчик секторов и контрольную сумму. //Если нет ни одного валидного сектора, то данные будут восстановлены из первого сектора и все //настройки из protected_eeprom будут установлены по умолчанию void FlashInit() { int current_sector_i; int current_sector_f; int i; INT16U ee_cnt_int; INT16U min_ee_cnt; INT16U current_ee_cnt; int min_sector_num; BOOL has_valid_sectors; unsigned char ee_cnt[2]; unsigned char ee_version[EEPROM_VER_LENGTH]; has_valid_sectors = DEF_FALSE; min_ee_cnt = EE_MAX_CNT; //проходим по всем секторам в поисках валидного и самого нового сектора //если есть одновременно сектора со счётчиками EE_MIN_CNT и EE_MAX_CNT, то считаем, что //самый новый сектор - это от EE_MIN_CNT до максимального с шагом 1. Если шаг изменился, то //дальше не считаем. for(current_sector_i = EE_FIRST_SECTOR; current_sector_i <= EE_LAST_SECTOR; current_sector_i++) { FlashRead(current_sector_i, eeprom_version, ee_version, EEPROM_VER_LENGTH); if(strncmp((char const *)ee_version, (char const *)eeprom_version_flash, EEPROM_VER_LENGTH) != 0) continue; if(!FlashCheckCrc(current_sector_i)) continue; FlashRead(current_sector_i, eeprom_cnt, ee_cnt, 2); ee_cnt_int = ((ee_cnt[0] & 0xFF) + ((ee_cnt[1] & 0xFF) << 8)); //invalid flash sector if((ee_cnt_int == EE_INVALID_ZERO) || (ee_cnt_int == EE_INVALID_ONES)) continue; has_valid_sectors = DEF_TRUE; if(ee_cnt_int <= min_ee_cnt) { min_ee_cnt = ee_cnt_int; min_sector_num = current_sector_i; } } //нет валидных секторов - пересоздаём всё заново if(!has_valid_sectors) { current_sector = EE_FIRST_SECTOR; current_cnt = EE_MIN_CNT; FlashCopySectorFromScratch(current_sector, FlashNextSector()); return; } //есть валидные сектора //Обходим все валидные сектора, начиная с сектора с минимальным счётчиком //если следующий сектор имеет счётчик меньше начального или имеет счётчик на 2 //больший предыдущего, то значит мы обнаружили самый новый сектор флэш current_sector_i = min_sector_num; current_sector_f = min_sector_num; current_ee_cnt = min_ee_cnt; for(i = EE_FIRST_SECTOR; i <= EE_LAST_SECTOR; i++) { FlashRead(current_sector_i, eeprom_version, ee_version, EEPROM_VER_LENGTH); if(strncmp((char const *)ee_version, (char const *)eeprom_version_flash, EEPROM_VER_LENGTH) != 0) { if(current_sector_i >= EE_LAST_SECTOR) { current_sector_i = EE_FIRST_SECTOR; } else { current_sector_i++; } continue; } if(!FlashCheckCrc(current_sector_i)) continue; FlashRead(current_sector_i, eeprom_cnt, ee_cnt, 2); ee_cnt_int = ((ee_cnt[0] & 0xFF) + ((ee_cnt[1] & 0xFF) << 8)); //invalid flash sector if((ee_cnt_int == EE_INVALID_ZERO) || (ee_cnt_int == EE_INVALID_ONES)) { if(current_sector_i >= EE_LAST_SECTOR) { current_sector_i = EE_FIRST_SECTOR; } else { current_sector_i++; } continue; } if(ee_cnt_int < current_ee_cnt) break; if((ee_cnt_int - current_ee_cnt) > 1) break; current_ee_cnt = ee_cnt_int; current_sector_f = current_sector_i; if(current_sector_i >= EE_LAST_SECTOR) { current_sector_i = EE_FIRST_SECTOR; } else { current_sector_i++; } } //определен первый сектор во флэш current_sector = current_sector_f; current_cnt = current_ee_cnt; }
/***************************************************************************** * * 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 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 provides the QSPI FLASH interface for the Simplified header * functionality. * * @param SourceAddress is address in FLASH data space * @param DestinationAddress is address in DDR data space * @param LengthBytes is the length of the data in Bytes * * @return * - XST_SUCCESS if the write completes correctly * - XST_FAILURE if the write fails to completes correctly * * @note none. * ****************************************************************************/ u32 QspiAccess( u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes) { u8 *BufferPtr; u32 Length = 0; u32 BankSel = 0; u32 LqspiCrReg; u32 Status; u8 BankSwitchFlag = 1; /* * Linear access check */ if (LinearBootDeviceFlag == 1) { /* * Check for non-word tail, add bytes to cover the end */ if ((LengthBytes%4) != 0){ LengthBytes += (4 - (LengthBytes & 0x00000003)); } memcpy((void*)DestinationAddress, (const void*)(SourceAddress + FlashReadBaseAddress), (size_t)LengthBytes); } else { /* * Non Linear access */ BufferPtr = (u8*)DestinationAddress; /* * Dual parallel connection actual flash is half */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { SourceAddress = SourceAddress/2; } while(LengthBytes > 0) { /* * Local of DATA_SIZE size used for read/write buffer */ if(LengthBytes > DATA_SIZE) { Length = DATA_SIZE; } else { Length = LengthBytes; } /* * Dual stack connection */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_STACK_CONNECTION) { /* * Get the current LQSPI configuration value */ LqspiCrReg = XQspiPs_GetLqspiConfigReg(QspiInstancePtr); /* * Select lower or upper Flash based on sector address */ if (SourceAddress >= (QspiFlashSize/2)) { /* * Set selection to U_PAGE */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, LqspiCrReg | XQSPIPS_LQSPI_CR_U_PAGE_MASK); /* * Subtract first flash size when accessing second flash */ SourceAddress = SourceAddress - (QspiFlashSize/2); fsbl_printf(DEBUG_INFO, "stacked - upper CS \n\r"); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); } } /* * Select bank */ if ((SourceAddress >= FLASH_SIZE_16MB) && (BankSwitchFlag == 1)) { BankSel = SourceAddress/FLASH_SIZE_16MB; fsbl_printf(DEBUG_INFO, "Bank Selection %d\n\r", BankSel); Status = SendBankSelect(BankSel); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO, "Bank Selection Failed\n\r"); return XST_FAILURE; } BankSwitchFlag = 0; } /* * If data to be read spans beyond the current bank, then * calculate length in current bank else no change in length */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { /* * In dual parallel mode, check should be for half * the length. */ if((SourceAddress & BANKMASK) != ((SourceAddress + (Length/2)) & BANKMASK)) { Length = (SourceAddress & BANKMASK) + FLASH_SIZE_16MB - SourceAddress; /* * Above length calculated is for single flash * Length should be doubled since dual parallel */ Length = Length * 2; BankSwitchFlag = 1; } } else { if((SourceAddress & BANKMASK) != ((SourceAddress + Length) & BANKMASK)) { Length = (SourceAddress & BANKMASK) + FLASH_SIZE_16MB - SourceAddress; BankSwitchFlag = 1; } } /* * Copying the image to local buffer */ FlashRead(SourceAddress, Length); /* * Moving the data from local buffer to DDR destination address */ memcpy(BufferPtr, &ReadBuffer[DATA_OFFSET + DUMMY_SIZE], Length); /* * Updated the variables */ LengthBytes -= Length; /* * For Dual parallel connection address increment should be half */ if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_PARALLEL_CONNECTION) { SourceAddress += Length/2; } else { SourceAddress += Length; } BufferPtr = (u8*)((u32)BufferPtr + Length); } /* * Reset Bank selection to zero */ Status = SendBankSelect(0); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO, "Bank Selection Reset Failed\n\r"); return XST_FAILURE; } if (XPAR_PS7_QSPI_0_QSPI_MODE == DUAL_STACK_CONNECTION) { /* * Reset selection to L_PAGE */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, LqspiCrReg & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK)); fsbl_printf(DEBUG_INFO, "stacked - lower CS \n\r"); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); } } return XST_SUCCESS; }
PRIVATE uint8 XMODEM_SendFrame(void) { sint i,ch; uint16 Check; uint8 SendFlag; uint8 canCount; #ifdef SF_Xmodem uint8 SF_Block[128]; #endif xv = &XV; SendFlag = FALSE; if (xv->PktBufCount==0) { canCount=0; XMODEM_Read1Byte(&ch); do { #if 1 if (ch==XV_TIMEOUT) //frank change to 0xFF //if (ch==0xFF) { xv->XMode=0; return XMODEM_TIMEOUT; } #endif switch (ch&0xff) { case ACK: if(xv->XMode==0) { pause(10); return (XMODEM_COMPLETED); } else if (xv->PktNumSent==(uint8)(xv->PktNum+1)) { xv->PktNum = xv->PktNumSent; if (xv->PktNum==0) xv->PktNumOffset = xv->PktNumOffset + 256; SendFlag = TRUE; } break; case NAK: SendFlag = TRUE; break; case CAN: if(++canCount>=2) return XMODEM_ABORT; break; case 'C': if ((xv->PktNum==0) && (xv->PktNumOffset==0)) { if ((xv->XOption==XoptCheck) && (xv->PktNumSent==0)) XMODEM_SetOption(XoptCRC); if (xv->XOption!=XoptCheck) SendFlag = TRUE; } break; } if (! SendFlag) XMODEM_Read1Byte(&ch); } while (!SendFlag); if (xv->PktNumSent==xv->PktNum) /* make a new packet */ { xv->PktNumSent++; if (xv->DataLen==128) xv->PktBuf[0] = SOH; else xv->PktBuf[0] = STX; xv->PktBuf[1] = xv->PktNumSent; xv->PktBuf[2] = ~ ((uint8)xv->PktNumSent); i = 1; #ifndef SF_Xmodem while ((i<=xv->DataLen) && send_length>0) { xv->PktBuf[2+i] = *send_ptr++; i++; send_length--; } #else //read 128 bytes or less data from serial flash if((i<=xv->DataLen) && send_length>0) { while(Flash_Success!= FlashRead((uint32)send_ptr,&xv->PktBuf[2+i],xv->DataLen)); { send_ptr += xv->DataLen; i += xv->DataLen; send_length -= xv->DataLen; } } #endif if (i>1) { while (i<=xv->DataLen) { xv->PktBuf[2+i] = 0x1A; i++; } Check = XMODEM_CalcCheck(xv->PktBuf); if (xv->CheckLen==1) /* Checksum */ xv->PktBuf[xv->DataLen+3] = (uint8)Check; else { xv->PktBuf[xv->DataLen+3] = (uint8)((Check&0xff00)>>8); xv->PktBuf[xv->DataLen+4] = (uint8)(Check&0xff); } xv->PktBufCount = 3 + xv->DataLen + xv->CheckLen; } else { /* send EOT */