u8 nandflash_write_buffer[NAND_SERECT_FULL_SIZE];
static int currentBlock = -1;
static int currentPage = -1;
//带缓冲的nand读取,不支持跨扇区
void NAND_Read_Addr_Mal(u32 addr,u8* buffer,u32 length)
{
u32 i = 0;
u32 readBlock = ((addr/NAND_SERECT_SIZE)/NAND_PAGE_NUM);//获取要写入的块
u32 readPage = ((addr/NAND_SERECT_SIZE)%NAND_PAGE_NUM);//获取要写入的页面
u32 readoffset = (addr%NAND_SERECT_SIZE);//写入位置偏移
u32 readPageCount = ((length + readoffset)/NAND_SERECT_SIZE);//获取一共需要写入的页
if(((length + readoffset)%NAND_SERECT_SIZE) != 0)readPageCount++;//比如刚好2048的时候,就还是在一页
if(readPageCount == 1)//仅读取一个快
{
//先检查当前需要读取的数据是不是在缓冲区中
if(currentBlock >= 0 && currentPage >= 0)
{
if(readBlock == currentBlock && readPage == currentPage)
{
//在缓冲区中读取数据
for(i = 0; i < length; i++)
{
buffer[i] = nandflash_write_buffer[readoffset+i];
}
}
else
{
//在物理设备中读取数据
NAND_Read_Random_Page(readBlock,readPage,readoffset,buffer,length);
}
}
else if(currentBlock == -1 && currentPage == -1)
{
//缓冲区为空,直接进行物理读取
NAND_Read_Random_Page(readBlock,readPage,readoffset,buffer,length);
}
}
else
{
// printf("2 or up sector not vailed \r\n");
}
}
//带缓冲nand写入,不支持跨扇区
void NAND_Write_Addr_Mal(u32 addr,u8* buffer,u32 length)
{
u32 writeBlock = (addr/NAND_SERECT_SIZE)/NAND_PAGE_NUM; //获取要写入的块
u32 writePage = (addr/NAND_SERECT_SIZE)%NAND_PAGE_NUM; //获取要写入的页面
u32 writeoffset = (addr%NAND_SERECT_SIZE); //写入位置偏移
u32 i = 0;
u32 copy;
if(currentBlock >= 0 && currentPage >= 0)
{
if(currentBlock == writeBlock && currentPage == writePage)//没有切换页面,那么数据更新依旧在缓存中
{
for(i = writeoffset; i < writeoffset+length ;i++)
{
nandflash_write_buffer[i] = buffer[i-writeoffset];
}
}
else
{
//更新了页面的写入,先将缓存中数据写入物理设备,进行新的一轮缓存操作
copy = (currentBlock/42)+NAND_COPYBACL_BLOCK_START;
//擦除交换分区
NAND_Erase_Block(copy);
for(i = 0; i < NAND_PAGE_NUM;i++)//拷贝数据到交换分区
{
if(i != currentPage)
{
NAND_Copy_Back_Page(currentBlock,i,copy,i);
}
}
//擦除源分区
NAND_Erase_Block(currentBlock);
//将原来数据拷贝回去
for(i = 0; i < NAND_PAGE_NUM;i++)//拷贝数据到交换分区
{
if(i != currentPage)
{
NAND_Copy_Back_Page(copy,i,currentBlock,i);
}
}
//将缓存数据拷贝到目的分区
NAND_Write_Page_full(currentBlock,currentPage,NAND_SERECT_FULL_SIZE,nandflash_write_buffer);
//到这里缓存的写入物理设备完成,接下来开始新一轮缓存
NAND_Read_Full_Page(writeBlock,writePage,nandflash_write_buffer,NAND_SERECT_FULL_SIZE);
currentBlock = writeBlock;
currentPage = writePage;//更新标记
//接下来更新数据,数据更新在缓存中进行,切换的时候写入
for(i = writeoffset; i < writeoffset+length ;i++)
{
nandflash_write_buffer[i] = buffer[i-writeoffset];
}
}
}
else if(currentBlock == -1 && currentPage == -1)//当前缓存包里面没有数据
{
//从nand中读出来
NAND_Read_Full_Page(writeBlock,writePage,nandflash_write_buffer,NAND_SERECT_FULL_SIZE);
currentBlock = writeBlock;
currentPage = writePage;//更新标记
//接下来更新数据,数据更新在缓存中进行,切换的时候写入
for(i = writeoffset; i < writeoffset+length ;i++)
{
nandflash_write_buffer[i] = buffer[i-writeoffset];
}
}
}
void Nand_Flush(void) //nand缓冲区刷入设备
{
u32 copy;
u32 i = 0;
//将还没有写入的数据刷新到nand中,标记归零
if(currentBlock >= 0 && currentPage >= 0)
{
//更新了页面的写入,先将缓存中数据写入物理设备,进行新的一轮缓存操作
copy = (currentBlock/42)+NAND_COPYBACL_BLOCK_START;
//擦除交换分区
NAND_Erase_Block(copy);
for(i = 0; i < NAND_PAGE_NUM;i++)//拷贝数据到交换分区
{
if(i != currentPage)
{
NAND_Copy_Back_Page(currentBlock,i,copy,i);
}
}
//擦除源分区
NAND_Erase_Block(currentBlock);
//将原来数据拷贝回去
for(i = 0; i < NAND_PAGE_NUM;i++)//拷贝数据到交换分区
{
if(i != currentPage)
{
NAND_Copy_Back_Page(copy,i,currentBlock,i);
}
}
//将缓存数据拷贝到目的分区
NAND_Write_Page_full(currentBlock,currentPage,NAND_SERECT_FULL_SIZE,nandflash_write_buffer);
currentBlock = -1;
currentPage = -1;
}
}
结合之前写的USB做U盘的例子来看,能降低写文件的时候的擦除次数