?? flash.c
字號(hào):
#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;
//注意:對(duì)于XBYTE[]的操作的偏移地址是仿真器的需要,實(shí)際CUP不需要
// 檢查指定扇區(qū)是否空,扇區(qū)空返回0
//=======================================================================
//===========SRAM讀寫驅(qū)動(dòng)====================================//
/*************************************************************
*函數(shù)名稱: select_sector(uchar sector)
*輸入?yún)?shù): uchar sector --- 24位地址線的高8位
*輸出參數(shù): void
*函數(shù)功能: 根據(jù)輸入地址線的數(shù)據(jù)對(duì)相應(yīng)地址線置位,本函數(shù)對(duì)
* 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 低四位對(duì)應(yīng) a16 a17 a18 a19
P4&=0x07; //保留P4的低三位
x<<=4;
x&=0xf0;
P4|=x;
if(A15)P4|=0x08;
}
/*************************************************************
*函數(shù)名稱: read_sramb(ulong addr,uint leng,void *buf)
*輸入?yún)?shù): ulong addr --- 24位地址
* uint leng --- 讀數(shù)據(jù)的長(zhǎng)度
* void *buf --- 指針,把讀出的數(shù)據(jù)存放在此空間
*返回值 : uchar 1 --- 讀SRAM失敗(地址有誤)
0 --- 讀SRAM成功
*函數(shù)功能: 讀出leng長(zhǎng)度的,以addr為首地址的,存放在SRAM的數(shù)據(jù),
* 并存放在 *buf 指向的空間
*************************************************************/
uchar read_sramb(ulong addr,uint leng,void *buf)
{
uchar sector;
uint rd_addr;//addr0;
uchar EAStatus;
sector=*((uchar *)(&addr)+1); // 取頁(yè)面地址
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);
}
/*************************************************************
*函數(shù)名稱: write_sramb(ulong addr,uint leng,void *buf)
*輸入?yún)?shù): ulong addr --- 24位地址
* uint leng --- 讀數(shù)據(jù)的長(zhǎng)度
* void *buf --- 指針,要寫入的數(shù)據(jù)存放在此空間
*返回值 : uchar 0 --- 寫SRAM成功
* 1 --- 寫SRAM失敗(地址有誤)
* 2 --- 寫SRAM失敗(校驗(yàn)有誤)
*函數(shù)功能: 把存放在指向 *buf 的空間的、leng長(zhǎng)度的數(shù)據(jù),
* 寫入以addr為首地址的SRAM中
*************************************************************/
uchar write_sramb(ulong addr,uint leng,void *buf)
{
uchar sector;
uint rd_addr;
uchar EAStatus;
sector=*((uchar *)(&addr)+1); // 取頁(yè)面地址
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驅(qū)動(dòng)程序===================================//
// 本部分為HY29LV320驅(qū)動(dòng)
// 此芯片為4M BYTE 并行 FLASH
uchar sector_blank_check(ulong _sector_addr)
{
uchar sector;
uint addr;
uchar EAStatus;
sector=*((uchar *)(&_sector_addr)+1); // 取頁(yè)面地址
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 個(gè)扇區(qū),每扇區(qū)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 //其他扇區(qū),每扇區(qū)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) //字庫(kù)及預(yù)留區(qū),不允許操作,前28個(gè)扇區(qū)
return(1);
erase_addr = 0x100000 + (ulong)(erase_sector_num - 23)*0x10000;
sector=*((uchar *)(&erase_addr)+1); // 取頁(yè)面地址
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中l(wèi)eng長(zhǎng)度的數(shù)據(jù)寫到FLASH指定單元,寫入正確返回0,否則返回1
//注意:如果被寫的地址的數(shù)據(jù)不是0XFF可能會(huì)造成FLASH一直忙,會(huì)造成讀出錯(cuò)
uchar write_flash(ulong wr_addr,uint wr_length,void *wr_buf)
{
uchar sector;
uint addr;
uchar EAStatus;
sector=*((uchar *)(&wr_addr)+1); // 取頁(yè)面地址
addr=(uint)wr_addr; // 取地址指針
// if((sector >34)||(sector<4)) return(1);//0-3 為字庫(kù)需要保護(hù)4-7 為安全審計(jì)記錄
// if((wr_addr + wr_length - 1) > 0x1fffff) return(1);
if(wr_addr<0x100000) //字庫(kù)及預(yù)留區(qū),不允許操作,前23個(gè)扇區(qū)
return(1);
EAStatus = EA;
EA = 0;
if(addr & 0x8000) A15 = 1;
else A15 = 0;
//write_data_flg=1; //掉電時(shí)給出的標(biāo)志 掉電有用
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中l(wèi)eng長(zhǎng)度的數(shù)據(jù)寫到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); // 取頁(yè)面地址
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);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -