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

📄 nand.c

📁 使用物理地址方式绕开mtd驱动进行nand flash的低级格式化和维护可以修复nand 坏块(不是物理损坏而是由于文件系统造成的坏块)
💻 C
字号:
/********************************************************************//*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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -