nand.c

来自「使用物理地址方式绕开mtd驱动进行nand flash的低级格式化和维护可以修复」· C语言 代码 · 共 343 行

C
343
字号
/********************************************************************//*FILENAME: lfn.c                                                   */                                                /*FUNCTION: low level format nand flash  in linux                   *//*DATA    : 2007-1-18 10:22                                         *//*AUR     : ZHANG YI FNEG                                           *//*ORI     : ZZVCOM                                                  *//********************************************************************//*Ver0.01   : 2007-1-18 16:44    能够读出页数据,芯片ID号,状态寄存器内容。*/#include <unistd.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/mman.h>#include <time.h>#include "nand.h"#define  DEBUG_NAND_2#ifdef DEBUG_NAND_1    #define DBG_NAND(fmt, args...)           printf(fmt,## args)#else    #define DBG_NAND(fmt, args...)#endif#ifdef DEBUG_NAND_2    #define DBG_NAND_2(fmt, args...)           printf(fmt,## args)#else    #define DBG_NAND_2(fmt, args...)#endifGPIO_REGISTER * gpio_base;unsigned char * nand_base;u32 fd_gpio,fd_nand;u8  PageBuf[528];struct nand_info nand;volatile u32 delayp;u32 count;void delayt(u32 tm){    u32 i;    for(i=0;i<tm;i++){         delayp = (volatile u32)i;    }}void nand_control(int cmd){	  DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);    switch(cmd){        case NAND_CTL_SETCLE:   		       gpio_base->or=(gpio_base->or |   (0x80000000 >> CLE));   //CL = 1		    break;	      case NAND_CTL_CLRCLE: 		         gpio_base->or=(gpio_base->or & (~(0x80000000 >> CLE)));  //CL = 0		    break;	      case NAND_CTL_SETALE: 		         gpio_base->or=(gpio_base->or |   (0x80000000 >> ALE));   //AL = 1		    break;	      case NAND_CTL_CLRALE: 		         gpio_base->or=(gpio_base->or & (~(0x80000000 >> ALE)));  //AL = 0 		    break;	      case NAND_CTL_SETNCE: 		    break;	      case NAND_CTL_CLRNCE:      		break;    }    delayt(40000);    //usleep(1);}int nand_init (void){    char dev_name[]="/dev/mem";    DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);    count = 0;    fd_gpio = open(dev_name,O_RDWR);    if(fd_gpio<0){         printf("open %s is error\n",dev_name);         return -1;    }    gpio_base = (GPIO_REGISTER *)mmap( 0, 0x32, PROT_READ | PROT_WRITE, MAP_SHARED,fd_gpio, 0x40060000 );    if(gpio_base == NULL){         printf("gpio base mmap is error\n");         close(fd_gpio);         return -1;    }        fd_nand = open(dev_name,O_RDWR);    if(fd_nand<0){         printf("open %s is error\n",dev_name);         return -1;    }    nand_base = (unsigned char *)mmap( 0, 1, PROT_READ | PROT_WRITE, MAP_SHARED,fd_nand, 0xfe000000);    if(gpio_base == NULL){         printf("nand base mmap is error\n");         close(fd_nand);         return -1 ;    }            	  gpio_base->tc = (gpio_base->tc | ((0x80000000 >> CLE)|(0x80000000 >> ALE)|(0x80000000 >> WP)));//set CLE,ALE,WP as output pin	  gpio_base->tc = (gpio_base->tc & (~(0x80000000 >> RB))); //set RB as input pin	    gpio_base->osl = (gpio_base->osl & 0xff00ffff);    gpio_base->tsl = (gpio_base->tsl & 0xff00ffff);            gpio_base->od = (gpio_base->od | ((0x80000000 >> CLE)|(0x80000000 >> ALE)|(0x80000000 >> WP)));    gpio_base->or = (gpio_base->or | (0x80000000  >> CLE));   //CL = 1    gpio_base->or = (gpio_base->or | (0x80000000  >> WP));    //WP = 1        return 0;    }u32 Busy(void){	  return gpio_base->ir & (0x80000000 >> RB);}/*u32 Status(void){	  }*/void nand_uninit(void){	  DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);     munmap((GPIO_REGISTER *)gpio_base,0x32);    munmap((unsigned char *)nand_base,1);    close(fd_gpio);    close(fd_nand);}u32 nand_write_addr(u32 addr){    DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);        nand_control(NAND_CTL_SETALE);    #if 1    //printf("address=%08x\r\n",addr);    *nand_base = (unsigned char)(addr        & 0xFF);       //页内地址    *nand_base = (unsigned char)((addr >>8)  & 0xFF);       //页地址    *nand_base = (unsigned char)((addr >>16) & 0xFF);       //块地址    *nand_base = (unsigned char)((addr >>24) & 0xFF);       //块地址    #endif    #if 0    *nand_base = 0;    *nand_base = 0;    *nand_base = 0;    *nand_base = 0;    #endif    #if 0    *nand_base = nand.offset;    *nand_base = nand.page;    *nand_base = nand.block;    #endif    nand_control(NAND_CTL_CLRALE);    return 0;}u32 nand_write_command(u32 command){    DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);    nand_control(NAND_CTL_SETCLE);    *nand_base = (unsigned char)command;    nand_control(NAND_CTL_CLRCLE);    return 0;}u8  nand_read_u8(void){	  return *nand_base ;}u32 read_nand_id(void){	  u8 uData1,uData2;	  DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);	  nand_write_command(READ_IC_SIGNATURE);	  uData1 = nand_read_u8();	  DBG_NAND("MANUFACTURE= %04x,",uData1);	  uData2 = nand_read_u8();	  DBG_NAND("DEVICE= %04x\r\n",uData1);    return uData1 + (uData2<<8);	   }int nand_read_status(void){	  u8 uData;	  DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);	  nand_write_command(READ_STATUS);	  uData = nand_read_u8();	  DBG_NAND("status= %04x\r\n",uData);    return uData;	   }int nand_read_page(u32 addr,u8 *p){	  u32 i;	  u32 address;	  DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);	  nand_write_command(READ_A);	  /*	  Bus  I/O7 I/O6 I/O5 I/O4 I/O3 I/O2 I/O1 I/O0    1st   A7   A6   A5   A4   A3   A2   A1   A0    2nd   A16  A15  A14  A13  A12  A11  A10  A9	  3rd   A24  A23  A22  A21  A20  A19  A18  A17    4th   VIL  VIL  VIL  VIL  VIL  VIL  A26  A25	  */    address  = nand.offset;    address += nand.page  << 8;    address += nand.block << 13;	  nand_write_addr(address);	  	  while(!Busy()){	  	   printf("wait for busy\r\n");	  }	   	  for(i=0;i<256;i++){	  	 p[i] = nand_read_u8();	  }	  for(i=256;i<512;i++){	  	 p[i] = nand_read_u8();	  } 	  for(i=0;i<16;i++){	  	 p[i + 512] = nand_read_u8();	  }	  	  return 0;}int nand_write_page(u32 addr,u8 *p){	  u32 i;	  u32 address;	  u8  uData;	  DBG_NAND_2("ZYF:%s,%s,%d---------------start\r\n",__FILE__,__FUNCTION__,__LINE__);	  nand_write_command(PROGRAM_PAGE);	  /*	  Bus  I/O7 I/O6 I/O5 I/O4 I/O3 I/O2 I/O1 I/O0    1st   A7   A6   A5   A4   A3   A2   A1   A0    2nd   A16  A15  A14  A13  A12  A11  A10  A9	  3rd   A24  A23  A22  A21  A20  A19  A18  A17    4th   VIL  VIL  VIL  VIL  VIL  VIL  A26  A25	  */    address  = nand.offset;    address += nand.page  << 8;    address += nand.block << 13;	  nand_write_addr(address);    /*	  	  while(!Busy()){	  	   printf("wait for busy\r\n");	  }	*/	     	  for(i=0;i<256;i++){	  	 *nand_base = (unsigned char)p[i];	  }	  for(i=256;i<512;i++){	  	 *nand_base = (unsigned char)p[i];	  } 	  for(i=0;i<16;i++){	  	 *nand_base = p[i + 512];	  }	  	  nand_write_command(CONFIRM_PROGRAM);	  while(1){	  	   uData = nand_read_status();	  	   if((uData & 0x01)) printf("program page fail.\r\n");	  	   if((uData & 0x40)) break;	  	   else{	            DBG_NAND_2("wait for erase block\r\n");	  	   }	  	   			  }	  	  DBG_NAND_2("ZYF:%s,%s,%d---------------end\r\n",__FILE__,__FUNCTION__,__LINE__);	  return 0;}u32 nand_erase_addr(u32 addr){    DBG_NAND("ZYF:%s,%s,%d\r\n",__FILE__,__FUNCTION__,__LINE__);        nand_control(NAND_CTL_SETALE);    #if 1    //printf("address=%08x\r\n",addr);    //*nand_base = (unsigned char)(addr        & 0xFF);       //页内地址    *nand_base = (unsigned char)((addr >>8)  & 0xFF);       //页地址    *nand_base = (unsigned char)((addr >>16) & 0xFF);       //块地址    //*nand_base = (unsigned char)((addr >>24) & 0xFF);       //块地址    #endif    #if 0    *nand_base = 0;    *nand_base = 0;    *nand_base = 0;    *nand_base = 0;    #endif    #if 0    *nand_base = nand.offset;    *nand_base = nand.page;    *nand_base = nand.block;    #endif    nand_control(NAND_CTL_CLRALE);    return 0;}int nand_block_erase(u32 addr){	  u8 uData;	  u32 address;	  //DBG_NAND_2("ZYF:%s,%s,%d--------------start\r\n",__FILE__,__FUNCTION__,__LINE__);	  //printf("format block %d  ",nand.block);	  nand_write_command(ERASE_BLOCK);	  	  address  = nand.offset;    address += nand.page  << 8;    address += nand.block << 13;	  nand_erase_addr(address);	  	  nand_write_command(CONFIRM_ERASE);	  	  //nand_read_status();	  /*	  while(!Busy()){	  	   printf("wait for busy\r\n");	  }	*/   	  while(1){	  	   uData = nand_read_status();	  	   if((uData & 0x01)) {                        printf("*");                   }	  	   if((uData & 0x40)) {                        printf(".");                       break;                   }else{	               DBG_NAND_2("wait for erase block\r\n");	   		  	   }	  	   			  }	  //DBG_NAND_2("ZYF:%s,%s,%d--------------end\r\n",__FILE__,__FUNCTION__,__LINE__);                count += 1;                if((count % 32)==0){                    printf("  ");                }                if((count % 64)==0) {                    if(count>0){                        printf(" %02dMB",count/64);                    }                    printf("\r\n");                }	  return 0;}int nand_ic_erase(void){	  u32 i;	  for(i=0;i<2048;i++){	  	  DBG_NAND("----------------------------------------------------block=%d\r\n",i);	      nand_block_erase(i * 16*1024);	  }	  return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?