📄 flash.c
字号:
/******************************************************************************
FLASH 操作
/******************************************************************************
名称:flash.c
功能:对FLASH进行操作
硬件:AT45DB021
作者:Albert
日期:2004-08-29
修改日期:
修改内容:
/*****************************************************************************/
#include <mega128.h>
#include <spi.h>
#include "flash.h"
#include "type.h"
BYTE gFlashBuff[0x1000]; //FLASH缓冲区 = 2 BLOCK = 4kB
/******************************/
int CalculateAddrOffsetSize ( DWORD addr1 , DWORD addr2); //计算地址偏移大小
DWORD AddrToPageAndOffset(DWORD addr,DWORD addr_offset); //根据地址和偏移大小计算新地址
BOOL ReadFlashStatus(void);
BOOL ReadFlashMem(BYTE *buf, WORD size, DWORD addr); //读FLASH
void ReadFlashPage(BYTE *pBuf,WORD size, DWORD addr);
BOOL WriteFlashMem(BYTE *buf, WORD size, DWORD addr); //写FLASH
void WriteFlashPage(BYTE *pBuf,WORD size, DWORD addr); //写一页
void CopyFlashPage(WORD despage,WORD srcpage); //复制页
void CopyFlashBlock(WORD desblock,WORD srcblock); //复制Block
void EraseFlashPage(WORD pager);
void EraseFlashBlock(BYTE block);
void EraseFlashChip(void);
void EraseSector(BYTE Sector);
void InitSpi(void);
/******************************/
//计算两个flash地址之间的大小
int CalculateAddrOffsetSize ( DWORD addr1 , DWORD addr2)
{
WORD page1,page2,page;
WORD offset1,offset2,offset;
int size;
if( addr1 == addr2 )
return 0;
else if( addr1 > addr2 )
{
page1 = (WORD)(addr1 >> 9);
offset1 = (WORD)addr1 & 0x1ff;
page2 = (WORD)(addr2 >> 9);
offset2 = (WORD)addr2 & 0x1ff;
if( offset1 >= offset2 )
{
page = page1 - page2;
offset = offset1 - offset2;
size = page*FLASH_PAGE_SIZE + offset;
}
else
{
page = page1 - page2 - 1;
offset = ( offset1 + FLASH_PAGE_SIZE ) - offset2;
size = page*FLASH_PAGE_SIZE + offset;
}
}
return size;
}
//给出地址和地址偏移量,计算页地址和页内地址,返回新地址
DWORD AddrToPageAndOffset(DWORD addr,DWORD addr_offset)
{
WORD page;
WORD offset;
WORD srcpage,pagetemp;
WORD srcoffset,offsettemp;
WORD offsetsum;
WORD pagerem;
DWORD address;
srcpage = (WORD)(addr >> 9);
srcoffset = (WORD)(addr & 0x001ff );
if(srcoffset > 255)
return FALSE;
pagetemp = (WORD)(addr_offset / FLASH_PAGE_SIZE);
offsettemp = (WORD)(addr_offset % FLASH_PAGE_SIZE);
offsetsum = srcoffset + offsettemp;
pagerem = offsetsum / FLASH_PAGE_SIZE;
if(pagerem > 1)
return FALSE;
offset = offsetsum % FLASH_PAGE_SIZE;
page = srcpage + pagetemp + pagerem;
address = (DWORD)page << 9;
address += (DWORD)offset;
return address;
}
BOOL ReadFlashStatus(void)
{
BYTE status;
FLASH_CS_H;
delay_ms(1);
FLASH_CS_L;
spi(0xD7);
status = spi(0xff);
FLASH_CS_L;
delay_ms(1);
FLASH_CS_H;
if(status & 0x80)
return TRUE;
else
return FALSE;
}
//不连续写FLASH(主存读数据),一页一页读
void ReadFlashBuf(DWORD address)
{
while(ReadFlashStatus() == FALSE);
FLASH_CS_H;
delay_ms(1);
FLASH_CS_L;
spi(0x53);
spi((char)((address >> 16)&0x0f));
spi((char)((address >> 8)&0xfe));
spi(0x00);
FLASH_CS_L;
delay_ms(1);
FLASH_CS_H;
}
//不连续写FLASH(主存读数据),一页一页读
void ReadFlashPage(BYTE *pBuf,WORD size, DWORD addr)
{
WORD i;
while(ReadFlashStatus() == FALSE);
FLASH_CS_H;
delay_ms(1);
FLASH_CS_L;
spi(0xD2);
spi((char)(addr >> 16));
spi((char)(addr >> 8));
spi((char)addr);
spi(0x00);
spi(0x00);
spi(0x00);
spi(0x00);
for(i=0;i<size;i++)
*pBuf++ = spi(0xff);
FLASH_CS_L;
delay_ms(1);
FLASH_CS_H;
}
BOOL ReadFlashMem(BYTE *buf, WORD size, DWORD addr)
{
WORD i;
WORD pagenum = 0;
WORD pageres = 0;
WORD remain = 0;
WORD pager_offset;
pager_offset = (WORD)(addr & 0x001ff);
if(pager_offset > 255)
return FALSE;
if(size <= (FLASH_PAGE_SIZE - pager_offset))
ReadFlashPage(buf,size,addr);
else
{
ReadFlashPage(buf,FLASH_PAGE_SIZE-pager_offset,addr);
remain = size - (FLASH_PAGE_SIZE - pager_offset);
pagenum = remain / FLASH_PAGE_SIZE;
pageres = remain % FLASH_PAGE_SIZE;
if((pagenum == 0)&&(pageres == 0))
return FALSE;
for(i=1;i<pagenum+1;i++)
{
ReadFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset),FLASH_PAGE_SIZE,(addr+i*0x00200)&0xffe00);//页地址加1
}
ReadFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset), size-(FLASH_PAGE_SIZE*i-pager_offset), (addr+i*0x00200)&0xffe00);
}
return TRUE;
}
//给定FLASH地址,连续写数据
BOOL WriteFlashMem(BYTE *buf, WORD size, DWORD addr)
{
WORD i;
WORD pagenum = 0;
WORD pageres = 0;
WORD remain = 0;
WORD pager_offset;
pager_offset = (WORD)(addr & 0x001ff);
if(pager_offset > 255)
return FALSE;
if(size <= (FLASH_PAGE_SIZE - pager_offset))
WriteFlashPage(buf,size,addr);
else
{
WriteFlashPage(buf,FLASH_PAGE_SIZE-pager_offset,addr);
remain = size - (FLASH_PAGE_SIZE - pager_offset);
pagenum = remain / FLASH_PAGE_SIZE;
pageres = remain % FLASH_PAGE_SIZE;
if((pagenum == 0)&&(pageres==0))
return FALSE;
for(i=1;i<pagenum+1;i++)
{
WriteFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset),FLASH_PAGE_SIZE,(addr+i*0x00200)&0xffe00);//页地址加1
}
WriteFlashPage(buf+(FLASH_PAGE_SIZE*i-pager_offset), size-(FLASH_PAGE_SIZE*i-pager_offset), (addr+i*0x00200)&0xffe00);
}
return TRUE;
}
//不连续写FLASH(主存写数据),一页一页写
void WriteFlashPage(BYTE *pBuf,WORD size, DWORD addr)
{
WORD i;
while(ReadFlashStatus() == FALSE);
ReadFlashBuf(addr); //读到buff
FLASH_CS_H;
delay_ms(1);
FLASH_CS_L;
spi(0x82);
spi((char)(addr >> 16));
spi((char)(addr >> 8));
spi((char)addr);
for(i=0;i<size;i++)
spi(*pBuf++);
FLASH_CS_L;
delay_ms(1);
FLASH_CS_H;
}
//拷贝一个sector (起始页后4K字节)
void CopyFlashPage(WORD despage,WORD srcpage)
{
DWORD addr;
addr = (DWORD)(srcpage*2) << 12;
ReadFlashMem(gFlashBuff,0x1000L,addr);
addr = (DWORD)(despage*2) << 12;
WriteFlashMem(gFlashBuff,0x1000L,addr);
}
//拷贝BLOCK (起始页后2048个字节为1个BLOCK = 2048B)
void CopyFlashBlock(WORD desblock,WORD srcblock)
{
DWORD addr;
addr = (DWORD)(srcblock << 9);
ReadFlashMem(gFlashBuff,2048,addr);
addr = (DWORD)(desblock << 9);
WriteFlashMem(gFlashBuff,2048,addr);
}
//页擦除
void EraseFlashPage(WORD pager)
{
while(ReadFlashStatus() == FALSE);
FLASH_CS_H;
delay_ms(1);
FLASH_CS_L;
spi(0x81);
spi((char)(pager>>7));
spi((char)((pager<<1)&0xfe));
spi(0x00);
FLASH_CS_L;
delay_ms(1);
FLASH_CS_H;
delay_ms(1);
}
//块擦除
void EraseFlashBlock(BYTE block)
{
while(ReadFlashStatus() == FALSE);
FLASH_CS_H;
delay_ms(1);
FLASH_CS_L;
spi(0x50);
spi((char)(block>>4));
spi((char)((block<<4)&0xf0));
spi(0x00);
FLASH_CS_L;
delay_ms(1);
FLASH_CS_H;
delay_ms(1);
}
//芯片擦除
void EraseFlashChip(void)
{
BYTE i;
for(i=0;i<128;i++)//256个BLOCK
EraseSector(i);
}
//擦除1个扇区
void EraseSector(BYTE Sector)
{ //4KB
EraseFlashBlock(Sector*2);
EraseFlashBlock(Sector*2+1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -