📄 flash.c
字号:
#include "include.h"
uint data flash_r_addr;
uint data flash_w_addr;
uchar data flash_r_data;
uchar data flash_w_data;
bit A15;
sbit A20=P3^5;
sbit AB15=P4^3;
//注意:对于XBYTE[]的操作的偏移地址是仿真器的需要,实际CUP不需要
// 检查指定扇区是否空,扇区空返回0
//=======================================================================
//===========SRAM读写驱动====================================//
/*************************************************************
*函数名称: select_sector(uchar sector)
*输入参数: uchar sector --- 24位地址线的高8位
*输出参数: void
*函数功能: 根据输入地址线的数据对相应地址线置位,本函数对
* SRAM、FLASH的地址操作有效
*************************************************************/
void select_sector(uchar sector)
{
uchar x;
if(sector >15)
{
if(sector>31) //置位 A21
SetupPortA(A21,1);
else
SetupPortA(A21,0);
A20=1; //置位 A20
}
else
{
SetupPortA(A21,0);
A20=0;
}
x=sector&0x0f; //x 低四位对应 a16 a17 a18 a19
P4&=0x07; //保留P4的低三位
x<<=4;
x&=0xf0;
P4|=x;
if(A15)P4|=0x08;
}
/*************************************************************
*函数名称: read_sramb(ulong addr,uint leng,void *buf)
*输入参数: ulong addr --- 24位地址
* uint leng --- 读数据的长度
* void *buf --- 指针,把读出的数据存放在此空间
*返回值 : uchar 1 --- 读SRAM失败(地址有误)
0 --- 读SRAM成功
*函数功能: 读出leng长度的,以addr为首地址的,存放在SRAM的数据,
* 并存放在 *buf 指向的空间
*************************************************************/
uchar read_sramb(ulong addr,uint leng,void *buf)
{
uchar sector;
uint rd_addr;//addr0;
uchar EAStatus;
sector=*((uchar *)(&addr)+1); // 取页面地址
rd_addr=(uint)addr; // 取地址指针
if(sector >8) return(1);
if((addr + leng -1) > 0x80000) return(1);
EAStatus = EA;
EA = 0;
if(rd_addr & 0x8000) A15 = 1;
else A15 = 0;
rd_addr = rd_addr & 0x7fff;
select_sector(sector);
flash_r_addr = rd_addr;
do
{
if(flash_r_addr & 0x8000)
{
flash_r_addr=0;
A15=~A15;
if(!A15) sector++;
select_sector(sector);
}
PSD8xx_reg.PAGE&=0x7f;
flash_r_data = XBYTE[flash_r_addr];
_nop_ ( );
_nop_ ( );
*((uchar*)buf) = flash_r_data;
((uchar*)buf)++;
flash_r_addr++;
}while(--leng);
PSD8xx_reg.PAGE|=0x80;
EA = EAStatus;
return(0);
}
/*************************************************************
*函数名称: write_sramb(ulong addr,uint leng,void *buf)
*输入参数: ulong addr --- 24位地址
* uint leng --- 读数据的长度
* void *buf --- 指针,要写入的数据存放在此空间
*返回值 : uchar 0 --- 写SRAM成功
* 1 --- 写SRAM失败(地址有误)
* 2 --- 写SRAM失败(校验有误)
*函数功能: 把存放在指向 *buf 的空间的、leng长度的数据,
* 写入以addr为首地址的SRAM中
*************************************************************/
uchar write_sramb(ulong addr,uint leng,void *buf)
{
uchar sector;
uint rd_addr;
uchar EAStatus;
sector=*((uchar *)(&addr)+1); // 取页面地址
rd_addr=(uint)addr; // 取地址指针
//send_char(sector);
if(sector >7) return(1);
if((addr + leng -1) > 0x80000) return(1);
EAStatus = EA;
EA = 0;
if(rd_addr & 0x8000) A15 = 1;
else A15 = 0;
rd_addr = rd_addr & 0x7fff;
select_sector(sector);
flash_r_addr = rd_addr;
do
{
if(flash_r_addr & 0x8000)
{
flash_r_addr=0;
A15=~A15;
if(!A15) sector++;
select_sector(sector);
}
PSD8xx_reg.PAGE&=0x7f;
XBYTE[flash_r_addr]=*((uchar*)buf);
delayms(1) ;
PSD8xx_reg.PAGE&=0x7f;
flash_r_data = XBYTE[flash_r_addr];
if(flash_r_data != *((uchar*)buf)) {PSD8xx_reg.PAGE&=0x7f; return(2); }// Write_FAU_data(6,WRITE_SRAM_FAIL);
((uchar*)buf)++;
flash_r_addr++;
}while(--leng);
PSD8xx_reg.PAGE|=0x80;
EA = EAStatus;
return(0);
}
//===================FLASH驱动程序===================================//
// 本部分为HY29LV320驱动
// 此芯片为4M BYTE 并行 FLASH
uchar sector_blank_check(ulong _sector_addr)
{
uchar sector;
uint addr;
uchar EAStatus;
sector=*((uchar *)(&_sector_addr)+1); // 取页面地址
addr=(uint)_sector_addr; // 取地址指针
EAStatus = EA;
EA = 0;
if(addr & 0x8000) A15 = 1;
else A15 = 0;
addr = addr & 0x7fff;
if(_sector_addr<0x010000) //第 0---7 个扇区,每扇区8K BYTE
{
select_sector(sector);
addr = addr&0xe000;
for(flash_r_addr=0;flash_r_addr<0x2000;flash_r_addr++)
{
_nop_ ( );
PSD8xx_reg.PAGE|=0x80;
flash_r_data = XBYTE[flash_r_addr+addr];
PSD8xx_reg.PAGE&=0x7f;
_nop_ ( );
_nop_ ( );
if(flash_r_data!=0xff)
{
EA = EAStatus;
return (1);
}
}
}
else //其他扇区,每扇区64K BYTE
{
A15=0;
do
{
select_sector(sector);
for(flash_r_addr=0;flash_r_addr<0x8000;flash_r_addr++)
{
_nop_ ( );
PSD8xx_reg.PAGE|=0x80;
flash_r_data = XBYTE[flash_r_addr];
PSD8xx_reg.PAGE&=0x7f;
_nop_ ( );
_nop_ ( );
if(flash_r_data!=0xff)
{
EA = EAStatus;
return (1);
}
}
A15=~A15;
}while(A15);
}
EA = EAStatus;
return(0);
}
/************************************************************************/
/* PROCEDURE: Erase_One_Block */
/* */
/* This procedure can be used to erase a total of 64K words. */
/* */
/* Input: */
/* Dst DESTINATION address where the erase operation starts */
/* */
/* Output: */
/* NONE */
/************************************************************************/
uchar flash_sector_erase(uchar erase_sector_num)
{
ulong erase_addr;
uchar sector;
uint addr;
uchar EAStatus;
if(erase_sector_num<23) //字库及预留区,不允许操作,前28个扇区
return(1);
erase_addr = 0x100000 + (ulong)(erase_sector_num - 23)*0x10000;
sector=*((uchar *)(&erase_addr)+1); // 取页面地址
addr=(uint)erase_addr; // 取地址指针
EAStatus = EA;
EA = 0;
if(addr & 0x8000) A15 = 1;
else A15 = 0;
addr = addr&0x7fff;
select_sector(sector);
_nop_ ( );
_nop_ ( );
PSD8xx_reg.PAGE|=0x80;
XBYTE[0xaaa] = 0xaa;
XBYTE[0x555] = 0x55;
XBYTE[0xaaa] = 0x80;
XBYTE[0xaaa] = 0xaa;
XBYTE[0x555] = 0x55;
XBYTE[addr] = 0x30;
PSD8xx_reg.PAGE&=0x7f;
delay_ms(50) ;
if( sector_blank_check(erase_addr) ){ return (1);}//Write_FAU_data(6,ERASE_FLASH_FAIL);
EA = EAStatus;
return(0);
}
/************************************************************************/
/* PROCEDURE: Erase_Entire_Chip */
/* */
/* This procedure can be used to erase the entire chip. */
/* */
/* Input: */
/* NONE */
/* */
/* Output: */
/* NONE */
/************************************************************************/
/*uchar flash_chip_erase(void)
{
uchar i;
reset_addr();
_nop_ ( );
_nop_ ( );
P4_1 = 0;
PSD8xx_reg.PAGE|=0x80;
XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0xaa;
XBYTE[0x555+PSD_REG_ADDR+0x100] = 0x55;
XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0x80;
XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0xaa;
XBYTE[0x555+PSD_REG_ADDR+0x100] = 0x55;
XBYTE[0xaaa+PSD_REG_ADDR+0x100] = 0x10;
P4_1 = 1;
PSD8xx_reg.PAGE&=0x7f;
_nop_ ( );
_nop_ ( );
for(i=0; i<10; i++)
{
delay_ms(4) ;
}
//if( check_toggle_bit(0x8000) ) return (1);
for(i=0x00;i<0x20;i++)
if( sector_blank_check(i) ) return (1);
return(0);
}
*/
//================================================================================
uchar write_flash_abyte(uint addr,uchar abyte)
{
uchar k,i,j,cnt;
k=2;
while(k) //不成功写几遍
{
flash_w_data = abyte;
flash_w_addr = addr;
PSD8xx_reg.PAGE|=0x80;
XBYTE[0xaaa] = 0xaa;
XBYTE[0x555] = 0x55;
XBYTE[0xaaa] = 0xa0;
XBYTE[flash_w_addr] =flash_w_data;
PSD8xx_reg.PAGE&=0x7f;
//=============================================
PSD8xx_reg.PAGE|=0x80;
cnt = 50;
while(cnt)
{
cnt--;
i = XBYTE[flash_w_addr];
j = XBYTE[flash_w_addr];
if((i&0x40) != (j&0x40)) //D6 == D6
continue;
i = XBYTE[flash_w_addr];
if((i&0x80)==(flash_w_data&0x80))
break; //D7 == D7
}
PSD8xx_reg.PAGE&=0x7f;
//=============================================
PSD8xx_reg.PAGE|=0x80;
flash_r_data =XBYTE[flash_w_addr];
PSD8xx_reg.PAGE&=0x7f;
if(flash_r_data == flash_w_data){ return (0);}// check_write_flash
else {k--;}
}
return (1);
}
//========================================================================
//将SRAM中leng长度的数据写到FLASH指定单元,写入正确返回0,否则返回1
//注意:如果被写的地址的数据不是0XFF可能会造成FLASH一直忙,会造成读出错
uchar write_flash(ulong wr_addr,uint wr_length,void *wr_buf)
{
uchar sector;
uint addr;
uchar EAStatus;
sector=*((uchar *)(&wr_addr)+1); // 取页面地址
addr=(uint)wr_addr; // 取地址指针
// if((sector >34)||(sector<4)) return(1);//0-3 为字库需要保护4-7 为安全审计记录
// if((wr_addr + wr_length - 1) > 0x1fffff) return(1);
if(wr_addr<0x100000) //字库及预留区,不允许操作,前23个扇区
return(1);
EAStatus = EA;
EA = 0;
if(addr & 0x8000) A15 = 1;
else A15 = 0;
//write_data_flg=1; //掉电时给出的标志 掉电有用
addr = addr & 0x7fff;
select_sector(sector);
do
{
if(addr&0x8000)
{
addr=0X00;
A15=~A15;
if(!A15) sector++;
select_sector(sector);
}
if( write_flash_abyte(addr,*((uchar*)wr_buf)))
{
EA = EAStatus;
return (2);
}
else
{
if(low_pwr==1) {shut_bat(0);}//low_pwr=2;
((uchar*)wr_buf)++;
addr++;
}
}while(--wr_length);
EA = EAStatus;
return(0);
}
//==========================================================================
// 将FLASH中leng长度的数据写到SRAM指定单元,写入正确返回0,否则返回1
uchar read_flash(ulong rd_addr, uint rd_length, void *rd_buf)
{
uchar sector;
uint addr;
uchar EAStatus;
sector=*((uchar *)(&rd_addr)+1); // 取页面地址
addr=(uint)rd_addr; // 取地址指针
// if(sector > 34)
// return(1);
if((rd_addr + rd_length -1) > 0x3fffff)
return(1);
EAStatus = EA;
EA = 0;
if(addr & 0x8000)
A15 = 1;
else
A15 = 0;
addr = addr & 0x7fff;
select_sector(sector);
flash_r_addr = addr;
do
{
if(flash_r_addr & 0x8000)
{
flash_r_addr=0;
A15=~A15;
if(!A15) sector++;
select_sector(sector);
}
_nop_ ( );
_nop_ ( );
_nop_ ( );
PSD8xx_reg.PAGE|=0x80;
flash_r_data = XBYTE[flash_r_addr];
PSD8xx_reg.PAGE&=0x7f;
_nop_ ( ); _nop_ ( );
*((uchar*)rd_buf) =flash_r_data;
((uchar*)rd_buf)++;
flash_r_addr++;
}while(--rd_length);
EA = EAStatus;
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -