⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m25p64.c

📁 Blackfin驱动, 对SPI flash编程
💻 C
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////

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 + -