flashat45db161d驱动模块源码C.docx
《flashat45db161d驱动模块源码C.docx》由会员分享,可在线阅读,更多相关《flashat45db161d驱动模块源码C.docx(18页珍藏版)》请在冰豆网上搜索。
flashat45db161d驱动模块源码C
声明:
希望使用者保留本人的相关信息,当然了,要面试时用除外,呵呵
/**********模块注释*********************************************************
模块名:
E:
\__ldr__\my_prj\SW_PRJ\SRC\EX_DEV_DRV\at45db161d.c
模块功能:
提供操作flash:
AT45DB161D的必要的接口,简单明了.
存在问题:
1)如果突然断电,很可能要会丢掉1page数据,原来的模块也存在这样的问题,电脑windows系统也有.
2)没有考虑坏页的问题.
把flash的两个ram分别用作wbuf和rbuf.
全局设定:
全局依赖:
与flash芯片通信的驱动模块
编程语言:
ANSIC
作者及日期:
练达荣2015/06/18
版本:
V1.0
修改及日期:
*******************************************************************************/
#include
#include
#include"../delay.h"
#include"../uart.h"
#include"../stc_spi.h"
#define__DELCALE_IN_THIS_FILE__
#include"at45db161d.h"
//#defineDEBUG_THIS_MODULE
#if0//defDEBUG_THIS_MODULE
#defineDEBUG_uart1_Sendbuf(buffer,bytes16)uart1_Sendbuf(buffer,bytes16)
#defineDEBUG_uart1_SendString(str)uart1_SendString(str)
#defineDEBUG_uart1_SendByte(dat8)uart1_SendByte(dat8)
#else
#defineDEBUG_uart1_Sendbuf(buffer,bytes16)
#defineDEBUG_uart1_SendString(str)
#defineDEBUG_uart1_SendByte(dat8)
#endif
///////////////////////////////////////////移植相关///////////////////////////////////////////////////////////////////////////
#defineSPI_CSP12//外部flashSPI使能信号
#defineSelect_Flash()SPI_CS=0
#defineUnSelect_Flash()SPI_CS=1
#definewrite1Byte(x)spi_WriteRead1Byte(x)
#defineread1Byte()spi_WriteRead1Byte(0)
///////////////////////////////////////////FLASH操作命令///////////////////////////////////////////////////////////////////////////
#definePAGE_TO_B1_XFER0x53//mainmemorypagetobuffer1transfer
#definePAGE_TO_B2_XFER0x55//mainmemorypagetobuffer2transfer
#definePAGE_TO_B2_COMP0x61//mainmemorypagecomparetobuffer2
#defineB2_TO_PAGE_WITH_ERASE0x86//buffer2tomainmemorypageprogramwithbuilt-inerase
#defineSTATUS_REGISTER0xD7
#defineBUFFER_1_READ0xD1//D4buffer1read(changeto0xD4forSPImode0,3)
#defineFLASH_CMD_ReadID0x9f//读取芯片32位ID.
#defineBUFFER_2_WRITE0x87//buffer2write
#defineBUFFER_2_READ0xD3//D6buffer2read(changeto0xD6forSPImode0,3)
///////////////////////////////////////////纯软件部分///////////////////////////////////////////////////////////////////////////
typedefstruct
{
UINT16pageIdRead;//[0~4095]当前读的页地址
UINT16pageIdWrite;//[0~4095]当前写的页地址
}T_FlashCtrl;
staticT_FlashCtrlctl;
typedefenum
{
E_ReadBuffer,
E_WriteBuffer
}ET_BufReadWrite;
/****************************************************************************************
*Function:
检测并等待器件忙状态
*Description:
过读状态寄存器来检测忙状态
*Calls:
-
*Input:
-
*Output:
-
*Return:
*****************************************************************************************/
staticvoidFLASH_Wait_Busy(void)
{
Select_Flash();
write1Byte(STATUS_REGISTER);
while
(1)
{
if(read1Byte()&0x80)//读取的最高位1时器件忙
break;
}
UnSelect_Flash();
}
/****************************************************************************************
*Function:
缓冲区(writebuffer)数据与FLASH指定页比较
*Description:
状态寄存器bit6为0表示比较数据想匹配,1表示比较数据不相匹配
*Calls:
-
*Input:
-
*Output:
TRUE不相同
FALSE相同
*Return:
*****************************************************************************************/
staticUINT8flash_buffer_compareUnsame(UINT16page)
{
Select_Flash();
write1Byte(PAGE_TO_B2_COMP);
write1Byte((UINT8)(page>>6));
write1Byte((UINT8)(page<<2));
write1Byte(0x00);
UnSelect_Flash();
FLASH_Wait_Busy();
Select_Flash();
write1Byte(STATUS_REGISTER);
if(read1Byte()&0x40)//读取的比较状态位
{
UnSelect_Flash();
return1;
}
else
{
UnSelect_Flash();
return0;
}
}
/****************************************************************
原型:
功能:
从flash里读给定page的数据到flash的部ram.
入参:
uintpageflash的页,[0~4095]
ET_BufReadWritebufferType
出参:
运行环境:
调用说明:
作者:
练达荣2015/06/18
****************************************************************/
staticvoidLoad_Page_To_Buffer(UINT16page,ET_BufReadWritebufferType)
{
Select_Flash();
write1Byte(bufferType==E_ReadBuffer?
PAGE_TO_B1_XFER:
PAGE_TO_B2_XFER);
write1Byte((UINT8)(page>>6));
write1Byte((UINT8)(page<<2));
write1Byte(0x00);
UnSelect_Flash();
FLASH_Wait_Busy();
}
/****************************************************************************************
*Function:
将"写缓冲区容"写入到主存储器中指定页
*Description:
*Calls:
-
*Input:
-页地址,缓冲区
*Output:
-
*Return:
*****************************************************************************************/
staticvoidWrite_Page_From_Buffer(UINT16page)
{
Select_Flash();
write1Byte(B2_TO_PAGE_WITH_ERASE);
write1Byte((UINT8)(page>>6));
write1Byte((UINT8)(page<<2));
write1Byte(0x00);//don'tcare
UnSelect_Flash();
FLASH_Wait_Busy();
}
/****************************************************************************************
*Function:
从读缓冲区读数据(BUFFER1),读出字节可选
*Description:
*Calls:
-
*Input:
-页字节地址,缓冲接收数组,读数据长度
*Output:
-
*Return:
*****************************************************************************************/
staticvoidRead_DataFromFlashBuffer(uintaddr,UINT8*dat,UINT16bytes)
{
uinti;
Select_Flash();
write1Byte(BUFFER_1_READ);
write1Byte(0x00);
write1Byte((UINT8)(addr>>8));
write1Byte((UINT8)addr);
for(i=0;i{
dat[i]=read1Byte();
}
UnSelect_Flash();
}
/****************************************************************************************
*Function:
从读缓冲区读数据(BUFFER1),读出字节可选
*Description:
*Calls:
-
*Input:
-页字节地址,缓冲接收数组,读数据长度
*Output:
-
*Return:
*****************************************************************************************/
staticvoidRead_DataFromWriteBuffer(uintaddr,UINT8*dat,UINT16bytes)
{
uinti;
Select_Flash();
write1Byte(BUFFER_2_READ);
write1Byte(0x00);
write1Byte((UINT8)(addr>>8));
write1Byte((UINT8)addr);
for(i=0;i{
dat[i]=read1Byte();
}
UnSelect_Flash();
}
/****************************************************************************************
*Function:
将数据写入写缓冲区(BUFFER2),写入字节可选
*Description:
;
*Calls:
-
*Input:
-页字节地址,缓冲发送数组,写读数据长度
*Output:
-
*Return:
*****************************************************************************************/
staticvoidWrite_Data2FlashBuffer(uintaddr,UINT8*dat,UINT16bytes)
{
uinti;
Select_Flash();
write1Byte(BUFFER_2_WRITE);
write1Byte(0x00);
write1Byte((UINT8)(addr>>8));
write1Byte((UINT8)addr);
for(i=0;i{
write1Byte(dat[i]);
}
UnSelect_Flash();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//以下是全局函数
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
voidflash_init(void)
{
memset(&ctl,0,sizeof(ctl));
Load_Page_To_Buffer(ctl.pageIdWrite,E_WriteBuffer);
Load_Page_To_Buffer(ctl.pageIdRead,E_ReadBuffer);
}
/****************************************************************
原型:
BOOLflash_write_ok(UINT32addr,UINT8*buf,UINT16bytes)
功能:
把数据写到flash的绝对地址中,可能只是写到其buf里面.
约定:
任何时候的ctl.pageIdWrite所对应的页都会被读到相应writebuf里,并且只可能比flash里新.
入参:
UINT32addrflash的绝对字节地址(0~2MByte,每个page最后16字节不要,但认为是连续的2MBytes)
UINT8*buf等待保存的数据
UINT16bytes要保存数据字节数
出参:
TRUE写成功
FALSE写失败,地址越界
运行环境:
调用说明:
作者:
练达荣2015/06/18
****************************************************************/
BOOLflash_write_ok(UINT32addr,UINT8*buf,UINT16bytes)
{
UINT16page=addr/BYTES_PER_PAGE;
UINT16beginAddr=addr%BYTES_PER_PAGE;
UINT8bytes_will_write;
if(addr>=FLASH_TOTAL_BYTES||addr+bytes>FLASH_TOTAL_BYTES)returnFALSE;
DEBUG_uart1_SendString("FFWWBBBB\r\n");
if(page!
=ctl.pageIdWrite)//写的不是当前页,先保存当前页到flash.
{
DEBUG_uart1_SendString("FFWW0000\r\n");
DEBUG_uart1_Sendbuf((UINT8*)&page,sizeof(page));
DEBUG_uart1_Sendbuf((UINT8*)&ctl.pageIdWrite,sizeof(ctl.pageIdWrite));
Write_Page_From_Buffer(ctl.pageIdWrite);
ctl.pageIdWrite=page;
Load_Page_To_Buffer(ctl.pageIdWrite,E_WriteBuffer);
}
while(beginAddr+bytes>BYTES_PER_PAGE)
{//超出原来的页
DEBUG_uart1_SendString("FFWW1111\r\n");
DEBUG_uart1_Sendbuf((UINT8*)&beginAddr,sizeof(beginAddr));
DEBUG_uart1_Sendbuf((UINT8*)&bytes,sizeof(bytes));
DEBUG_uart1_Sendbuf((UINT8*)&ctl.pageIdWrite,sizeof(ctl.pageIdWrite));
bytes_will_write=BYTES_PER_PAGE-beginAddr;
Write_Data2FlashBuffer(beginAddr,buf,bytes_will_write);
if(flash_buffer_compareUnsame(ctl.pageIdWrite))
{
DEBUG_uart1_SendString("FFWW2222\r\n");
Write_Page_From_Buffer(ctl.pageIdWrite);
}
buf+=bytes_will_write;
bytes-=bytes_will_write;
beginAddr=0;ctl.pageIdWrite++;
Load_Page_To_Buffer(ctl.pageIdWrite,E_WriteBuffer);
}
if(bytes!
=0)
{
DEBUG_uart1_SendString("FFWW3333\r\n");
DEBUG_uart1_Sendbuf((UINT8*)&beginAddr,sizeof(beginAddr));
DEBUG_uart1_Sendbuf((UINT8*)&bytes,sizeof(bytes));
DEBUG_uart1_Sendbuf(buf,bytes);
Write_Data2FlashBuffer(beginAddr,buf,bytes);
}
returnTRUE;
}
/****************************************************************
原型:
UINT16flash_read(UINT32addr,UINT8*savebuf,UINT16bytes)
功能:
从flash的绝对地址中,读出特定的字节数,可能只是读readbuffer,也可能两个都读.
约定:
任何时候的ctl.pageIdWrite所对应的页都会被读到相应writebuf里,并且只可能比flash里新.
入参:
UINT32addrflash的绝对字节地址(0~2MByte,每个page最后16字节不要,但认为是连续的2MBytes)
UINT8*buf等待保存的数据
UINT16bytes要保存数据字节数
出参:
实际读成功的字节数.
运行环境:
调用说明:
作者:
练达荣2015/06/18
****************************************************************/
UINT16flash_read(UINT32addr,UINT8*savebuf,UINT16bytes)
{
UINT16page=addr/BYTES_PER_PAGE;
UINT16beginAddr=addr%BYTES_PER