static int nandll_read_page(unsigned char *buf, unsigned long addr, int large_block) { int i; int page_size = 512; if (large_block) page_size = 2048; show("in this fucn\n"); NF_ENABLE_CE; NF_CLEAR_RB; NF_CMD(NAND_CMD_READ0); NF_ADDR(0x0); if (large_block) NF_ADDR(0x0); /*从0x0地址开始拷贝*/ NF_ADDR(addr & 0xff); NF_ADDR((addr >> 8) & 0xff); NF_ADDR((addr >> 16) & 0xff); if (large_block) NF_CMD(NAND_CMD_READSTART); NF_DETECT_RB; for (i = 0; i < page_size; i++) buf[i] = NF_RDDATA8; NF_DISABLE_CE; return 0; }
static void rLB_ReadPage(U32 addr, unsigned char * to) { U32 i; rNF_Reset(); // Enable the chip NF_nFCE_L(); NF_CLEAR_RB(); // Issue Read command NF_CMD(CMD_READ); // Set up address NF_ADDR(0x00); NF_ADDR(0x00); NF_ADDR((addr) & 0xff); NF_ADDR((addr >> 8) & 0xff); NF_ADDR((addr >> 16) & 0xff); NF_CMD(CMD_READ3); NF_DETECT_RB(); // wait tR(max 12us) for (i = 0; i < 2048; i++) { to[i] = NF_RDDATA8(); } NF_nFCE_H(); }
static int NAND_WritePage(unsigned long block,unsigned long page,unsigned char *buffer) //?Flash { int i; unsigned long blockPage=(block<<5)+page; //NF_RSTECC(); // Initialize ECC unsigned volatile short *NFCONF; unsigned volatile short *NFCMD; unsigned volatile short *NFSTAT; unsigned volatile short *NFADDR; unsigned volatile short *NFDATA; NFCONF=(unsigned short *)0x4e000000; NFCMD=(unsigned short *)0x4e000004; NFSTAT=(unsigned short *)0x4e000010; NFDATA=(unsigned short *)0x4e00000C; NFADDR=(unsigned short *)0x4e000008; NF_nFCE_L(); NF_CMD(0x0); //?????\\Read Mode 1 NF_CMD(0x80); // Write 1st command,?Õu?¤J NF_ADDR(0); // Column 0 NF_ADDR(blockPage&0xff); NF_ADDR((blockPage>>8)&0xff); // Block & page num. NF_ADDR((blockPage>>16)&0xff); for(i=0;i<512;i++) { NF_WRDATA(*buffer++); // Write one page to NFM from buffer } #if 0 seBuf[0]=rNFECC0; seBuf[1]=rNFECC1; seBuf[2]=rNFECC2; seBuf[5]=0xff; // Marking good block for(i=0;i<16;i++) NF_WRDATA(seBuf[i]); // Write spare array(ECC and Mark) #endif NF_CMD(0x10); // Write 2nd command for(i=0;i<10;i++); //tWB = 100ns. ////?????? NF_WAITRB(); //wait tPROG 200~500us; NF_CMD(0x70); // Read status command for(i=0;i<3;i++); //twhr=60ns if (NF_RDDATA()&0x1) { NF_nFCE_H(); return 0; }//error } else { NF_nFCE_H(); return 1; } }
static int NF_WritePage(U32 block,U32 page,U8 *buffer,U8 *spareBuf) { int i; U32 blockPage=(block<<5)+page; U8 *bufPt=buffer; NF_nFCE_L(); NF_CMD(0x0); NF_CMD(0x80); // Write 1st command NF_ADDR(0); // Column 0 NF_ADDR(blockPage&0xff); // NF_ADDR((blockPage>>8)&0xff); // Block & page num. NF_ADDR((blockPage>>16)&0xff); // for(i=0;i<512;i++) { NF_WRDATA(*bufPt++); // Write one page to NFM from buffer } if(spareBuf!=NULL) { for(i=0;i<16;i++) { NF_WRDATA(spareBuf[i]); // Write spare array(ECC and Mark) } } NF_CMD(0x10); // Write 2nd command Delay(1); //tWB = 100ns. NF_WAITRB(); //wait tPROG 200~500us; NF_CMD(0x70); // Read status command Delay(1); //twhr=60ns if (NF_RDDATA()&0x1) // Page write error { NF_nFCE_H(); printf("[PROGRAM_ERROR:block#=%d]\n",block); NF_MarkBadBlock(block); return 0; } else { NF_nFCE_H(); #if (WRITEVERIFY==1) //return NF_VerifyPage(block,page,pPage); #else return 1; #endif } }
char __low_nand_write_page(unsigned int page_addr,unsigned char *from) { U32 i; char nfstatus; unsigned int *pfrom = (unsigned int *)from;//2440的NFADDR寄存器是32位的 // printk("write page addr :%.8x \r\n",page_addr); // __low_nand_reset(); // Enable the chip NF_nFCE_L(); NF_CLEAR_RB(); // Issue Read command NF_CMD(CMD_WRITE1); // Set up address NF_ADDR(page_addr & 0xff); NF_ADDR((page_addr >> 8) & 0x0f); NF_ADDR((page_addr >> 12) & 0xff); NF_ADDR((page_addr >> 20) & 0xff); NF_ADDR((page_addr >> 28) & 0x01); // NF_WRDATA(0xffffffff); // NF_WRDATA(0xffffffff); // NF_WRDATA(0xffffffff); // NF_WRDATA(0xffffffff); for(i = 0;i < (NAND_PAGE_SIZE+64) >> 2;++i) { NF_WRDATA( *((unsigned*)pfrom++)); } NF_CMD(CMD_WRITE2); NF_DETECT_RB(); // wait tR(max 12us) NF_CMD(CMD_STATUS); return (NF_RDDATA8() & 0x01); // nfstatus = NF_RDDATA8(); // NF_nFCE_H(); // printk("nand status:%x\r\n",nfstatus); }
char __low_nand_erase_block(unsigned int row_addr) { NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(CMD_ERASE1); NF_ADDR((row_addr >> 12) & 0xff); NF_ADDR((row_addr >> 20) & 0xff); NF_ADDR((row_addr >> 28) & 0x01); NF_CMD(CMD_ERASE2); NF_DETECT_RB(); NF_CMD(CMD_STATUS); return (NF_RDDATA8() & 0x01); }
static char rNF_ReadID() { char pMID; char pDID; char nBuff; char n4thcycle; int i; NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(CMD_READID); // read id command NF_ADDR(0x0); for ( i = 0; i < 100; i++ ); pMID = NF_RDDATA8(); pDID = NF_RDDATA8(); nBuff = NF_RDDATA8(); n4thcycle = NF_RDDATA8(); NF_nFCE_H(); return (pDID); }
static int NAND_ReadPage(unsigned long block,unsigned long page,unsigned char *buffer) //?Flash { int i; unsigned int blockPage; unsigned volatile short *NFCONF; unsigned volatile short *NFCMD; unsigned volatile short *NFSTAT; unsigned volatile short *NFADDR; unsigned volatile short *NFDATA; NFCONF=(unsigned short *)0x4e000000; NFCMD=(unsigned short *)0x4e000004; NFSTAT=(unsigned short *)0x4e000010; NFDATA=(unsigned short *)0x4e00000C; NFADDR=(unsigned short *)0x4e000008; page=page&0x1f; blockPage=(block<<5)+page; //1Bolck¥]§t32page //NF_RSTECC(); // Initialize ECC NF_nFCE_L(); NF_CMD(0x00); // Read command NF_ADDR(0); // Column = 0 NF_ADDR(blockPage&0xff); // NF_ADDR((blockPage>>8)&0xff); // Block & Page num. NF_ADDR((blockPage>>16)&0xff); // for(i=0;i<10;i++); //wait tWB(100ns) NF_WAITRB(); // Wait tR(max 12us) for(i=0;i<512;i++) { *buffer++=NF_RDDATA(); // Read one page } NF_nFCE_H(); }
static int NF_ReadPage(U32 block,U32 page,U8 *buffer,U8 *spareBuf) { int i; unsigned int blockPage; U8 *bufPt=buffer; page=page&0x1f; blockPage=(block<<5)+page; NF_nFCE_L(); NF_CMD(0x00); // Read command NF_ADDR(0); // Column = 0 NF_ADDR(blockPage&0xff); // NF_ADDR((blockPage>>8)&0xff); // Block & Page num. NF_ADDR((blockPage>>16)&0xff); // Delay(1); //wait tWB(100ns)/////?????? NF_WAITRB(); // Wait tR(max 12us) for(i=0;i<(512);i++) { *bufPt++=NF_RDDATA(); // Read one page } if(spareBuf!=NULL) { for(i=0;i<16;i++) spareBuf[i]=NF_RDDATA(); // Read spare array } NF_nFCE_H(); return 1; }
static int NF_IsBadBlock(U32 block) { unsigned int blockPage; U8 data; blockPage=(block<<5); // For 2'nd cycle I/O[7:5] NF_nFCE_L(); NF_CMD(0x50); // Spare array read command NF_ADDR(517&0xf); // Read the mark of bad block in spare array(M addr=5) NF_ADDR(blockPage&0xff); // The mark of bad block is in 0 page NF_ADDR((blockPage>>8)&0xff); // For block number A[24:17] NF_ADDR((blockPage>>16)&0xff); // For block number A[25] Delay(1); // wait tWB(100ns) NF_WAITRB(); // Wait tR(max 12us) data=NF_RDDATA(); NF_nFCE_H(); if(data!=0xff) { printf("[block %d:bad block(%x)]\n",block,data); return 1; } else { printf("."); return 0; } }
static int NF_MarkBadBlock(U32 block) { int i; U32 blockPage=(block<<5); seBuf[0]=0xff; seBuf[1]=0xff; seBuf[2]=0xff; seBuf[5]=0x44; // Bad blcok mark=0 NF_nFCE_L(); NF_CMD(0x50); NF_CMD(0x80); // Write 1st command NF_ADDR(0x0); // The mark of bad block is NF_ADDR(blockPage&0xff); // marked 5th spare array NF_ADDR((blockPage>>8)&0xff); // in the 1st page. NF_ADDR((blockPage>>16)&0xff); for(i=0;i<16;i++) { NF_WRDATA(seBuf[i]); // Write spare array } NF_CMD(0x10); // Write 2nd command Delay(1); //tWB = 100ns. NF_WAITRB(); // Wait tPROG(200~500us) NF_CMD(0x70); Delay(1); //twhr=60ns// if (NF_RDDATA()&0x1) // Spare arrray write error { NF_nFCE_H(); printf("[Program error is occurred but ignored]\n"); } else { NF_nFCE_H(); } printf("[block #%d is marked as a bad block]\n",block); return 1; }
// int printk(const char *fmt, ...); void __low_nand_reset() { NF_CE_L(); NF_CLEAR_RB(); NF_CMD(CMD_RESET); NF_DETECT_RB(); NF_CE_H(); }
static void nandll_reset(void) { NF_ENABLE_CE; /* 片选使能 */ NF_CLEAR_RB; /* 清除就绪/忙位 */ NF_CMD(NAND_CMD_RESET); /* 写复位命令 */ NF_DETECT_RB; /* 等待复位完成 */ NF_DISABLE_CE; /* 片选禁用 */ }
static void NF_Init(void) { NF_Reset(); //NF_nFCE_L(); NF_CMD(READ_1_1); //NF_nFCE_H(); }
static void NF_Reset() { NF_nFCE_L(); // 片选 Nand Flash 芯片 NF_CLEAR_RB(); // 清除 RnB 信号 NF_CMD( NF_CMD_RST ); // 复位命令 NF_WAIT_RB(); // 等待 RnB 信号变高,即不忙 NF_nFCE_H(); // 取消 Nand Flash 选中 }
// // Reset the chip // static void rNF_Reset() { NF_CE_L(); NF_CLEAR_RB(); NF_CMD(CMD_RESET); NF_DETECT_RB(); NF_CE_H(); }
WORD NF_ReadPage(WORD block,WORD page,BYTE* buffer) { int i; WORD blockPage = (block << 5) + page; BYTE* bufPt = buffer; BYTE ECCbuf[6]; NF_RSTECC(); // 复位 ECC NF_MainECCUnlock(); // 解锁本页 main 区域的 ECC 校验,允许生成 ECC 校验码 NF_nFCE_L(); NF_CLEAR_RB(); // 清 RnB 信号 NF_CMD( NF_CMD_RD1 ); // 从本页的上半部分开始读 NF_ADDR( 0 ); // 从本页的第一个列(字节)开始读 NF_ADDR( blockPage & 0xff ); // 这三行代码指明页号 NF_ADDR( ( blockPage >> 8 ) & 0xff ); NF_ADDR( ( blockPage >> 16 ) & 0xff ); NF_WAIT_RB(); // 往本页的 main 区里写入 buffer 里的内容 for(i=0 ; i<NF_MAINSIZE ; i++) { buffer[i] = NF_RDDATA8(); } NF_MainECCLock(); // 锁定 main 区域的 ECC 校验码 NF_SpareECCUnlock(); // 解锁本页 spare 区域的 ECC 校验 // 读 spare 区域的前4个字节,即 main 区域的 ECC 校验码部分 for(i=0 ; i<4 ; i++) { ECCbuf[i] = NF_RDDATA8(); } NF_SpareECCLock(); // 锁定 spare 区域的 ECC 校验码 // 读 spare 区域的第5,第6个字节,即 spare 区域的 ECC 校验码部分 for(i=4 ; i<6 ; i++) { ECCbuf[i] = NF_RDDATA8(); } /* 下面就是验证 ECC 校验码了 */ if(( ECCbuf[0] == (NFMECCD0 & 0xff)) && ( ECCbuf[1] == ((NFMECCD0 >> 16) & 0xff)) && ( ECCbuf[2] == (NFMECCD1 & 0xff)) && ( ECCbuf[3] == ((NFMECCD1 >> 16) & 0xff)) && ( ECCbuf[4] == (NFSECCD & 0xff)) && ( ECCbuf[5] == ((NFSECCD >> 16) & 0xff))) { // ECC 校验全部成功 NF_nFCE_H(); return 1; } else { // ECC 校验不成功
void SubmitSpareAreaReadCmd(DWORD SectorStartAddr, DWORD SpareStartAddr) { NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(CMD_READ); // Send read command. NF_ADDR((SpareStartAddr)&0xff); NF_ADDR((SpareStartAddr>>8)&0xff); NF_ADDR((SectorStartAddr) & 0xff); NF_ADDR((SectorStartAddr >> 8) & 0xff); if(g_bNeedExtAddr) { NF_ADDR((SectorStartAddr >> 16) & 0xff); } NF_CMD(CMD_READ3); // 2nd command NF_DETECT_RB(); // Wait for command to complete. }
static void NF_Reset(void) { NF_nFCE_L(); NF_CMD(0xFF); //reset command Delay(1); //tWB = 100ns. NF_WAITRB(); //wait 200~500us; NF_nFCE_H(); }
void __low_nand_read_page(unsigned int page_addr,unsigned char *to) { U32 i; char nfstatus; unsigned int *pto = (unsigned int *)to; // printk("read page addr :%.8x \r\n",page_addr); // __low_nand_reset(); // Enable the chip NF_nFCE_L(); NF_CLEAR_RB(); // Issue Read command NF_CMD(CMD_READ); // Set up address NF_ADDR(page_addr & 0xff); NF_ADDR((page_addr >> 8) & 0x0f); NF_ADDR((page_addr >> 12) & 0xff); NF_ADDR((page_addr >> 20) & 0xff); NF_ADDR((page_addr >> 28) & 0x01); NF_CMD(CMD_READ2); NF_DETECT_RB(); // wait tR(max 12us) for (i = 0; i < (NAND_PAGE_SIZE+64) >> 2;++i) { *((unsigned*)pto++) = NF_RDDATA(); } // for (i = 0; i < NAND_PAGE_SIZE ;++i) // { // to[i] = NF_RDDATA8(); // } NF_nFCE_H(); }
static int NF_EraseBlock(U32 block) { U32 blockPage=(block<<5); #if BAD_CHECK if(NF_IsBadBlock(block) && block!=0) //block #0 can't be bad block for NAND boot return 0; #endif NF_nFCE_L(); NF_CMD(0x60); // Erase one block 1st command NF_ADDR(blockPage&0xff); // Page number=0 NF_ADDR((blockPage>>8)&0xff); NF_ADDR((blockPage>>16)&0xff); NF_CMD(0xd0); // Erase one blcok 2nd command Delay(1); //wait tWB(100ns) NF_WAITRB(); // Wait tBERS max 3ms. NF_CMD(0x70); // Read status command if (NF_RDDATA()&0x1) // Erase error { NF_nFCE_H(); printf("[ERASE_ERROR:block#=%d]\n",block); NF_MarkBadBlock(block); return 0; } else { NF_nFCE_H(); return 1; } }
WORD NF_CheckId() { WORD id; NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD( NF_CMD_RDD ); NF_ADDR( 0x0 ); // 指定地址 0x0, 芯片手册要求 NF_WAIT_RB(); id = NF_RDDATA8() << 8; // 厂商 ID id |= NF_RDDATA8(); // 设备 ID NF_nFCE_H(); return id; }
static U16 NF_CheckId(void) { U16 id; NF_nFCE_L(); NF_CMD(0x90); NF_ADDR(0x0); Delay(1); //wait tWB(100ns) id=NF_RDDATA()<<8; // Maker code(K9S1208V:0xec) id|=NF_RDDATA(); // Devide code(K9S1208V:0x76) NF_nFCE_H(); return id; }
char __low_nand_readid(unsigned int *part1,unsigned *part2) { char g_nfid1; char g_nfid2; char g_nfid3; char g_nfid4; char g_nfid5; char pMID; char pDID; char nBuff; char n4thcycle; int i; NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(CMD_READID); // read id command NF_ADDR(0x00); for ( i = 0; i < 100; i++ ); g_nfid1 = NF_RDDATA8(); g_nfid2 = NF_RDDATA8(); g_nfid3 = NF_RDDATA8(); g_nfid4 = NF_RDDATA8(); g_nfid5 = NF_RDDATA8(); pMID = g_nfid1; pDID = g_nfid2; nBuff = NF_RDDATA8(); n4thcycle = NF_RDDATA8(); NF_nFCE_H(); return (pDID); }
BOOL FMD_LB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors) { ULONG SectorAddr = (ULONG)startSectorAddr; DWORD i; volatile DWORD rddata; UINT32 nRetEcc = 0; DWORD MECCBuf[MAX_SECTORS_PER_PAGE]; UINT16 nSectorLoop; int NewSpareAddr = NAND_PAGE_SIZE; int NewDataAddr = 0; int NewSectorAddr = startSectorAddr; DWORD SECCBuf1; // 1st Spare ECC DWORD SECCBuf2; // 2nd Spare ECC(cloned from 1st) BYTE RawSectorInfo[8]; RETAILMSG(FMD_ZONE_FUNCTION,(TEXT("#### FMD_DRIVER:::FMD_LB_READSECTOR %x %x\r\n"),startSectorAddr,NewDataAddr)); if (!pSectorBuff && !pSectorInfoBuff) { return(FALSE); } if ( dwNumSectors > 1 ) { RETAILMSG(FMD_ZONE_ERROR, (TEXT("######## FATAL ERROR => FMD::FMD_ReadSector->dwNumsectors is bigger than 1. \r\n"))); return FALSE; } if (!pSectorBuff) { return NAND_LB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff); } SubmitSpareAreaReadCmd(NewSectorAddr, NewSpareAddr+NAND_SECC1_OFFSET); //< Spare Area Start Address, SECTOR_SIZE(512)*SECTOS_PER_PAGE(4)=2048 -> Physical Page Size // Read SECC1, SECC2 from Spare area SECCBuf1 = NF_RDDATA_WORD(); SECCBuf2 = NF_RDDATA_WORD(); // Set address for random access to read SectorInfo and MECC code from Spare Area NF_CMD(CMD_RDO); // Send read random data output command NF_ADDR((NewSpareAddr)&0xff); NF_ADDR(((NewSpareAddr)>>8)&0xff); NF_CMD(CMD_RDO2); // Command done if (pSectorInfoBuff) /// Read SectorInfo doesn't check this { ReadOneSectorInfo(RawSectorInfo); ///< Read One SectorInfo by sizeof(SectorInfo) // Check ECC abour SectorInfo NF_WRMECCD0( ((SECCBuf1&0xff00)<<8)|(SECCBuf1&0xff) ); NF_WRMECCD1( ((SECCBuf1&0xff000000)>>8)|((SECCBuf1&0xff0000)>>16) ); nRetEcc = NF_ECC_ERR0; if (!ECC_CorrectData(startSectorAddr, RawSectorInfo, nRetEcc, ECC_CORRECT_SPARE1)) // Use specific byte { RETAILMSG(FMD_ZONE_ERROR, (TEXT("#### SECC1 ECC correction failed\n"))); NF_nFCE_H(); return FALSE; } RestructSectorInfo(pSectorInfoBuff, RawSectorInfo); } else { for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++)