⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nandflash.c

📁 实现nandflash的简单驱动函数 adi blackfin561 与三星公司的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 + -