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

📄 flashdrv.c

📁 ATMEL系列存储器驱动程序,提供地层和上层驱动
💻 C
字号:
/*
 *CopyRight  Reserved?    凯拓科技版权所有  http://www.ktopcn.com  
 *文件名:flashdrv.c
 *描述:提供Flash操作的底层程序。
 *
 *版本:v1.0
 *作者:ktop
 *日期:2004/11/16
 */
#define		FLASHDRV_C 
#include "flashdrv.h"
static const uchar scucBitCode[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; 
 

/*
 *函数性质:私有
 *入口:无
 *出口:无
 *功能:按SPI的时序启动SPI
 */
static void StartSPI(void)
{
	#if (SPI_MODE == SPI_MODE_3) || (SPI_MODE == SPI_ICPH)	
	SET_CLK();NOP();
	#else
	CLR_CLK();NOP();
	#endif
	CLR_CS();NOP();
}


/*
 *函数性质:私有
 *入口:待移入的数据ucData
 *出口:无
 *功能:将待移入的数据移入到FLASH中。
 */
static void ShiftInsingleData(uchar ucData)
{
	uchar i;
	for (i = 0; i < 8; i++)
	{
		CLR_CLK();NOP();
		if ( ucData & scucBitCode[i] )
		{
			SET_DO();	
		}
		else
		{
			CLR_DO();	
		}	
		SET_CLK();NOP();
	}	
} 

/*
 *函数性质:私有
 *入口:待发送的数据缓冲pData,等发送的数据个数uiLen。
 *出口:无
 *功能:将缓冲中给定个数的数据移位输出到Flash
 */
static void ShiftInData(uchar *pData, uint uiLen)
{
	uint i;
	
	while(uiLen--)
	{
		for (i = 0; i < 8; i++)
		{
			CLR_CLK();NOP();
			if ( (*pData) & scucBitCode[i] )
			{
				SET_DO();	
			}
			else
			{
				CLR_DO();	
			}	
			SET_CLK();NOP();
		}
		pData++;		
	}	
}



/*
 *函数性质:私有
 *入口:存放数据的缓冲pData, 需要读取的数据个数uiLen
 *出口:无
 *功能:从Flash中读给定个数的数据入缓冲。
 */
static void ShiftOutData(uchar *pData, uint uiLen)
{
	uint i;
	
	while(uiLen--)
	{  
		*pData = 0;
		for (i = 0; i < 8; i++)
		{
			CLR_CLK();NOP();
			if ( READ_DI() )
			{
				*pData |= scucBitCode[i];	
			}
			SET_CLK();NOP();
		}		
		pData++;
	}	
}


/*
 *函数性质:私有
 *入口:无
 *出口:整合后的地址值
 *功能:整合页地址与页内偏移地址。
 */
static ulong CombPageAndOffect(uint uiPageAddr, uint uiOffectInPage)
{
	ulong i;
	i = uiPageAddr;
	i <<= 10;							//页地址左移10位
	i &= 0xfffffc00;
	i |= uiOffectInPage;				//整合偏移量
	return i;	
}


/*
 *函数性质:私有
 *入口:无
 *出口:无
 *功能:将SPI总线从数据输入转为数据输出模式。
 */   
static void InToOut(void)
{
	#if  (SPI_MODE == SPI_ICPL) || (SPI_MODE == SPI_ICPH)
	CLR_CLK();NOP();
	SET_CLK();NOP();
	#endif	
}





/*
 *函数性质:私有
 *入口:无
 *无口:无
 *功能:停止SPI操作。
 */
static void StopSPI(void)
{
	SET_CS();
	#if (SPI_MODE == SPI_MODE_3) || (SPI_MODE == SPI_ICPH)	
	SET_CLK();NOP();
	#else
	CLR_CLK();NOP();
	#endif	
}




#if CONT_READ_EN == true
/*
 *函数性质:公共
 *入口:Flash页地址uiPageAddr,Flash页内的偏移量uiOffectInPage, 储存读入的数据缓冲pData,需要读入的数据长度uiLen
 *出口:无
 *功能:从Flash阵列中连续读数据,并将读得的数据存入到pData中。
 */
void ContinueReadFlash(uint uiPageAddr, uint uiOffectInPage, uchar *pData, uint uiLen)
{
	ulong i;
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	i = CombPageAndOffect(uiPageAddr, uiOffectInPage);

	ShiftInsingleData(CON_ARRAY_READ);
	ShiftInsingleData((uchar)(i>>16));
	ShiftInsingleData((uchar)(i>>8));
	ShiftInsingleData((uchar)i);
	ShiftInData(pData, 4);									//移入4个不相关的字节

	InToOut();
	CLRWATCHDOG(); 
	ShiftOutData(pData,uiLen);								//读数据。
	CLRWATCHDOG(); 
	StopSPI();												//停止SPI操作。	
}
#endif






#if PAGE_READ_EN == true
/*
 *函数性质:公共
 *入口:Flash页地址uiPageAddr,Flash页内的偏移量uiOffectInPage, 储存读入的数据缓冲pData,需要读入的数据长度uiLen
 *出口:无
 *功能:从Flash阵列中以页方式读数据,并将读得的数据存入到pData中。当读到一个页的尾部时,
 *下一次读出的数据为页的起始数据。
 */
void PageReadFlash(uint uiPageAddr, uint uiOffectInPage, uchar *pData, uint uiLen)
{
	ulong i;   
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	i = CombPageAndOffect(uiPageAddr, uiOffectInPage);

	ShiftInsingleData(MEM_PAGE_READ);
	ShiftInsingleData((uchar)(i>>16));
	ShiftInsingleData((uchar)(i>>8));
	ShiftInsingleData((uchar)i);
	ShiftInData(pData, 4);									//移入4个不相关的字节

	InToOut();
	CLRWATCHDOG(); 
	ShiftOutData(pData,uiLen);								//读数据。
	CLRWATCHDOG(); 
	StopSPI();												//停止SPI操作。		
}
#endif






#if BUFFER_READ_EN == true
/*
 *函数性质:公共
 *入口:Buffer号ucBufNum,Buffer内的偏移量uiOffectInPage, 储存读入的数据缓冲pData,需要读入的数据长度uiLen
 *出口:无
 *功能:从给定的Flash缓冲中读数据,读得的数据存放到pData中。当读到缓冲的尾部时,再次读出将会读到缓冲的头部。
 */
void ReadFlashBuff(uchar ucBufNum, uint uiOffectInPage, uchar *pData, uint uiLen)
{  
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(ucBufNum);
	ShiftInsingleData(ucBufNum);							//移入一个不相关字节
	ShiftInsingleData((uchar)(uiOffectInPage>>8));
	ShiftInsingleData((uchar)uiOffectInPage);
	ShiftInsingleData((uchar)uiOffectInPage);				//移入一个不相关字节

	InToOut();
	CLRWATCHDOG(); 
	ShiftOutData(pData,uiLen);								//读数据。
	CLRWATCHDOG(); 
	StopSPI();												//停止SPI操作。		
}
#endif





#if STU_REG_READ_EN == true
/*
 *函数性质:公共
 *入口:无
 *出口:状态寄存器的值
 *功能:读Flash的状态寄存器值。
 */
uchar ReadFlashStuReg(void)
{
	uchar i;
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(STU_REG_READ);
	InToOut();
	ShiftOutData(&i,1);										//读取状态寄存器的值。
	StopSPI();												//停止SPI操作。		
	return i;
}
#endif





#if BUFFER_W_EN == true
/*
 *函数性质:公共
 *入口:Buffer号ucBufNum,Buffer内的偏移量uiOffectInPage, 储存写入的数据缓冲pData,需要写入的数据长度uiLen
 *出口:无
 *功能:往给定的Flash缓冲写数据,待写入的数据存放在pData中,当写到缓冲的尾部时,再次写入将会写入到缓冲的头部。
 */
void WriteFlashBuff(uchar ucBufNum, uint uiOffectInPage, uchar *pData, uint uiLen)
{
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(ucBufNum);
	ShiftInsingleData(ucBufNum);							//移入一个不相关字节
	ShiftInsingleData((uchar)(uiOffectInPage>>8));
	ShiftInsingleData((uchar)uiOffectInPage);
	CLRWATCHDOG(); 
	ShiftInData(pData,uiLen);								//写数据。
	CLRWATCHDOG(); 
	StopSPI();												//停止SPI操作。			
}
#endif





#if BUFF_TO_MEM_WITH_ERASE_EN == true
/*
 *函数性质:公共
 *入口:Buffer号ucBufNum,Flash的页地址uiFlashPageAddr
 *出口:无
 *功能:往给定编号的Buffer数据写入到给定的Flash页,并使用内置擦除器。
 */
void WriteBuffToFlash(uchar ucBufNum, uint uiFlashPageAddr)
{
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(ucBufNum);
	ShiftInsingleData((uchar)(uiFlashPageAddr>>6));
	ShiftInsingleData((uchar)(uiFlashPageAddr<<2));
	ShiftInsingleData(ucBufNum);						//写入一个不相关字节。
	StopSPI();	
}
#endif





#if BUFF_TO_MEM_NO_ERASE_EN == true
/*
 *函数性质:公共
 *入口:Buffer号ucBufNum,Flash的页地址uiFlashPageAddr
 *出口:无
 *功能:往给定编号的Buffer数据写入到给定的Flash页,不使用内置擦除器。
 */
void WriteBuffToFlashWithNoErase(uchar ucBufNum, uint uiFlashPageAddr)
{   
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(ucBufNum);
	ShiftInsingleData((uchar)(uiFlashPageAddr>>6));
	ShiftInsingleData((uchar)(uiFlashPageAddr<<2));
	ShiftInsingleData(ucBufNum);						//写入一个不相关字节。
	StopSPI();	
}
#endif




#if PAGE_ERASE_EN == true
/*
 *函数性质:公共
 *入口:页地址uiFlashPageAddr
 *出口:无
 *功能:页擦除Flash
 */
void FlashPageErase(uint uiFlashPageAddr)
{
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(PAGE_ERASE);
	ShiftInsingleData((uchar)(uiFlashPageAddr>>6));
	ShiftInsingleData((uchar)(uiFlashPageAddr<<2));
	ShiftInsingleData(PAGE_ERASE);						//写入一个不相关字节。
	StopSPI();		
}
#endif





#if BLOCK_ERASE_EN == true
/*
 *函数性质:公共
 *入口:Flash块地址uiFlashBlockAddr
 *出口:无
 *功能:块擦除Flash
 */
void FlashBlockErase(uint uiFlashBlockAddr)
{
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(BLOCK_ERASE);
	ShiftInsingleData((uchar)(uiFlashBlockAddr>>3));
	ShiftInsingleData((uchar)(uiFlashBlockAddr<<5));
	ShiftInsingleData(BLOCK_ERASE);						//写入一个不相关字节。
	StopSPI();	
}
#endif





#if BUFF_TO_MEM_EN == true
/*
 *函数性质:公共
 *入口:Buffer编号ucBufNum,Flash页地址uiPageAddr,Flash页内的偏移量uiOffectInPage,
 * 待写入的数据缓冲pData,需要写入的数据长度uiLen
 *出口:无
 *功能:本函数整合写缓冲和缓冲数据写入存储器功能,先将数据写入到给定的缓冲中,写入缓冲的偏移量
 *由uiOffectInPage确定。如果写入的数据超出缓冲的范围,则自动回绕到缓冲的头部。在写缓冲完成后,
 *将芯片的片选置高,则开始缓冲的数据到存储器传送。在整个写入未完成时,状态寄存器中的忙信号有效。
 */
void WriteFlashWithBuff(uchar ucBufNum, uint uiPageAddr, uint uiOffectInPage, uchar *pData, uint uiLen)
{
	ulong i;
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	i = CombPageAndOffect(uiPageAddr, uiOffectInPage);

	ShiftInsingleData(ucBufNum);
	ShiftInsingleData((uchar)(i>>16));
	ShiftInsingleData((uchar)(i>>8));
	ShiftInsingleData((uchar)i);
	CLRWATCHDOG(); 
	ShiftInData(pData, uiLen);								//写入数据
	CLRWATCHDOG(); 
	StopSPI();												//停止SPI操作。	
	
}
#endif


#if  MEM_TO_BUFF_EN == true
/*
 *函数性质:公共
 *入口:Buffer编号ucBufNum,  Flash的页地址uiFlashPageAddr
 *出口:无
 *功能:从主存储器中给定页地址读数据到给定的缓冲
 */
void ReadFlashToBuff(uchar ucBufNum, uint uiFlashPageAddr)
{
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(ucBufNum);
	ShiftInsingleData((uchar)(uiFlashPageAddr>>6));
	ShiftInsingleData((uchar)(uiFlashPageAddr<<2));
	ShiftInsingleData(ucBufNum);						//写入一个不相关字节。
	StopSPI();	
}
#endif


#if COMP_MEM_AND_BUFF_EN == true
/*
 *函数性质:公共
 *入口:Buffer编号ucBufNum,  Flash的页地址uiFlashPageAddr
 *出口:无
 *功能:比较给定的缓冲与存储器中对应页的数据。如果相等,则状态寄存器中相应的位清零,否则置位,
 *在比较过程中,忙标志有效。
 */
void CompFlashAndBuff(uchar ucBufNum, uint uiFlashPageAddr)
{   
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(ucBufNum);
	ShiftInsingleData((uchar)(uiFlashPageAddr>>6));
	ShiftInsingleData((uchar)(uiFlashPageAddr<<2));
	ShiftInsingleData(ucBufNum);						//写入一个不相关字节。
	StopSPI();		
}
#endif

#if AUTO_RE_W_FROM_BUFF_EN == true
/*
 *函数性质:公共
 *入口:Buffer编号ucBufNum,Flash页地址uiPageAddr,Flash页内的偏移量uiOffectInPage,
 * 待写入的数据缓冲pData,需要写入的数据长度uiLen
 *出口:无
 *功能:自动读出给定页地址的Flash数据到给定的Buffer中,并在修改完缓冲中的数据后,自动重写入到
 *相应的存储器中。在写入过程中,状态寄存器中忙标志有效。
 */
void AutoReWriteFlash(uchar ucBufNum, uint uiFlashPageAddr, uint uiOffectInPage, uchar*pData, uint uiLen)
{   
	SET_CLK_OUT();SET_DO_OUT();SET_CS_OUT();
	StartSPI();
	ShiftInsingleData(ucBufNum);
	ShiftInsingleData((uchar)(uiFlashPageAddr>>6));
	ShiftInsingleData((uchar)(uiFlashPageAddr<<2));
	ShiftInsingleData(ucBufNum);						//写入一个不相关字节。	
	CLRWATCHDOG(); 
	WriteFlashBuff(ucBufNum, uiOffectInPage, pData, uiLen);
	CLRWATCHDOG(); 
	StopSPI();
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -