📄 nandflash.c
字号:
#include <cdefBF561.h>
#include "nandflash.h"
int pf_direction(int pf, int pf_direction)
{
volatile unsigned short int *dirc_register;
if(pf_direction != 0 && pf_direction != 1) return 0;
if(pf>=0&&pf<=47)
{
if(pf<=15&&pf>=0) dirc_register = FIO0_DIR;
else if(pf<=31&&pf>=16) { dirc_register = FIO1_DIR; pf -= 16;}
else if(pf<=47&&pf>=32) { dirc_register = FIO2_DIR; pf -= 32;}
if(pf_direction) { *dirc_register |= (0x1<<pf);}
else {*dirc_register &= (0xffff - (0x1<<pf));}
}
else return 0;
}
int pf_outset(int pf, int setdata)
{
volatile unsigned short int *tempregister;
if(setdata != 0 && setdata != 1) return 0;
if(pf>=0&&pf<=47)
{
if(pf<=15&&pf>=0) tempregister = FIO0_FLAG_D;
else if(pf<=31&&pf>=16) { tempregister = FIO1_FLAG_D; pf -= 16;}
else if(pf<=47&&pf>=32) { tempregister = FIO2_FLAG_D; pf -= 32;}
if(setdata) { *tempregister |= (0x1<<pf);return 1;}
else {*tempregister &= (0xffff - (0x1<<pf));return 1;}
}
else return 0;
}
int pf_set(int pf)
{
volatile unsigned short int *tempregister;
if(pf>=0&&pf<=47)
{
if(pf<=15&&pf>=0) {tempregister = FIO0_FLAG_S;
*tempregister |= (0x1<<pf);
//++
delay(2);
*tempregister &=0x0;
tempregister = FIO0_FLAG_C;
*tempregister &=0x0;
tempregister = FIO0_FLAG_T;
*tempregister &=0x0;
}
else if(pf<=31&&pf>=16) { tempregister = FIO1_FLAG_S;pf -= 16;
*tempregister |= (0x1<<pf);
//++
delay(2);
*tempregister &=0x0;
tempregister = FIO1_FLAG_C;
*tempregister &=0x0;
tempregister = FIO1_FLAG_T;
*tempregister &=0x0;
}
else if(pf<=47&&pf>=32) { tempregister = FIO2_FLAG_S; pf -= 32;
*tempregister |= (0x1<<pf);
//++
delay(2);
*tempregister &=0x0;
tempregister = FIO2_FLAG_C;
*tempregister &=0x0;
tempregister = FIO2_FLAG_T;
*tempregister &=0x0;
}
// *tempregister |= (0x1<<pf);
}
else return 0;
}
int pf_clear(int pf)
{
volatile unsigned short int *tempregister;
if(pf>=0&&pf<=47)
{
if(pf<=15&&pf>=0) {tempregister = FIO0_FLAG_C;
*tempregister |= (0x1<<pf);
//++
delay(2);
*tempregister &=0x0;
tempregister = FIO0_FLAG_S;
*tempregister &=0x0;
tempregister = FIO0_FLAG_T;
*tempregister &=0x0;
}
else if(pf<=31&&pf>=16) { tempregister = FIO1_FLAG_C; pf -= 16;
*tempregister |= (0x1<<pf);
//++
delay(2);
*tempregister &=0x0;
tempregister = FIO1_FLAG_S;
*tempregister &=0x0;
tempregister = FIO1_FLAG_T;
*tempregister &=0x0;
}
else if(pf<=47&&pf>=32) { tempregister = FIO2_FLAG_C; pf -= 32;
*tempregister |= (0x1<<pf);
//++
delay(2);
*tempregister &=0x0;
tempregister = FIO2_FLAG_S;
*tempregister &=0x0;
tempregister = FIO2_FLAG_T;
*tempregister &=0x0;
}
// *tempregister |= (0x1<<pf);
}
else return 0;
}
/*
nandflash_cle()
{while(1)
{
pf_outset(cle,1);
pf_set(cle);
delay(100);
pf_clear(cle);
}
}
*/
void delay(int time)
{ if(time <= 0) return 0;
int i;
for(i=0;i<=time;i++) {;}
}
void nandflash_we_on()
{
pf_outset(we,setdata0);
// pf_clear(we);
// delay(50);
// printf("done! ");
// pf_set(we);
//delay(500);
}
void nandflash_we_off()
{
//pf_set(we);
pf_outset(we,setdata1);
}
void nandflash_cle_on()
{
//pf_set(cle);
pf_outset(cle,setdata1);
}
void nandflash_cle_off()
{
//pf_clear(cle);
pf_outset(cle,setdata0);
}
void nandflash_ale_on()
{
//pf_set(ale);
pf_outset(ale,setdata1);
}
void nandflash_ale_off()
{
//pf_clear(ale);
pf_outset(ale,setdata0);
}
void nandflash_re_on()
{
//pf_clear(re);
pf_outset(re,setdata0);
}
void nandflash_re_off()
{
//pf_set(re);
pf_outset(re,setdata1);
}
void nandflash_ce_on()
{
//pf_clear(ce);
pf_outset(ce,setdata0);
}
bool nandflash_ce_off()
{
//pf_set(ce);
if(pf_outset(ce,setdata1))
return true;
else
return false;
}
void nandflash_rb_on()
{
pf_outset(rb,setdata1);
}
void nandflash_rb_off()
{
pf_outset(rb,setdata0);
}
int nandflash_init()
{
// *pEBIU_AMGCTL = 0x00F0; //禁用外部存储和SDRAM
// *pEBIU_SDGCTL = 0xE0088848;
// *pEBIU_SDBCTL = 0x0;
if( !pf_direction(we,pf_out)) return 0;
if( !pf_direction(re,pf_out)) return 0;
if( !pf_direction(ale,pf_out)) return 0;
if( !pf_direction(cle,pf_out)) return 0;
if( !pf_direction(rb,pf_in)) return 0;
if( !pf_direction(ce,pf_out)) return 0;
nandflash_ce_on();
}
void create_initial_invalid_block_table()
{
unsigned int Block_Address = 0; //Block_Address 为页地址 Page_Address 为列地址
int block_count = 0; //first_block;
int bad_block_count = 0;
int block_num;
//int num_bad_block;
struct Invalid_Block_Table bad_blocks;
struct Invalid_Block * list_table;
list_table = bad_blocks.value.next;
for(block_num = 2048; block_num != 0 ; block_num--)
{
Block_Address = set_block_address(Block_Address,block_count); //获取模块首地址
block_count = 64;
if(check_is_invalid_block(Block_Address) && check_is_invalid_block(Block_Address+1))
{
if(bad_block_count == 0)
{
bad_blocks.value.bad_block = Block_Address; //添加无效模块表
bad_block_count++;
printf("BAD_BLOCK = %d ,num = %d \n",Block_Address/64,bad_block_count);
}
else
{
struct Invalid_Block * p;
p = (struct Invalid_Block *)malloc(sizeof(struct Invalid_Block));
list_table = p;
list_table->bad_block = Block_Address;
list_table = p->next;
bad_block_count++;
printf("BAD_BLOCK = %d ,num = %d \n",Block_Address/64,bad_block_count);
}
}
}
}
bool check_is_invalid_block(unsigned int Block_Address)
{
int NAND_Addr;
unsigned char pdes;
unsigned short Page_Address = 0x07FF; //2048列
NAND_Addr = (Block_Address << 12) | Page_Address;
pdes = check_block_read(NAND_Addr);
if((pdes) == 0xFF || (pdes) == 0xFFFF) //比较地址后标志。
{
return false;
}
else
return true;
}
unsigned int set_block_address(unsigned int Block_Address ,int block_count)
{
Block_Address += block_count;
return Block_Address;
}
void write_command(unsigned char command)
{
nandflash_cle_on();
nandflash_we_on();
nandflash_ale_off();
nandflash_re_off();
delay(3);//初始延迟>20ns
write_flash_command(command);
nandflash_we_off();
nandflash_cle_off();
}
void write_flash_command(unsigned char write_data)
{
*pNAND_COMMAND_REG = write_data;
delay(50);//延迟>30ns
}
void write_addr(int nand_addr)
{
unsigned char addr;
addr = (unsigned char)(nand_addr & 0x000000FF); //NAND_Address_A0_A7
nandflash_ale_on();
nandflash_we_on();
nandflash_cle_off();
nandflash_re_off();
delay(5);//setup time 延迟>20ns
write_flash_addr(addr);
nandflash_we_off();
nandflash_ale_off();
addr = (unsigned char)((nand_addr >> 8) & 0x0000000F);//NAND_Address_A8_A11
nandflash_ale_on();
nandflash_we_on();
nandflash_cle_off();
nandflash_re_off();
delay(5);//setup time 延迟>20ns
write_flash_addr(addr);
nandflash_we_off();
nandflash_ale_off();
addr = (unsigned char)((nand_addr >> 12) & 0x000000FF);//NAND_Address_A12_A19
nandflash_ale_on();
nandflash_we_on();
nandflash_cle_off();
nandflash_re_off();
delay(5);//setup time 延迟>20ns
write_flash_addr(addr);
nandflash_we_off();
nandflash_ale_off();
addr = (unsigned char)((nand_addr >> 20) & 0x000000FF);//NAND_Address_A20_A27
nandflash_ale_on();
nandflash_we_on();
nandflash_cle_off();
nandflash_re_off();
delay(5);//setup time 延迟>20ns
write_flash_addr(addr);
nandflash_we_off();
nandflash_ale_off();
addr = (unsigned char)((nand_addr >> 28) & 0x00000001);//NAND_Address_A28
nandflash_ale_on();
nandflash_we_on();
nandflash_cle_off();
nandflash_re_off();
delay(5);//setup time 延迟>20ns
write_flash_addr(addr);
nandflash_we_off();
nandflash_ale_off();
}
void write_flash_addr(unsigned char addr)
{
*pNAND_ADDRESS_REG = addr;
delay(50);//延迟>30ns
}
bool Page_data_read(unsigned int Block_Address,unsigned short Page_Address,unsigned char *pdes)
{
int i;
int NAND_Addr;
NAND_Addr = (Block_Address << 12) | Page_Address;
//int DATA_NUM = 2048 - Page_Address;
int DATA_NUM = 5;
write_command(0x00);
write_addr(NAND_Addr);//修改
write_command(0x30);
Wait_NAND_RADY(rb); //内部写页寄存器结束 进入i/o传输
for(i = 0;i<DATA_NUM;i++)
{
delay(500); //读周期>30ns
*(pdes+i) = ReadByte();
}
return true;
}
bool Page_data_write(unsigned int Block_Address,unsigned short Page_Address,unsigned char *psrc)
{
int i;
unsigned char NAND_Data;
int NAND_Addr;
int DATA_NUM = strlen(psrc);
NAND_Addr = (Block_Address << 12) | Page_Address;
// Table.current.value = NAND_Addr;
write_command(0x80);
write_addr(NAND_Addr);
delay(50); //写数据之前均要延迟>100ns
for(i = 0;i<DATA_NUM;i++)
{
delay(100);//写周期>30ns ,max program time= 700 us
nandflash_we_on();
nandflash_cle_off();
nandflash_ale_off();
nandflash_re_off();
delay(2);//使能延迟20ns
*pNAND_DATA_REG = *(psrc+i);
nandflash_we_off();
printf("commit data = %x\n",*(psrc+i));
}
write_command(0x10);
Wait_NAND_RADY(rb);//页寄存器内部写结束 进入状态读写
NAND_Data = statue_read();
if(NAND_Data != 0xe0)
return false;
else
return true;
}
bool nd_block_erase(unsigned int Block_Address)
{
unsigned char NAND_Data = 0;
unsigned int address;
address = Block_Address << 12;
write_command(0x60);
write_addr(address);
write_command(0xd0);
delay(500000);//擦除模块延迟<3ms
//前面为擦除执行
NAND_Data = statue_read();
if(NAND_Data != 0xe0)//0xc0
return false;
else
return true;
}
void Wait_NAND_RADY(int pf)
{
volatile unsigned short int *tempregister;
tempregister = FIO1_FLAG_D;
pf -= 16;
while(!(*tempregister & (1<<0)));//ready
}
void NAND_Finish(int pf)
{
volatile unsigned short int *tempregister;
tempregister = FIO1_FLAG_D;
pf -= 16;
while(*tempregister & (1<<0));//busy
}
unsigned char check_block_read(int NAND_Addr)
{
unsigned char rdata;
write_command(0x00);
write_addr(NAND_Addr);//修改
write_command(0x30);
(rb); //页寄存器写入结束 进入 i/o传输
rdata = ReadByte();
return rdata;
}
unsigned char statue_read(void)
{
unsigned char rdata;
write_command(0x70);
delay(50); //状态寄存器写入延迟
rdata = ReadByte();
return rdata;
}
unsigned char ReadByte(void)
{
unsigned char Rdata;
nandflash_re_on();
nandflash_we_off();
nandflash_ale_off();
nandflash_cle_off();
delay(4);//延迟>35ns
delay(50);
Rdata = *pNAND_DATA_REG;
delay(50);//读周期延迟>30ns
nandflash_re_off();
printf("Rdata = %x \n",Rdata);
return Rdata;
}
bool nandflash_exit()
{
if(nandflash_ce_off())
return true;
else
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -