📄 m25p64.c
字号:
//////////////////////////////////////////////////////////////
ERROR_CODE ReadData( unsigned long ulStart, long lCount, long lStride, int *pnData )
{
unsigned long ShiftValue;
char dummyread, *cnData,ReadValue;
int i;
cnData = (char *)pnData; // Pointer cast to be able to increment byte wise
// Start SPI interface
SetupSPI( (COMMON_SPI_SETTINGS|TIMOD01) );
*pSPI_TDBR = SPI_READ; // Send the read command to SPI device
Wait_For_SPIF(); // Wait until the instruction has been sent
ShiftValue = (ulStart >> 16); // Send the highest byte of the 24 bit address at first
*pSPI_TDBR = ShiftValue; // Send the byte to the SPI device
Wait_For_SPIF(); // Wait until the instruction has been sent
ShiftValue = (ulStart >> 8); // Send the middle byte of the 24 bit address at second
*pSPI_TDBR = ShiftValue; // Send the byte to the SPI device
Wait_For_SPIF(); // Wait until the instruction has been sent
*pSPI_TDBR = ulStart; // Send the lowest byte of the 24 bit address finally
Wait_For_SPIF(); // Wait until the instruction has been sent
dummyread = *pSPI_RDBR; // Read dummy to empty the receive register
// After the SPI device address has been placed on the MOSI pin the data can be
// received on the MISO pin.
for (i=0; i<lCount; i++)
{
*pSPI_TDBR = 0; //send dummy
Wait_For_SPIF(); //wait until the data has been sent
ReadValue = *pSPI_RDBR; //read
*cnData = ReadValue; // Store the value received in the buffer.
cnData++; // Increment the pointer of the buffer to store the next value
}
SPI_OFF(); // Turn off the SPI
for(i=0; i<1000; i++)
{
asm("nop;");
}
return NO_ERR;
}
//////////////////////////////////////////////////////////////
// ERROR_CODE EraseFlash()
//
// Sends an "erase all" command to the flash.
//
//////////////////////////////////////////////////////////////
ERROR_CODE EraseFlash()
{
ERROR_CODE ErrorCode = NO_ERR;
//A write enable instruction must previously have been executed
SendSingleCommand(SPI_WREN);
//The status register will be polled to check the write enable latch "WREN"
ErrorCode = Wait_For_WEL();
if( POLL_TIMEOUT == ErrorCode )
{
return ErrorCode;
}
else
//The bulk erase instruction will erase the whole flash
SendSingleCommand(SPI_BE);
// Erasing the whole flash will take time, so the following bit must be polled.
//The status register will be polled to check the write in progress bit "WIP"
ErrorCode = Wait_For_Status(WIP);
return ErrorCode;
}
//////////////////////////////////////////////////////////////
// ERROR_CODE EraseBlock()
//
// Sends an "erase block" command to the flash.
//
//////////////////////////////////////////////////////////////
ERROR_CODE EraseBlock( int nBlock )
{
unsigned long ulSectorOff = 0x0, ShiftValue;
ERROR_CODE ErrorCode = NO_ERR;
// if the block is invalid just return
if ( (nBlock < 0) || (nBlock > AFP_NumSectors) )
{
ErrorCode = INVALID_BLOCK; // tells us if there was an error erasing flash
return ErrorCode;
}
// figure out the offset of the block in flash
if ( (nBlock >= 0) && (nBlock < NUM_SECTORS) )
{
ulSectorOff = (nBlock * AFP_SectorSize1);
}
else
{
ErrorCode = INVALID_BLOCK; // tells us if there was an error erasing flash
return ErrorCode;
}
// A write enable instruction must previously have been executed
SendSingleCommand(SPI_WREN);
//The status register will be polled to check the write enable latch "WREN"
ErrorCode = Wait_For_WEL();
if( POLL_TIMEOUT == ErrorCode )
{
return ErrorCode;
}
else
//Turn on the SPI to send single commands
SetupSPI( (COMMON_SPI_SETTINGS|TIMOD01) );
// Send the erase block command to the flash followed by the 24 address
// to point to the start of a sector.
*pSPI_TDBR = SPI_SE;
ShiftValue = (ulSectorOff >> 16); // Send the highest byte of the 24 bit address at first
Wait_For_SPIF(); // Wait until the instruction has been sent
*pSPI_TDBR = ShiftValue;
Wait_For_SPIF(); // Wait until the instruction has been sent
ShiftValue = (ulSectorOff >> 8); // Send the middle byte of the 24 bit address at second
*pSPI_TDBR = ShiftValue;
Wait_For_SPIF(); // Wait until the instruction has been sent
*pSPI_TDBR = ulSectorOff; // Send the lowest byte of the 24 bit address finally
Wait_For_SPIF(); // Wait until the instruction has been sent
//Turns off the SPI
SPI_OFF();
Wait_For_SPIF(); // Wait until the instruction has been sent
// Poll the status register to check the Write in Progress bit
// Sector erase takes time
ErrorCode = Wait_For_Status(WIP);
// block erase should be complete
return ErrorCode;
}
//////////////////////////////////////////////////////////////
// ERROR_CODE GetCodes()
//
// Sends an "auto select" command to the flash which will allow
// us to get the manufacturer and device codes.
//
//////////////////////////////////////////////////////////////
ERROR_CODE GetCodes()
{
// The ST M25P64 does not support manufacturer and device codes.
return NO_ERR;
}
//////////////////////////////////////////////////////////////
// ERROR_CODE GetSectorNumber()
//
// Gets a sector number based on the offset.
//
// In the flash programmer plug-in a sector can be chosen
// and than be erased.
//////////////////////////////////////////////////////////////
ERROR_CODE GetSectorNumber( unsigned long ulOffset, int *pnSector )
{
int nSector = 0;
ERROR_CODE ErrorCode = NO_ERR;
if(ulOffset > (NUM_SECTORS*0x10000 -1)){
ErrorCode = INVALID_SECTOR;
return ErrorCode;
}
nSector = (int)ulOffset/0x10000;
*pnSector = nSector;
// ok
return ErrorCode;
}
//////////////////////////////////////////////////////////////
// ERROR_CODE ResetFlash()
//
// This function sends a Write Disable Command to the SPI device
// After that it checks the Write Enable Latch.
//
//////////////////////////////////////////////////////////////
ERROR_CODE ResetFlash()
{
char status_register = 0;
ERROR_CODE ErrorCode = NO_ERR;
SendSingleCommand(SPI_WRDI);
ErrorCode = Wait_For_Status(WEL);
// reset should be complete
return ErrorCode;
}
//////////////////////////////////////////////////////////////
// int ReadStatusRegister(void)
//
// Returns the 8-bit value of the status register.
// Inputs - none
// returns- second location of status_register[2],
// first location is garbage.
// Core sends the command
//
//////////////////////////////////////////////////////////////
char ReadStatusRegister(void)
{
char dummyread, status_register = 0;
int n;
SetupSPI( (COMMON_SPI_SETTINGS|TIMOD01) ); // Turn on the SPI
*pSPI_TDBR = SPI_RDSR; //send instruction to read status register
Wait_For_SPIF(); //wait until the instruction has been sent
dummyread = *pSPI_RDBR; //read dummy to empty the receive register
*pSPI_TDBR = 0; //send dummy to receive the status register
Wait_For_SPIF(); //wait until the data has been sent
status_register = *pSPI_RDBR; //read the status register
SPI_OFF(); // Turn off the SPI
for(n=0; n<1000; n++)
{
asm("nop;");
}
return status_register;
}
//////////////////////////////////////////////////////////////
// void Wait_For_SPIF(void)
//
// Polls the SPIF (SPI single word transfer complete) bit
// of SPISTAT until the transfer is complete.
// Inputs - none
// returns- none
//
//////////////////////////////////////////////////////////////
void Wait_For_SPIF(void)
{
int n;
unsigned short dummyread;
for(n=0; n<1000; n++)
{
asm("nop;");
}
while(1)
{
unsigned short iTest = *pSPI_STAT;
if( (iTest & SPIF) )
{
break;
}
}
dummyread = *pSPI_RDBR; /*read dummy to empty the receive register */
}
//////////////////////////////////////////////////////////////
// Wait_For_WEL(void)
//
// Polls the WEL (Write Enable Latch) bit of the Flash's status
// register.
// Inputs - none
// returns- none
//
//////////////////////////////////////////////////////////////
ERROR_CODE Wait_For_WEL(void)
{
int n, i;
char status_register = 0;
ERROR_CODE ErrorCode = NO_ERR; // tells us if there was an error erasing flash
for(i = 0; i < 35; i++)
{
status_register = ReadStatusRegister();
if( (status_register & WEL) )
{
ErrorCode = NO_ERR; // tells us if there was an error erasing flash
break;
}
for(n=0; n<1000; n++)
asm("nop;");
ErrorCode = POLL_TIMEOUT; // Time out error
};
return ErrorCode;
}
//////////////////////////////////////////////////////////////
// Wait_For_Status(void)
//
// Polls the Status Register of the Flash's status
// register until the Flash is finished with its access. Accesses
// that are affected by a latency are Page_Program, Sector_Erase,
// and Block_Erase.
// Inputs - Statusbit
// returns- none
//
//////////////////////////////////////////////////////////////
ERROR_CODE Wait_For_Status( char Statusbit )
{
int n, i;
char status_register = 0xFF;
ERROR_CODE ErrorCode = NO_ERR; // tells us if there was an error erasing flash
for(i = 0; i < TIMEOUT; i++)
{
status_register = ReadStatusRegister();
if( !(status_register & Statusbit) )
{
ErrorCode = NO_ERR; // tells us if there was an error erasing flash
break;
}
for(n=0; n<1000; n++)
asm("nop;");
ErrorCode = POLL_TIMEOUT; // Time out error
};
return ErrorCode;
}
//////////////////////////////////////////////////////////////
// void SendSingleCommand( const int iCommand )
//
// Sends a single command to the SPI flash
// inputs - the 8-bit command to send
// returns- none
//
//////////////////////////////////////////////////////////////
void SendSingleCommand( const int iCommand )
{
int n;
//turns on the SPI in single write mode
SetupSPI( (COMMON_SPI_SETTINGS|TIMOD01) );
//sends the actual command to the SPI TX register
*pSPI_TDBR = iCommand;
//The SPI status register will be polled to check the SPIF bit
Wait_For_SPIF();
//The SPI will be turned off
SPI_OFF();
//Pause before continuing
for(n=0; n<1000; n++)
{
asm("nop;");
}
}
//////////////////////////////////////////////////////////////
// Sets up the SPI for mode specified in spi_setting
// Inputs - spi_setting
// returns- none
//////////////////////////////////////////////////////////////
void SetupSPI( const int spi_setting )
{
//sets up the PF2 to be the slave select of the SPI
*pSPI_FLG = 0xFB04;
*pSPI_BAUD = BAUD_RATE_DIVISOR;
*pSPI_CTL = spi_setting;
}
//////////////////////////////////////////////////////////////
// Turns off the SPI
// Inputs - none
// returns- none
//
//////////////////////////////////////////////////////////////
void SPI_OFF(void)
{
int i;
*pSPI_CTL = 0x0400; // disable SPI
*pSPI_FLG = 0;
*pSPI_BAUD = 0;
for(i=0; i<1000; i++)
{
asm("nop;");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -