// The erase-first flash write function ----------------------------------------- void Fl2FlashEraseWriteEntry() { uint32_t tmp = theFlashParams.block_size; if (tmp == 0) { FlashEraseData *p = (FlashEraseData*)theFlashParams.buffer; for (uint32_t i = 0; i < theFlashParams.count; ++i) { tmp = FlashErase((CODE_REF)p->start, p->length); if (tmp != 0) break; ++p; } } else { tmp = FlashErase((CODE_REF)theFlashParams.base_ptr, theFlashParams.block_size); if (tmp == 0) { tmp = FlashWrite((CODE_REF)theFlashParams.base_ptr, theFlashParams.offset_into_block, theFlashParams.count, theFlashParams.buffer); } } theFlashParams.count = tmp; }
void main(void) { int seg, data; char c; unsigned e=0x9000,i=0; InitLib(); Print("\r\nPlease Input a value writting to segment 0x9000 of Flash Member: "); Scanf("%d", &seg); FlashErase(e); while(i<65535) { FlashWrite(e, i, seg); Print("\r\nThe value %d is writting to offset %d of Flash Memory", seg, i); i++; seg++; if(i%100==0) { Print("\r\nPress q to quit or any key to continue..."); c=Getch(); if ((c=='q') || (c=='Q')) return; } } }
void FlashWrite(unsigned int addr, char *data) { int i; FlashErase(addr); // must erase flash before writing TBLPTR = addr; // load the table latch with data for (i = 0; i < 64; i++) { TABLAT = data[i]; // copy data from buffer _asm TBLWTPOSTINC // increment the table latch _endasm } TBLPTR = addr; EECON1bits.EEPGD = 1; // select program memory EECON1bits.CFGS = 0; // enable program memory access EECON1bits.WREN = 1; // enable write access INTCONbits.GIE = 0; // disable interrupts // write sequence EECON2 = 0x55; EECON2 = 0xAA; EECON1bits.WR = 1; INTCONbits.GIE = 1; // enable interrupts }
/************************************************************************************//** ** \brief Erases the non-volatile memory. ** \param addr Start address. ** \param len Length in bytes. ** \return BLT_TRUE if successful, BLT_FALSE otherwise. ** ****************************************************************************************/ blt_bool NvmErase(blt_addr addr, blt_int32u len) { #if (BOOT_NVM_HOOKS_ENABLE > 0) blt_int8u result = BLT_NVM_NOT_IN_RANGE; #endif #if (BOOT_NVM_HOOKS_ENABLE > 0) /* give the application a chance to operate on memory that is not by default supported * by this driver. */ result = NvmEraseHook(addr, len); /* process the return code */ if (result == BLT_NVM_OKAY) { /* address was within range of the additionally supported memory and succesfully * erased, so we are all done. */ return BLT_TRUE; } else if (result == BLT_NVM_ERROR) { /* address was within range of the additionally supported memory and attempted to be * erased, but an error occurred, so we can't continue. */ return BLT_FALSE; } #endif /* still here so the internal driver should try and perform the erase operation */ return FlashErase(addr, len); } /*** end of NvmErase ***/
/* * @brief Edit the bootloader state words (subnet and bootloader state) * @param state The value of the bootloader state * @return void */ void writeBootloaderState(unsigned long state) { uint32 tempBootloaderSubnet = bootloaderSubnet; // address of the last word (4 bytes) of state flash = 0x0003FFFC // address of last 1kb block = 0x0003FC00 FlashErase(BL_STATE_BLOCK_ADDRESS); FlashProgram(&state, BL_STATE_WORD_ADDRESS, sizeof(uint32)); // address of the second to the last word in state flash FlashProgram(&tempBootloaderSubnet, BL_STATE_SUBNET_ADDRESS, sizeof(uint32)); }
unsigned long massStorageWrite(void * drive,unsigned char *data,unsigned long blockNumber,unsigned long numberOfBlocks) { //FlashProgram((unsigned long*)data,USER_PROGRAM_START+counter,BLOCK_SIZE*numberOfBlocks); //counter+=BLOCK_SIZE*numberOfBlocks; #ifdef DEBUG UARTprintf("Write block: %d, no. of blocks: %d\n",blockNumber,numberOfBlocks); int i,j; for (j=0;j<BLOCK_SIZE*numberOfBlocks;j+=16){ for (i=0;i<16;i++) UARTprintf("%x ",data[j+i]); UARTprintf("\n"); } #endif if (blockNumber==0){ memcpy(bootSector,data,BOOT_LEN); } else if (blockNumber==1||blockNumber==2){ memcpy(fat,data,FAT_LEN); firmware_start_cluster=directory[58];//sometimes the system will move the firmware to a different cluster } else if (blockNumber==3){ memcpy(directory,data,DIRECTORY_LEN); } //new firmware is being uploaded else if (blockNumber>=FIRMWARE_START_SECTOR&&blockNumber<FIRMWARE_START_SECTOR+USER_PROGRAM_LENGTH/BLOCK_SIZE){ unsigned long address=(blockNumber-FIRMWARE_START_SECTOR)*BLOCK_SIZE+USER_PROGRAM_START; if (blockNumber==FIRMWARE_START_SECTOR){ for (counter=0;counter<239;counter++) FlashErase(USER_PROGRAM_START+counter*1024); } FlashProgram((unsigned long*)data,address,BLOCK_SIZE*numberOfBlocks); return BLOCK_SIZE*numberOfBlocks; } return BLOCK_SIZE*numberOfBlocks; }
int HexrecSign(int a) { int i,crc; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); i=FlashErase(_SIGN_PAGE); CRC_ResetDR(); crc=CRC_CalcBlockCRC((uint32_t *)a,0x8000); i |= FlashProgram32((int)_FW_CRC,crc); // vpisi !!! i |= FlashProgram32((int)_FW_SIZE,0x8000); i |= FlashProgram32((int)_FW_START,a); CRC_ResetDR(); crc=CRC_CalcBlockCRC((uint32_t *)_FW_SIZE,3); i |= FlashProgram32((int)_SIGN_CRC,crc); return i; }
//копирование целиком сектора sector_start в sector_end. sector_end //будет стёрт. Записывает данные по умолчанию (кроме ключей). BOOL FlashCopySectorFromScratch(int sector_start, int sector_end) { BOOL ret; uint32_t block_from_address; uint32_t block_where_address; block_from_address = sector_start * EE_SECTOR_SIZE; block_where_address = 0; current_crc = 0; //стирание сектора ret = FlashBlankCheck(sector_end); if(ret) { if(!FlashErase(sector_end)) { gsm_uart_printf_unsafe("FlashCopySectorFromScratch: cannot erase\r"); return DEF_FALSE; } } while(1) { memcpy(ee_buffer, (void *)block_from_address, EE_BLOCK_SIZE); FlashAddScratchData(block_where_address); ret = FlashWrite(sector_end, block_where_address, EE_BLOCK_SIZE, ee_buffer); if(!ret) { gsm_uart_printf_unsafe("FlashCopySectorFromScratch: cannot write\r"); return DEF_FALSE; } block_from_address += EE_BLOCK_SIZE; block_where_address += EE_BLOCK_SIZE; if(block_where_address >= EE_SECTOR_SIZE) { //Считаем текущим сектором тот, куда мы перенесли данные current_sector = sector_end; current_cnt = FlashNextCounter(); return DEF_TRUE; } } }
/** * Erases the indicated flash memory * \param startAddress Start location of flash memory that is to be erased * it must land on a 1KB boundry * \param eraseLength Length of data to erase in flash memory * it must land on a 1KB boundry, set to 0x0 to skip erasure **/ int32_t twe_eraseFlashRange(uint32_t startAddress, uint32_t eraseLength) { int32_t status = 0; uint32_t modCheck; uint32_t block; modCheck = startAddress - startAddress/0x400; modCheck = modCheck + eraseLength/0x400; ASSERT(modCheck == 0); if(eraseLength > 0x0) { for(block = 0; block < (eraseLength/0x400); block++) { status = FlashErase(startAddress + 0x400 * block) // Erases each 1KB block ASSERT(status == 0); } } return status; }
/********************************************************** **Name: SaveRFParameterToFlash **Function: Save RF parameter to flash **Input: none **Output: none **********************************************************/ void SaveRFParameterToFlash(void) { u8 i; FlashErase(EEPROM_FirstAddr); gb_RxData[0]=0x5A; gb_RxData[1]=gb_FreqBuf_Addr; gb_RxData[2]=gb_RateBuf_Addr; gb_RxData[3]=gb_PowerBuf_Addr; gb_RxData[4]=gb_FdevBuf_Addr; gb_RxData[5]=gb_BandBuf_Addr; gb_RxData[6]=gb_Modem_Addr; gb_RxData[8]=gb_SystemMode; FlashWrite(EEPROM_FirstAddr, gb_RxData); for(i=0; i<32; i++) gb_RxData[i] = 0; }
//***************************************************************************** // //! Erases an EEPROM page. //! //! This function is called to erase an EEPROM page. It verifies that the page //! has been erased by reading the status words of the page and confirming that //! they read as 0xFFFFFFFF. //! //! \param pucPageAddr is the beginning address of the EEPROM page to erase. //! //! \return A value of 0 indicates that the erase was successful. A non-zero //! value indicates a failure. // //***************************************************************************** static long PageErase(unsigned char* pucPageAddr) { unsigned char* pucAddr; // // Loop through the Flash pages within the specified EEPROM page. // for(pucAddr = pucPageAddr; pucAddr < (pucPageAddr + g_ulEEPROMPgSize); pucAddr += FLASH_ERASE_SIZE) { // // Erase the page. // if(FlashErase((unsigned long)pucAddr)) { // // The erase failed. // return(-1); } } // // Verify that the EEPROM page is indeed erased by checking that the // status words are 0xFFFFFFFF (much faster than reading the entire // page). It is assumed that if there was an error erasing the data // portion of the page, then it will be detected when verifying the // subsequent data writes in SoftEEPROMWrite(). // if(((*(unsigned long*)pucPageAddr) != ERASED_WORD) || ((*(unsigned long*)(pucPageAddr + 4)) != ERASED_WORD)) { // // The erase-verify failed. // return(-1); } // // The erase and erase-verify were successful, so return 0. // return(0); }
bool ImportData() { uint8_t data[DATA_SIZE]; if (!ReadRom(data)) { return false; } if (!ReadMem(data + ROM_SIZE)) { return false; } FlashErase((void*)DATA_AREA_START); FlashWrite((void*)DATA_AREA_START, data, sizeof(data)); return 0 == memcmp(data, _data, sizeof(data)); }
/****************************************************************** * Function: TopMenu * * Purpose: Generates the top level menu. * ******************************************************************/ static int TopMenu( void ) { char ch; /* Print the top-level menu to stdout */ while (1) { MenuBegin(" Memory Test Main Menu"); MenuItem( 'a', "Test RAM" ); MenuItem( 'b', "Test Flash"); ch = MenuEnd( 'a', 'b' ); switch(ch) { MenuCase('a',TestRam()); MenuCase('b',TestFlash(TEST)); MenuCase('e',FlashErase()); /* hidden option */ MenuCase('m',TestFlash(SHOWMAP)); /* hidden option */ } if (ch == 'q') break; } return (ch); }
//***************************************************************************** // // Erase the data storage area of flash. // //***************************************************************************** void FlashStoreErase(void) { unsigned long ulAddr; // // Inform user we are erasing // SetStatusText("ERASE", 0, "ERASING", 0); // // Loop through entire storage area and erase each page. // for(ulAddr = FLASH_STORE_START_ADDR; ulAddr < FLASH_STORE_END_ADDR; ulAddr += 0x400) { FlashErase(ulAddr); } // // Inform user the erase is done. // SetStatusText("SAVE", "ERASE", "COMPLETE", "PRESS <"); }
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; }
void Persistent::pageInit(uint8_t* address, uint32_t sequence) { FlashErase((uint32_t) address); FlashProgram(&sequence, (uint32_t) address, 4); }
void Persistent::pageErase(uint8_t* address) { FlashErase((uint32_t) address); }
int32_t FlashWrite(uint16_t *source, uint16_t *destination, uint32_t numBytes) { uint16_t first_sector; uint16_t last_sector; uint32_t sector_size; uint32_t sector_base; uint32_t sector_num; uint8_t *buffer; uint8_t *src; uint8_t *dst; uint32_t len=0; if((uint32_t)destination > max_flash_size) { printk("%s: %08X out of scope \n",__FUNCTION__, (uint32_t)destination); return -1; } src=(uint8_t *)source; dst=(uint8_t *)(logic2phy((uint32_t)destination)); /* get covered sector range */ first_sector = FlashSectNum((uint32_t)dst); last_sector = FlashSectNum((uint32_t)dst+numBytes -1); buffer=kmalloc(FLASH_MAX_RW_SIZE, GFP_KERNEL); for(sector_num=first_sector; sector_num<= last_sector; sector_num++ ) { /* each sector has different size and base address */ sector_size=FlashSectSize(sector_num); sector_base=FlashSectAddr(sector_num); /* prepare new sector contents */ memcpy((char *)buffer, (char *)sector_base, sector_size); if((uint32_t)dst+numBytes < sector_base+sector_size) { memcpy(&buffer[(uint32_t)dst-sector_base], src, numBytes); }else { len=sector_base+sector_size-(uint32_t)dst; memcpy(&buffer[sector_size-len], src, len); src+=len; dst+=len; numBytes-=len; } /* burn new sector contents */ FlashErase(sector_num, sector_num); #ifdef CONFIG_FLASH_SST39VF320X if(isSST) { __SSTFlashWrite((uint16_t *)buffer, (uint16_t *)sector_base, sector_size); } else { __FlashWrite((uint16_t *)buffer, (uint16_t *)sector_base, sector_size); } #else __FlashWrite((uint16_t *)buffer, (uint16_t *)sector_base, sector_size); #endif } kfree(buffer); return 0; }
/***************************************************************************** * * 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; }
/***************************************************************************** * * The purpose of this function is to illustrate how to use the XQspiPs * device driver in Linear mode. This function writes data to the serial * FLASH in QSPI mode and reads data in Linear QSPI mode. * * @param None. * * @return XST_SUCCESS if successful, else XST_FAILURE. * * @note None. * *****************************************************************************/ int LinearQspiFlashExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId) { int Status; u8 UniqueValue; int Count; int Page; XQspiPs_Config *QspiConfig; /* * Initialize the QSPI driver so that it's ready to use */ QspiConfig = XQspiPs_LookupConfig(QspiDeviceId); if (NULL == QspiConfig) { return XST_FAILURE; } Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig, QspiConfig->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Perform a self-test to check hardware build */ Status = XQspiPs_SelfTest(QspiInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Enable two flash memories on seperate buses */ XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_WRITE); /* * Set the QSPI device as a master and enable manual CS, manual start * and flash interface mode options and drive HOLD_B pin high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_MANUAL_START_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8); /* * Initialize the write buffer for a pattern to write to the FLASH * and the read buffer to zero so it can be verified after the read, the * test value that is added to the unique value allows the value to be * changed in a debug environment to guarantee */ for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test); } memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * Assert the FLASH chip select. */ XQspiPs_SetSlaveSelect(QspiInstancePtr); /* * Erase the flash sectors */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); /* * Write data to the two flash memories on seperate buses, starting from * TEST_ADDRESS. This is same as writing to a single flash memory. The * LQSPI controller takes care of splitting the data words and writing * them to the two flash memories. The user needs to take care of the * address translation */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) + TEST_ADDRESS) / 2, PAGE_SIZE, WRITE_CMD); } /* * Read from the two flash memories on seperate buses in LQSPI mode. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_QUAD_READ); Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS, MAX_DATA); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup a pointer to the start of the data that was read into the read * buffer and verify the data read is the data that was written */ for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (ReadBuffer[Count] != WriteBuffer[DATA_OFFSET + (Count % PAGE_SIZE)]) { return XST_FAILURE; } } /* * Set the QSPI device as a master and enable manual CS, manual start * and flash interface mode options and drive HOLD_B pin high. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); /* * Initialize the write buffer for a pattern to write to the FLASH * and the read buffer to zero so it can be verified after the read, the * test value that is added to the unique value allows the value to be * changed in a debug environment to guarantee */ for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE; Count++, UniqueValue++) { WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test); } memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); /* * Erase the flash sectors */ FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA); /* * Write data to the two flash memories on seperate buses, starting from * TEST_ADDRESS. This is same as writing to a single flash memory. The * LQSPI controller takes care of splitting the data words and writing * them to the two flash memories. The user needs to take care of the * address translation */ for (Page = 0; Page < PAGE_COUNT; Page++) { FlashWrite(QspiInstancePtr, ((Page * PAGE_SIZE) + TEST_ADDRESS) / 2, PAGE_SIZE, WRITE_CMD); } /* * Read from the two flash memories on seperate buses in LQSPI mode. */ XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_LQSPI_MODE_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION); XQspiPs_SetLqspiConfigReg(QspiInstancePtr, DUAL_QSPI_CONFIG_QUAD_READ); Status = XQspiPs_LqspiRead(QspiInstancePtr, ReadBuffer, TEST_ADDRESS, MAX_DATA); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup a pointer to the start of the data that was read into the read * buffer and verify the data read is the data that was written */ for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; Count++, UniqueValue++) { if (ReadBuffer[Count] != WriteBuffer[DATA_OFFSET + (Count % PAGE_SIZE)]) { return XST_FAILURE; } } return XST_SUCCESS; }
/*----------------------------------------------------------------------------- * Verarbeitung der Bustelegramme */ static void ProcessBus(UINT8 ret) { TBusMsgType msgType; UINT16 *pData; UINT16 wordAddr; BOOL rc; BOOL msgForMe = FALSE; if (ret == BUS_MSG_OK) { msgType = spRxBusMsg->type; switch (msgType) { case eBusDevReqReboot: case eBusDevReqUpdEnter: case eBusDevReqUpdData: case eBusDevReqUpdTerm: if (spRxBusMsg->msg.devBus.receiverAddr == MY_ADDR) { msgForMe = TRUE; } default: break; } if (msgForMe == FALSE) { return; } if (msgType == eBusDevReqReboot) { /* Über Watchdog Reset auslösen */ /* Watchdogtimeout auf kurzeste Zeit (14 ms) stellen */ cli(); wdt_enable(WDTO_15MS); /* warten auf Reset */ while (1); } else { switch (sFwuState) { case WAIT_FOR_UPD_ENTER_TIMEOUT: case WAIT_FOR_UPD_ENTER: if (msgType == eBusDevReqUpdEnter) { /* Applicationbereich des Flash löschen */ FlashErase(); /* Antwort senden */ SetMsg(eBusDevRespUpdEnter, spRxBusMsg->senderAddr); BusSend(&sTxBusMsg); sFwuState = WAIT_FOR_UPD_DATA; } break; case WAIT_FOR_UPD_DATA: if (msgType == eBusDevReqUpdData) { wordAddr = spRxBusMsg->msg.devBus.x.devReq.updData.wordAddr; pData = spRxBusMsg->msg.devBus.x.devReq.updData.data; /* Flash programmieren */ rc = FlashProgram(wordAddr, pData, sizeof(spRxBusMsg->msg.devBus.x.devReq.updData.data) / 2); /* Antwort senden */ SetMsg(eBusDevRespUpdData, spRxBusMsg->senderAddr); if (rc == TRUE) { /* Falls Programmierung des Block OK: empfangene wordAddr zurücksenden */ sTxBusMsg.msg.devBus.x.devResp.updData.wordAddr = wordAddr; } else { /* Problem bei Programmierung: -1 als wordAddr zurücksenden */ sTxBusMsg.msg.devBus.x.devResp.updData.wordAddr = -1; } BusSend(&sTxBusMsg); } else if (msgType == eBusDevReqUpdTerm) { /* programmiervorgang im Flash abschließen (falls erforderlich) */ rc = FlashProgramTerminate(); /* Antwort senden */ SetMsg(eBusDevRespUpdTerm, spRxBusMsg->senderAddr); if (rc == TRUE) { /* Falls Programmierung OK: success auf 1 setzen */ sTxBusMsg.msg.devBus.x.devResp.updTerm.success = 1; } else { /* Problem bei Programmierung: -1 als wordAddr zurücksenden */ sTxBusMsg.msg.devBus.x.devResp.updTerm.success = 0; } BusSend(&sTxBusMsg); } break; default: break; } } } }
/***************************************************************************** * * 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; }
/***************************************************************************** * * 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 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; }
//***************************************************************************** // // This is the main application entry function. // //***************************************************************************** int main(void) { uint32_t ui32TxCount; uint32_t ui32RxCount; //uint32_t ui32Loop; // // Enable lazy stacking for interrupt handlers. This allows floating-point // instructions to be used within interrupt handlers, but at the expense of // extra stack usage. // ROM_FPULazyStackingEnable(); // // Set the clocking to run from the PLL at 50MHz // #if 1 ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Configure the required pins for USB operation. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); ROM_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_5 | GPIO_PIN_4); //ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / 100); /* This code taken from: http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/311237.aspx */ #else #include "hw_nvic.h" FlashErase(0x00000000); ROM_IntMasterDisable(); ROM_SysTickIntDisable(); ROM_SysTickDisable(); uint32_t ui32SysClock; ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); ui32SysClock = ROM_SysCtlClockGet(); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); ROM_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5); ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / 100); HWREG(NVIC_DIS0) = 0xffffffff; HWREG(NVIC_DIS1) = 0xffffffff; HWREG(NVIC_DIS2) = 0xffffffff; HWREG(NVIC_DIS3) = 0xffffffff; HWREG(NVIC_DIS4) = 0xffffffff; int ui32Addr; for(ui32Addr = NVIC_PRI0; ui32Addr <= NVIC_PRI34; ui32Addr+=4) { HWREG(ui32Addr) = 0; } HWREG(NVIC_SYS_PRI1) = 0; HWREG(NVIC_SYS_PRI2) = 0; HWREG(NVIC_SYS_PRI3) = 0; ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0); ROM_SysCtlUSBPLLEnable(); ROM_SysCtlDelay(ui32SysClock*2 / 3); ROM_IntMasterEnable(); ROM_UpdateUSB(0); while(1) { } #endif #define BOOTLOADER_TEST 0 #if BOOTLOADER_TEST #include "hw_nvic.h" //ROM_UpdateUART(); // May need to do the following here: // 0. See if this will cause bootloader to start //ROM_FlashErase(0); //ROM_UpdateUSB(0); #define SYSTICKS_PER_SECOND 100 uint32_t ui32SysClock = ROM_SysCtlClockGet(); ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICKS_PER_SECOND); ROM_SysTickIntEnable(); ROM_SysTickEnable(); //USBDCDTerm(0); // Disable all interrupts ROM_IntMasterDisable(); ROM_SysTickIntDisable(); ROM_SysTickDisable(); HWREG(NVIC_DIS0) = 0xffffffff; HWREG(NVIC_DIS1) = 0xffffffff; HWREG(NVIC_DIS2) = 0xffffffff; HWREG(NVIC_DIS3) = 0xffffffff; HWREG(NVIC_DIS4) = 0xffffffff; int ui32Addr; for(ui32Addr = NVIC_PRI0; ui32Addr <= NVIC_PRI34; ui32Addr+=4) { HWREG(ui32Addr) = 0; } HWREG(NVIC_SYS_PRI1) = 0; HWREG(NVIC_SYS_PRI2) = 0; HWREG(NVIC_SYS_PRI3) = 0; // 1. Enable USB PLL //ROM_SysCtlUSBPLLEnable(); // 2. Enable USB controller ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0); //USBClockEnable(USB0_BASE, 8, USB_CLOCK_INTERNAL); //HWREG(USB0_BASE + USB_O_CC) = (8 - 1) | USB_CLOCK_INTERNAL; ROM_SysCtlUSBPLLEnable(); // 3. Enable USB D+ D- pins // 4. Activate USB DFU ROM_SysCtlDelay(ui32SysClock * 2 / 3); ROM_IntMasterEnable(); // Re-enable interrupts at NVIC level ROM_UpdateUSB(0); // 5. Should never get here since update is in progress #endif // BOOTLOADER_TEST // // Enable the GPIO port that is used for the on-board LED. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // gjs Our board uses GPIOB for LEDs // gjs original ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // // Enable the GPIO pins for the LED (PF2 & PF3). // ROM_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0|GPIO_PIN_1); // gjs original ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3|GPIO_PIN_2); // // Not configured initially. // g_bUSBConfigured = false; // // Enable the UART that we will be redirecting. // ROM_SysCtlPeripheralEnable(USB_UART_PERIPH); // // Enable and configure the UART RX and TX pins // ROM_SysCtlPeripheralEnable(TX_GPIO_PERIPH); ROM_SysCtlPeripheralEnable(RX_GPIO_PERIPH); ROM_GPIOPinTypeUART(TX_GPIO_BASE, TX_GPIO_PIN); ROM_GPIOPinTypeUART(RX_GPIO_BASE, RX_GPIO_PIN); // // TODO: Add code to configure handshake GPIOs if required. // // // Set the default UART configuration. // ROM_UARTConfigSetExpClk(USB_UART_BASE, ROM_SysCtlClockGet(), DEFAULT_BIT_RATE, DEFAULT_UART_CONFIG); ROM_UARTFIFOLevelSet(USB_UART_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8); // // Configure and enable UART interrupts. // ROM_UARTIntClear(USB_UART_BASE, ROM_UARTIntStatus(USB_UART_BASE, false)); ROM_UARTIntEnable(USB_UART_BASE, (UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE | UART_INT_RT | UART_INT_TX | UART_INT_RX)); // // Enable the system tick. // #if 0 ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICKS_PER_SECOND); ROM_SysTickIntEnable(); ROM_SysTickEnable(); #endif // // Initialize the transmit and receive buffers. // USBBufferInit(&g_sTxBuffer); USBBufferInit(&g_sRxBuffer); // // Set the USB stack mode to Device mode with VBUS monitoring. // USBStackModeSet(0, eUSBModeDevice, 0); // // Pass our device information to the USB library and place the device // on the bus. // USBDCDCInit(0, &g_sCDCDevice); // // Clear our local byte counters. // ui32RxCount = 0; ui32TxCount = 0; // // Enable interrupts now that the application is ready to start. // ROM_IntEnable(USB_UART_INT); // Enable FreeRTOS mainA(); // FreeRTOS. Will not return #if 0 // // Main application loop. // while(1) { // // Have we been asked to update the status display? // if(g_ui32Flags & COMMAND_STATUS_UPDATE) { // // Clear the command flag // ROM_IntMasterDisable(); g_ui32Flags &= ~COMMAND_STATUS_UPDATE; ROM_IntMasterEnable(); } // // Has there been any transmit traffic since we last checked? // if(ui32TxCount != g_ui32UARTTxCount) { // // Turn on the Green LED. // // gjs ROM_UARTCharPutNonBlocking(USB_UART_BASE, 'b'); #if 1 if (ui32TxCount & 1) { GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_PIN_0); } else { GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0); } #else if (1 || g_ui32UARTTxCount & 0x01) { GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3); } else { //GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0); } // // Delay for a bit. // for(uint32_t ui32Loop = 0; ui32Loop < 150000; ui32Loop++) { } // // Turn off the Green LED. // GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0); #endif // // Take a snapshot of the latest transmit count. // ui32TxCount = g_ui32UARTTxCount; } // // Has there been any receive traffic since we last checked? // if(ui32RxCount != g_ui32UARTRxCount) { // // Turn on the Blue LED. // #if 1 if (ui32RxCount & 1) { GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, GPIO_PIN_1); } else { GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, 0); } #else GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); // // Delay for a bit. // for(uint32_t ui32Loop = 0; ui32Loop < 150000; ui32Loop++) { } // // Turn off the Blue LED. // GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); #endif // // Take a snapshot of the latest receive count. // ui32RxCount = g_ui32UARTRxCount; } } #endif }
/***************************************************************************** * * 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; }
//***************************************************************************** // //! Writes a new parameter block to flash. //! //! \param pucBuffer is the address of the parameter block to be written to //! flash. //! //! This function will write a parameter block to flash. Saving the new //! parameter blocks involves three steps: //! //! - Setting the sequence number such that it is one greater than the sequence //! number of the latest parameter block in flash. //! - Computing the checksum of the parameter block. //! - Writing the parameter block into the storage immediately following the //! latest parameter block in flash; if that storage is at the start of an //! erase block, that block is erased first. //! //! By this process, there is always a valid parameter block in flash. If //! power is lost while writing a new parameter block, the checksum will not //! match and the partially written parameter block will be ignored. This is //! what makes this fault-tolerant. //! //! Another benefit of this scheme is that it provides wear leveling on the //! flash. Since multiple parameter blocks fit into each erase block of flash, //! and multiple erase blocks are used for parameter block storage, it takes //! quite a few parameter block saves before flash is re-written. //! //! \return None. // //***************************************************************************** void FlashPBSave(unsigned char *pucBuffer) { unsigned char *pucNew; unsigned long ulIdx, ulSum; // // Check the arguments. // ASSERT(pucBuffer != (void *)0); // // See if there is a valid parameter block in flash. // if(g_pucFlashPBCurrent) { // // Set the sequence number to one greater than the most recent // parameter block. // pucBuffer[0] = g_pucFlashPBCurrent[0] + 1; // // Try to write the new parameter block immediately after the most // recent parameter block. // pucNew = g_pucFlashPBCurrent + g_ulFlashPBSize; if(pucNew == g_pucFlashPBEnd) { pucNew = g_pucFlashPBStart; } } else { // // There is not a valid parameter block in flash, so set the sequence // number of this parameter block to zero. // pucBuffer[0] = 0; // // Try to write the new parameter block at the beginning of the flash // space for parameter blocks. // pucNew = g_pucFlashPBStart; } // // Compute the checksum of the parameter block to be written. // for(ulIdx = 0, ulSum = 0; ulIdx < g_ulFlashPBSize; ulIdx++) { ulSum -= pucBuffer[ulIdx]; } // // Store the checksum into the parameter block. // pucBuffer[1] += ulSum; // // Look for a location to store this parameter block. This infinite loop // will be explicitly broken out of when a valid location is found. // while(1) { // // See if this location is at the start of an erase block. // if(((unsigned long)pucNew & 1023) == 0) { // // Erase this block of the flash. This does not assume that the // erase succeeded in case this block of the flash has become bad // through too much use. Given the extremely low frequency that // the parameter blocks are written, this will likely never fail. // But, that assumption is not made in order to be safe. // FlashErase((unsigned long)pucNew); } // // Loop through this portion of flash to see if is all ones (i.e. it // is an erased portion of flash). // for(ulIdx = 0; ulIdx < g_ulFlashPBSize; ulIdx++) { if(pucNew[ulIdx] != 0xff) { break; } } // // If all bytes in this portion of flash are ones, then break out of // the loop since this is a good location for storing the parameter // block. // if(ulIdx == g_ulFlashPBSize) { break; } // // Increment to the next parameter block location. // pucNew += g_ulFlashPBSize; if(pucNew == g_pucFlashPBEnd) { pucNew = g_pucFlashPBStart; } // // If every possible location has been checked and none are valid, then // it will not be possible to write this parameter block. Simply // return without writing it. // if((g_pucFlashPBCurrent && (pucNew == g_pucFlashPBCurrent)) || (!g_pucFlashPBCurrent && (pucNew == g_pucFlashPBStart))) { return; } } // // Write this parameter block to flash. // FlashProgram((unsigned long *)pucBuffer, (unsigned long)pucNew, g_ulFlashPBSize); // // Compare the parameter block data to the data that should now be in // flash. Return if any of the data does not compare, leaving the previous // parameter block in flash as the most recent (since the current parameter // block failed to properly program). // for(ulIdx = 0; ulIdx < g_ulFlashPBSize; ulIdx++) { if(pucNew[ulIdx] != pucBuffer[ulIdx]) { return; } } // // The new parameter block becomes the most recent parameter block. // g_pucFlashPBCurrent = pucNew; }
//копирует сектор из block_start в block_end, заменяя данные, начиная с адреса where_to_replace данными data //записывая data_size байт BOOL FlashCopySectorAndReplaceData(int sector_start, int sector_end, int where_to_replace, unsigned char *data, int data_size) { BOOL ret; int i; uint32_t block_from_address; uint32_t block_where_address; block_from_address = sector_start * EE_SECTOR_SIZE; block_where_address = 0; current_crc = 0; //стирание сектора ret = FlashBlankCheck(sector_end); if(ret) { if(!FlashErase(sector_end)) { gsm_uart_printf_unsafe("FlashCopySectorAndReplaceData: cannot erase\r"); return DEF_FALSE; } } while(1) { memcpy(ee_buffer, (void *)block_from_address, EE_BLOCK_SIZE); //если следующий блок начинается с адреса после адреса where_to_replace, то нужно //заменять данные уже в этом блоке if(((block_where_address + EE_BLOCK_SIZE) > where_to_replace) && (block_where_address <= where_to_replace) && data_size) { i = (where_to_replace - block_where_address) % EE_BLOCK_SIZE; while((i < EE_BLOCK_SIZE) && data_size) { ee_buffer[i] = *data; data_size--; data++; where_to_replace++; i++; } } FlashAddEepromData(block_where_address); ret = FlashWrite(sector_end, block_where_address, EE_BLOCK_SIZE, ee_buffer); if(!ret) { gsm_uart_printf_unsafe("FlashCopySectorAndReplaceData: cannot write\r"); return DEF_FALSE; } block_from_address += EE_BLOCK_SIZE; block_where_address += EE_BLOCK_SIZE; if(block_where_address >= EE_SECTOR_SIZE) { //Считаем текущим сектором тот, куда мы перенесли данные current_sector = sector_end; current_cnt = FlashNextCounter(); return DEF_TRUE; } } }
/***************************************************************************** * * 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; }
/* erase flash */ FlashError_t BDMFlashErase( void ) { return (FlashErase( &Flash )); }