📄 flashdrv.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 + -