#include "SPI_Flash.h" #include "SPI.h" #include "BoardCfg.h" unsigned char mSPIFlashBaudrate; unsigned char mSPIFlashHighSpeedBaudrate; unsigned char mFlashSectorBuffer[SPI_FLASH_SECTOR_SIZE]; unsigned int mSPIFlashOK; int InitSPIFlash() { FLASH_SS_PIN = 1; mSPIFlashBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 25000000); // mSPIFlashHighSpeedBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 50000000); mSPIFlashHighSpeedBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 35000000); mSPIFlashOK = 0; } int SPIFlashCheckAndConfigure() { if(SPIFlashCheckChipID() == RET_OK) { SPIFlashWriteEnable(); FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_WRITE_STATUS_REG,mSPIFlashHighSpeedBaudrate); SPITransaction(0x00,mSPIFlashHighSpeedBaudrate); //Configure for write enable the whole memory FLASH_SS_PIN = 1; SPIFlashReadStatusReg(1); mSPIFlashOK = 1; printf("SPI Flash configured\n"); return RET_OK; } mSPIFlashOK = 0; printf("ERROR: SPI Flash not detected\n"); return RET_ERROR; } int SPIFlashIsPresent() { return mSPIFlashOK; } int SPIFlashWriteEnable() { FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_WRITE_ENABLE,mSPIFlashHighSpeedBaudrate); FLASH_SS_PIN = 1; return RET_OK; } unsigned char SPIFlashReadStatusReg(int print) { unsigned char result; FLASH_SS_PIN = 0; result = SPITransaction(SPI_FLASH_READ_STATUS_REG,mSPIFlashBaudrate); result = SPITransaction(0x00,mSPIFlashBaudrate); //get data FLASH_SS_PIN = 1; if(print) { printf("Flash status register : 0x%x\n",result); } return result; } int SPIFlashCheckBusy() { unsigned char status = SPIFlashReadStatusReg(0); if((status & SPI_FLASH_BUSY_MASK) != 0) { return 1; } return 0; } int SPIFlashCheckChipID() { unsigned char VendorID, ChipID; FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_READ_ID,mSPIFlashBaudrate); SPITransaction(0x00,mSPIFlashBaudrate); SPITransaction(0x00,mSPIFlashBaudrate); SPITransaction(0x00,mSPIFlashBaudrate); //Vendor address VendorID = SPITransaction(0x00,mSPIFlashBaudrate); //Vendor ID, should be 0xBF ChipID = SPITransaction(0x00,mSPIFlashBaudrate); //Device ID, should be 0x41 FLASH_SS_PIN = 1; if(VendorID != SPI_FLASH_VENDOR_ID || ChipID != SPI_FLASH_CHIP_ID) { printf("SPI Flash detection FAILED. Vendor: 0x%x, Chip ID: 0x%x\n",VendorID,ChipID); return RET_ERROR; } printf("SPI Flash detected. Vendor: 0x%x, Chip ID: 0x%x\n",VendorID,ChipID); return RET_OK; } int SPIFlashReadBuffer(unsigned char *Buf, int Size, int StartAddress) { if(StartAddress + Size - 1 > SPI_FLASH_MAX_ADDRESS) { return RET_ERROR; } FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_HI_SPEED_READ,mSPIFlashBaudrate); SPITransaction(((StartAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate); SPITransaction(((StartAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate); SPITransaction((StartAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate); SPITransaction((0x00),mSPIFlashHighSpeedBaudrate); //Chip requires a dummy read in high speed int i; for(i = 0; i < Size; i++) { unsigned char tmp; tmp =SPITransaction(0xDE,mSPIFlashHighSpeedBaudrate); *Buf++ = tmp; // *Buf++ = SPITransaction(0xDE,mSPIFlashHighSpeedBaudrate); } FLASH_SS_PIN = 1; return RET_OK; } int SPIFlashEraseSector(int SectorAddress) { if(SectorAddress % SPI_FLASH_SECTOR_SIZE != 0) //Sectors are aligned on 0x1000 { return RET_ERROR; } SPIFlashWriteEnable(); FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_4KB_SECOTR_ERASE,mSPIFlashHighSpeedBaudrate); SPITransaction(((SectorAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate); SPITransaction(((SectorAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate); SPITransaction((SectorAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate); FLASH_SS_PIN = 1; SectorAddress++; while( SPIFlashCheckBusy() == true); //SPIFlashWriteEnable(); return RET_OK; } int SPIFlashErase64KSector(int SectorAddress, int Blocking) { if(SectorAddress % SPI_FLASH_64K_SECTOR_SIZE != 0) //Sectors are aligned on 0x1000 { return RET_ERROR; } if((SectorAddress + SPI_FLASH_64K_SECTOR_SIZE - 1) > SPI_FLASH_MAX_ADDRESS) { return RET_ERROR; } SPIFlashWriteEnable(); FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_64KB_BLOCK_ERASE,mSPIFlashHighSpeedBaudrate); SPITransaction(((SectorAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate); SPITransaction(((SectorAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate); SPITransaction((SectorAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate); FLASH_SS_PIN = 1; if(Blocking != 0) { while( SPIFlashCheckBusy() == true); // SPIFlashWriteEnable(); } return RET_OK; } int SPIFlashWriteSectorWorkingBuffer(int SectorAddress, int Erase) { if(SectorAddress % SPI_FLASH_SECTOR_SIZE != 0) //Sectors are aligned on 0x1000 { return RET_ERROR; } if(Erase == 1) { SPIFlashEraseSector(SectorAddress); } unsigned char *DataPtr = &mFlashSectorBuffer[0]; int j; for(j = 0; j < SPI_FLASH_SECTOR_SIZE; j++) { unsigned char curbyte; curbyte = *DataPtr; SPIFlashWriteEnable(); char Add1, Add2, Add3; Add1 = (unsigned char)((SectorAddress & 0xFF0000) >> 16); Add2 = ((unsigned char)((SectorAddress & 0x00FF00) >> 8)); Add3 = ((unsigned char)(SectorAddress & 0x0000FF)); int t; t = 0; FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_BYTE_PROGRAM,mSPIFlashHighSpeedBaudrate); // SPITransaction((unsigned char)((SectorAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate); // SPITransaction((unsigned char)((SectorAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate); // SPITransaction((unsigned char)(SectorAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate); SPITransaction(Add1,mSPIFlashHighSpeedBaudrate); SPITransaction(Add2,mSPIFlashHighSpeedBaudrate); SPITransaction(Add3,mSPIFlashHighSpeedBaudrate); SPITransaction(curbyte,mSPIFlashHighSpeedBaudrate); // SPITransaction(*DataPtr,mSPIFlashHighSpeedBaudrate); FLASH_SS_PIN = 1; DataPtr++; SectorAddress++; while( SPIFlashCheckBusy() == true); } return RET_OK; } int SPIFlashWriteByte(unsigned int ByteAddress, char byte, int blocking) { if(ByteAddress > SPI_FLASH_MAX_ADDRESS) { return RET_ERROR; } SPIFlashWriteEnable(); FLASH_SS_PIN = 0; SPITransaction(SPI_FLASH_BYTE_PROGRAM,mSPIFlashHighSpeedBaudrate); SPITransaction(((ByteAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate); SPITransaction(((ByteAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate); SPITransaction((ByteAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate); SPITransaction(byte,mSPIFlashHighSpeedBaudrate); FLASH_SS_PIN = 1; if(blocking) { while( SPIFlashCheckBusy() == true); } return RET_OK; } //int SPIFlashEraseSectorForWrite(unsigned char StartAddress, int Size) //{ // //First, let's determine which sector to erase. // // int NbSectors = 1; // int FirstSector = StartAddress / 0x1000; // int LastSector = (StartAddress + Size) / 0x1000; // // if(LastSector > FirstSector) // { // NbSectors = LastSector - FirstSector; // } // // int i; // for(i = FirstSector; i < LastSector; i++ ) //Erase each sector one by one // { // // } // //} //int SPIFlashWriteBuffer(unsigned char *Buf, int Size, int StartAddress) //{ // //First, we need to determine if the data overlaps or uses more than one sector // //First, let's determine which sector to erase. // int EndAddress = StartAddress + Size - 1; // if(EndAddress > SPI_FLASH_MAX_ADDRESS) // { // return RET_ERROR; // } // // int NbSectors = 1; // int FirstSector = StartAddress / SPI_FLASH_SECTOR_SIZE; // int LastSector = EndAddress / SPI_FLASH_SECTOR_SIZE; // // if(LastSector > FirstSector) // { // NbSectors = LastSector - FirstSector + 1; // } // // int i; // int FlashAddress = StartAddress; // int CurSector = FirstSector; // for(i = 0; i < NbSectors; i++ ) //Read, erase and write each sector one by one // { // //first we need to backup the data outside our buffer. // //TODO: optimize // int SectorStartAddress = CurSector++ * SPI_FLASH_SECTOR_SIZE; // int SectorEndAddress = SectorStartAddress + SPI_FLASH_SECTOR_SIZE - 1; // if(SectorEndAddress > EndAddress) // { // SectorEndAddress = EndAddress; // } // // SPIFlashReadBuffer(mFlashSectorBuffer,SPI_FLASH_SECTOR_SIZE,SectorStartAddress); //Get local RAM buffer of the sector // // //Update the data to write. // int RAMAddress = FlashAddress - SectorStartAddress; // int RAMSectorSize = SectorEndAddress - FlashAddress + 1; // FlashAddress += RAMSectorSize; // // unsigned char* RAMPtr = &mFlashSectorBuffer[RAMAddress]; // int j; // for(j = 0; j < RAMSectorSize; j++) // { // *RAMPtr++ = *Buf++; // } // // int SectorAddress = SectorStartAddress; // RAMPtr = mFlashSectorBuffer; // // for(j = 0; j < SPI_FLASH_SECTOR_SIZE; j++) // { // SPIFlashWriteEnable(); // // FLASH_SS_PIN = 0; // SPITransaction(SPI_FLASH_BYTE_PROGRAM,mSPIFlashHighSpeedBaudrate); // SPITransaction(((SectorAddress & 0xFF0000) >> 16),mSPIFlashBaudrate); // SPITransaction(((SectorAddress & 0x00FF00) >> 8),mSPIFlashBaudrate); // SPITransaction((SectorAddress & 0x0000FF),mSPIFlashBaudrate); // SPITransaction(*RAMPtr++,mSPIFlashBaudrate); // FLASH_SS_PIN = 1; // // SectorAddress++; // // while( SPIFlashCheckBusy() == true); // } // } //} int SPIFlashWriteBuffer(unsigned char *Buf, int Size, int StartAddress) { int CurDataFlashAddress, DataFlashEndAddress; char *DataBufPtr, *WorkPagePtr; int WriteFinished; //Init stuff WriteFinished = 0; DataFlashEndAddress = StartAddress + Size; //Start + size means the data at "DataFlashEndAddress" should not be written. CurDataFlashAddress = StartAddress; DataBufPtr = Buf; if(DataFlashEndAddress > SPI_FLASH_MAX_ADDRESS) { return RET_ERROR; } while(WriteFinished == 0) { //Determine the current sector start address. int SectorStartAddress; SectorStartAddress = ((CurDataFlashAddress / SPI_FLASH_SECTOR_SIZE) * SPI_FLASH_SECTOR_SIZE); //Weird but it works //Load the sector in RAM working buffer if(SPIFlashReadBuffer(mFlashSectorBuffer,SPI_FLASH_SECTOR_SIZE,SectorStartAddress) != RET_OK) { return RET_ERROR; } //Set the working buffer pointer to the right value. WorkPagePtr = &mFlashSectorBuffer[CurDataFlashAddress - SectorStartAddress]; //Modify the working buffer with data to write. int SectorFinished = 0; while(SectorFinished == 0) { *WorkPagePtr++ = *DataBufPtr++; CurDataFlashAddress++; //Are we at the end of the buffer to write? if(CurDataFlashAddress == DataFlashEndAddress) { SectorFinished = 1; WriteFinished = 1; // SPIFlashEraseSector(SectorStartAddress); SPIFlashWriteSectorWorkingBuffer(SectorStartAddress,1); break; } else if(CurDataFlashAddress % SPI_FLASH_SECTOR_SIZE == 0) //Are we at the beginning of the next sector? { SectorFinished = 1; // SPIFlashEraseSector(SectorStartAddress); SPIFlashWriteSectorWorkingBuffer(SectorStartAddress,1); break; } } } return 1; }