📄 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 + -