423 lines
12 KiB
C

#include "SPI_Flash.h"
#include "SPI.h"
#include "BoardCfg.h"
unsigned char mSPIFlashBaudrate;
unsigned char mSPIFlashHighSpeedBaudrate;
unsigned char mFlashSectorBuffer[SPI_FLASH_SECTOR_SIZE];
int InitSPIFlash()
{
FLASH_SS_PIN = 1;
mSPIFlashBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 25000000);
// mSPIFlashHighSpeedBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 50000000);
mSPIFlashHighSpeedBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 35000000);
}
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);
printf("SPI Flash configured\n");
return RET_OK;
}
printf("ERROR: SPI Flash not detected\n");
return RET_ERROR;
}
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;
}