📄 nand.c
字号:
/* Command sets */#define CMD_SEQ_DIN 0x80 /* Sequencial Data Input command */#define CMD_READ0 0x00 /* 1'st half address command */#define CMD_READ1 0x01 /* 2'st half address command */#define CMD_READ2 0x50 /* Spare area command */#define CMD_ID 0x90 /* ID command */#define CMD_RESET 0xff /* Reset command */#define CMD_PAGE_PGM 0x10 /* Page program command */#define CMD_BLK_ERASE1 0x60 /* Block erase command1 */#define CMD_BLK_ERASE2 0xd0 /* Block erase command2 */#define CMD_STATUS 0x70 /* Read status command */#define CLE (0x20) /* GPF5 */#define ALE (0x40) /* GPF6 */#define RB (0x80) /* GPF7 */volatile unsigned char *nand_base = 0x04000000;void nand_cmd(int cmd){ int i; REG(PDATF) |= CLE; REG(PDATF) &=~ALE; *nand_base = (unsigned char)cmd; for(i=0; i<5; i++);}void nand_paddr(int addr){ int i; REG(PDATF) |= ALE; REG(PDATF) &=~CLE; *nand_base = 0; *nand_base = (unsigned char)addr&0xff; *nand_base = (unsigned char)(addr>>8)&0x7f; for(i=0; i<5; i++);}void nand_baddr(int addr){ int i; REG(PDATF) |= ALE; REG(PDATF) &=~CLE; *nand_base = (unsigned char)addr&0xff; *nand_base = (unsigned char)(addr>>8)&0x7f; for(i=0; i<5; i++);}void nand_eraseblock(int baddr){ nand_cmd(CMD_BLK_ERASE1); nand_baddr(baddr<<5); nand_cmd(CMD_BLK_ERASE2); REG(PDATF) &= ~(ALE|CLE); while(!(REG(PDATF)&RB)); nand_cmd(CMD_STATUS); REG(PDATF) &= ~(ALE|CLE); if((*nand_base)&1){ SerialOutputString("\nErase block error!\n\n"); }}void nand_verifypage(int paddr, char *buf){ int i; char rb[528]; nand_cmd(CMD_READ0); nand_paddr(paddr); REG(PDATF) &= ~(ALE|CLE); while(!(REG(PDATF)&RB)); for(i=0; i<512; i++){ rb[i] = *nand_base; } for(i=0; i<512; i++){ if(buf[i] != rb[i]){ SerialOutputString("Verify Page error: "); SerialOutputHex(paddr); SerialOutputString("\n"); return; } }}void nand_readpage(int paddr, char *buf){ int i; nand_cmd(CMD_READ0); nand_paddr(paddr); REG(PDATF) &= ~(ALE|CLE); while(!(REG(PDATF)&RB)); for(i=0; i<512; i++){ buf[i] = *nand_base; }}void nand_writepage(int paddr, char *buf){ int i; nand_cmd(CMD_SEQ_DIN); nand_paddr(paddr); REG(PDATF) &= ~(ALE|CLE); for(i=0; i<512; i++){ *nand_base = buf[i]; } nand_cmd(CMD_PAGE_PGM); while(!(REG(PDATF)&RB)); nand_cmd(CMD_STATUS); if((*nand_base)&1){ SerialOutputString("\nWrite block error!\n\n"); }}int nand_readid(void){ int id = 0, i; nand_cmd(CMD_ID); REG(PDATF) |= ALE; REG(PDATF) &=~CLE; *nand_base = 0; REG(PDATF) &= ~(ALE|CLE); for(i=0; i<5; i++); //wait 100ns id = (*nand_base)<<8; id += *nand_base; SerialOutputString("\nNAND FLASH ID: "); SerialOutputHex(id); SerialOutputString("\n"); return id;}void nand_write(char *dst, char *src, int nword){ int block, page; nword >>= 12; nword ++; block = (int)dst>>14; nword += block; SerialOutputString("nand_write: from "); SerialOutputHex(block); SerialOutputString(" to "); SerialOutputHex(nword); SerialOutputString("\n"); for(; block<nword; block++){ nand_eraseblock(block); for(page=0; page<32; page++){ nand_writepage((block<<5)+page, src); nand_verifypage((block<<5)+page, src); src += 512; } }}void nand_read(char *dst, char *src, int nword){ int block, page; nword >>= 12; nword ++; block = (int)src>>14; nword += block; for(; block<nword; block++){ for(page=0; page<32; page++){ nand_readpage((block<<5)+page, dst); dst += 512; } }}void nand_test(void){ int i, j, p; char buf[528]; for(i=0; i<1024; i++){ nand_eraseblock(i); for(j=0; j<32; j++){ nand_readpage((i<<5)+j, buf); for(p=0; p<512; p++){ if(buf[p] != 0xff){ SerialOutputString("Bad Page: "); SerialOutputHex((i<<5)+j); SerialOutputString("\n"); break; } } } }} static int dmaddr;static int dm(int argc, char *argv[]){ int i, j, data; if(argc == 2){ strtou32(argv[1], &dmaddr); } for(i=0; i<16; i++){ SerialOutputHex(dmaddr); SerialOutputString(": "); for(j=0; j<16; j+=4){ data = *(int *)dmaddr; SerialOutputHex(data); SerialOutputString(" "); dmaddr += 4; } SerialOutputString("\n"); } return 0;}static char dmhelp[] = "dm {address}\n""dump memory as word\n";__commandlist(dm, "dm", dmhelp);static int wb(int argc, char *argv[]){ int wbaddr; int data; if(argc == 3){ strtou32(argv[1], &wbaddr); strtou32(argv[2], &data); }else{ return -1; } *(unsigned char*)wbaddr = (unsigned char)data; SerialOutputHex(wbaddr); SerialOutputString(": "); data = *(unsigned char*)wbaddr; SerialOutputHex(data); SerialOutputString("\n"); return 0;}static char wbhelp[] = "wb {address} {data}\n""write byte to memory\n";__commandlist(wb, "wb", wbhelp);static int dbaddr;static int db(int argc, char *argv[]){ int i, j; unsigned char data; if(argc == 2){ strtou32(argv[1], &dbaddr); }/* SerialOutputHex(dbaddr); SerialOutputString(": "); data = *(unsigned char*)dbaddr; SerialOutputHex(data); SerialOutputString("\n"); dbaddr ++;*/ for(i=0; i<8; i++){ SerialOutputHex(dbaddr); SerialOutputString(": "); for(j=0; j<8; j++){ data = *(unsigned char*)dbaddr; SerialOutputHex(data); SerialOutputString(" "); dbaddr += 1; } SerialOutputString("\n"); } return 0;}static char dbhelp[] = "db {address}\n""dump memory as byte\n";__commandlist(db, "db", dbhelp);static int ne(int argc, char *argv[]){ int blk1, blk2; int i, j, p; char buf[528]; if(argc == 2){ strtou32(argv[1], &blk1); blk2 = blk1; }else if(argc == 3){ strtou32(argv[1], &blk1); strtou32(argv[2], &blk2); } for(i=blk1; i<=blk2; i++){ nand_eraseblock(i); for(j=0; j<32; j++){ nand_readpage((i<<5)+j, buf); for(p=0; p<512; p++){ if(buf[p] != 0xff){ SerialOutputString("Bad Page: "); SerialOutputHex((i<<5)+j); SerialOutputString("\n"); break; } } } } return 0;}static char nehelp[] = "ne {blk1} {blk2}\n""erase nand flash from block blk1 to blk2\n";__commandlist(ne, "ne", nehelp);static int nraddr;static int nr(int argc, char *argv[]){ int i, j; char buf[528]; if(argc == 2){ strtou32(argv[1], &nraddr); } nand_readpage(nraddr, buf); for(i=0; i<512; i+=16){ SerialOutputHex(i); SerialOutputString(": "); for(j=i; j<i+16; j+=4){ SerialOutputHex(*(int *)(buf+j)); SerialOutputString(" "); } SerialOutputString("\n"); } nraddr ++; return 0;}static char nrhelp[] = "nr {page}\n""read nand page\n";__commandlist(nr, "nr", nrhelp);static int nwaddr, nwmaddr;static int nw(int argc, char *argv[]){ char buf[528]; if(argc == 2){ strtou32(argv[1], &nwaddr); }else if(argc == 3){ strtou32(argv[1], &nwaddr); strtou32(argv[2], &nwmaddr); } nand_writepage(nwaddr, (char *)nwmaddr); nand_verifypage(nwaddr, (char *)nwmaddr); nwaddr ++; nwmaddr += 512; return 0;}static char nwhelp[] = "nw {page} {address}\n""write memory data to nand flash page\n";__commandlist(nw, "nw", nwhelp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -