?? nand_test.c
字號:
/****************************************************************************
* file name : nand_test.c
* Date : 15. 04. 2005
* Version : 1.0
* Description : NAND flash test menu display function
*
*
****************************************************************************/
#include "nand_test.h"
void NAND_flash_test(void)
{
int sel = 0;
while(1){
Uart_Printf("+--------------[ NAND flash test ]----------------+\n");
Uart_Printf("| 1:SOP(K9F5608U0B)\n");
Uart_Printf("| 2:SMC(K9S1208V0M)\n");
Uart_Printf("| 3:Previous menu\n");
Uart_Printf("+-------------------------------------------------+\n");
Uart_Printf(" Select the type of a NAND flash memory : ");
sel = Uart_GetIntNum();
Uart_Printf("+-------------------------------------------------+\n\n\n");
switch(sel){
case 1:
K9F5608_menu();
break;
case 2:
break;
case 3 :
return;
default:
Uart_Printf("Wrong number seleted.. Try again!!\n\n\n");
break;
}
}
}
void NAND_reset(void)
{
int i;
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(NAND_CMD_RESET);
for(i=0;i<10;i++);
NF_nFCE_H();
}
void NAND_init(void)
{
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
// TACLS [14:12] CLE&ALE duration = HCLK*TACLS.
// TWRPH0 [10:8] TWRPH0 duration = HCLK*(TWRPH0+1)
// TWRPH1 [6:4] TWRPH1 duration = HCLK*(TWRPH1+1)
// AdvFlash(R) [3] Advanced NAND, 0:256/512, 1:1024/2048
// PageSize(R) [2] NAND memory page size
// when [3]==0, 0:256, 1:512 bytes/page.
// when [3]==1, 0:1024, 1:2048 bytes/page.
// AddrCycle(R) [1] NAND flash addr size
// when [3]==0, 0:3-addr, 1:4-addr.
// when [3]==1, 0:4-addr, 1:5-addr.
// BusWidth(R/W) [0] NAND bus width. 0:8-bit, 1:16-bit.
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
// Lock-tight [13] 0:Disable lock, 1:Enable lock.
// Soft Lock [12] 0:Disable lock, 1:Enable lock.
// EnablillegalAcINT[10] Illegal access interupt control. 0:Disable, 1:Enable
// EnbRnBINT [9] RnB interrupt. 0:Disable, 1:Enable
// RnB_TrandMode[8] RnB transition detection config. 0:Low to High, 1:High to Low
// SpareECCLock [6] 0:Unlock, 1:Lock
// MainECCLock [5] 0:Unlock, 1:Lock
// InitECC(W) [4] 1:Init ECC decoder/encoder.
// Reg_nCE [1] 0:nFCE=0, 1:nFCE=1.
// NANDC Enable [0] operating mode. 0:Disable, 1:Enable.
NAND_reset();
}
void spin_wheel(void)
{
static int p = 0;
static char w[] = "\\/-";
Uart_Printf("\010%c", w[p]);
(++p==3)?(p=0):0;
}
int NAND_readID(void){
int i;
int id = 0;
NF_nFCE_L();
NF_CMD(NAND_CMD_READID);
NF_ADDR(0x0);
for (i=0; i<10; i++);
id = NF_RDDATA8()<<8; // Maker code : 0xec
id |= NF_RDDATA8(); // Devide code(K9S1208V:0x76), (K9K2G16U0M:0x75)
NF_nFCE_H();
return (id & 0xffff);
}
void NAND_check_block(U32 blk_max_cnt)
{
int i, start, end, badblock;
NAND_init();
badblock = 0;
Uart_Printf("block number must be between 0 and %d\n",blk_max_cnt-1);
Uart_Printf("Select the number of start block to check: ");
start = Uart_GetIntNum();
if( (start<0) || (start>blk_max_cnt) ){
Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
return;
}
Uart_Printf("\nSelect the number of end block to check: ");
end = Uart_GetIntNum();
if( (end<0) || (end>blk_max_cnt) ){
Uart_Printf("/n/nEnd block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
return;
}
Uart_Printf("\n\nDisplay block status\n");
for(i=start;i<end;i++){
Uart_Printf("%4d",i);
if(NAND_check_badblock(i) == 1){
Uart_Printf("\b\b\b\b");
Uart_Printf("BLOCK[%4d] is bad\n",i);
badblock++;
}else{
if(i != end) Uart_Printf("\b\b\b\b");
}
}
if(badblock == 0)
Uart_Printf("\nBLOCK[%d] ~ BLOCK[%d] is good..\n", start, end);
else
Uart_Printf("%d blocks is bad block..\n", badblock);
Uart_Printf("\nBlock check has been done..\n\n\n");
}
int NAND_check_badblock(U32 block)
{
int i, blockpage = block * NAND_PAGE_COUNT;
U8 data;
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(NAND_CMD_READOOB);
NF_ADDR(517 & 0xf);
NF_ADDR(blockpage & 0xff);
NF_ADDR((blockpage >> 8) & 0xff);
NF_ADDR((blockpage >> 16) & 0xff);
for(i=0;i<10;i++);
NF_DETECT_RB();
data = NF_RDDATA8();
NF_nFCE_H();
if(data != 0xff) return 1; //is bad block
else return 0; //isn't bad block
}
int NAND_mark_badblock(U32 block)
{
int i;
U32 blockpage = block * NAND_PAGE_COUNT;
seBuf[0]=0xff;
seBuf[1]=0xff;
seBuf[2]=0xff;
seBuf[5]=0x44; // Bad blcok mark=0
NF_nFCE_L();
NF_CMD(NAND_CMD_READOOB);
NF_CMD(NAND_CMD_SEQIN);
NF_ADDR(0x0);
NF_ADDR(blockpage&0xff);
NF_ADDR((blockpage>>8)&0xff);
NF_ADDR((blockpage>>16)&0xff);
for(i=0;i<NAND_OOB_SIZE;i++) NF_WRDATA8(seBuf[i]);
NF_CMD(NAND_CMD_PAGEPROG);
for(i=0;i<10;i++);
NF_DETECT_RB();
NF_CMD(NAND_CMD_STATUS);
for(i=0;i<3;i++);
if(NF_RDDATA8() & 0x1){
NF_nFCE_H(); //spare array write error
// Uart_printf("[Marking badblock is error!!]\n");
}else{
NF_nFCE_H(); // block is marked as bad block
}
return 1;
}
void NAND_erase(U32 blk_max_cnt){
int i, start, end, erase_err;
Uart_Printf("NAND flash Erase Test\n");
Uart_Printf("\nYou MUST be well aware that\n");
Uart_Printf("1. the block size of NAND flash is 0x%x\n", NAND_BLOCK_SIZE);
Uart_Printf("2. the page size of NAND flash is 0x%x\n", NAND_PAGE_SIZE);
NAND_init();
erase_err = 0;
Uart_Printf("\n\nblock number must be between 0 and %d\n",blk_max_cnt-1);
Uart_Printf("Select the number of start block to erase: ");
start = Uart_GetIntNum();
if( (start<0) || (start>blk_max_cnt) ){
Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
return;
}
Uart_Printf("\nSelect the number of end block to erase: ");
end = Uart_GetIntNum();
if( (end<0) || (end>blk_max_cnt) ){
Uart_Printf("/n/nEnd block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
return;
}
if(start>end){
Uart_Printf("start block number is bigger than end block number.. Try again\n");
return;
}
Uart_Printf("\n\nStart Erasing block\n");
for(i=start;i<=end;i++){
Uart_Printf("%4d",i);
if(NAND_erase_block(i) == 1){
Uart_Printf("\b\b\b\b");
Uart_Printf("%4d:ERROR!!\n", i);
erase_err++;
}else{
if(i != end) Uart_Printf("\b\b\b\b");
}
}
if(erase_err == 0)
Uart_Printf("\nBLOCK[%d] ~ BLOCK[%d] is erased..\n", start, end);
Uart_Printf("\nBlock erase has been done..\n\n\n");
}
int NAND_erase_block(U32 block)
{
int i;
U32 blockpage = block * NAND_PAGE_COUNT;
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(NAND_CMD_ERASE1);
NF_ADDR(blockpage & 0xff);
NF_ADDR((blockpage >> 8) & 0xff);
NF_ADDR((blockpage >> 16) & 0xff);
NF_CMD(NAND_CMD_ERASE2);
for(i=0;i<40;i++);
NF_DETECT_RB();
NF_CMD(NAND_CMD_STATUS);
if(NF_RDDATA8() & 0x1) // Erase error
{
NF_nFCE_H();
NAND_mark_badblock(block);
return 1;
}else{
NF_nFCE_H();
return 0;
}
}
void NAND_read(U32 blk_max_cnt)
{
U32 s_blk_num, i;
U8 *buf;
Uart_Printf("NAND flash Read Test\n");
Uart_Printf("This test reads data from NAND flash and copies data to memory\n");
Uart_Printf("This test reads only one block you select\n");
Uart_Printf("\nYou MUST be well aware that\n");
Uart_Printf("1. the block size of NAND flash is 0x%x\n", NAND_BLOCK_SIZE);
Uart_Printf("2. the page size of NAND flash is 0x%x\n", NAND_PAGE_SIZE);
Uart_Printf("\n\nblock number must be between 0 and %d\n",blk_max_cnt-1);
Uart_Printf("Select the number of block to read: ");
s_blk_num = Uart_GetIntNum();
if( (s_blk_num<0) || (s_blk_num>blk_max_cnt) ){
Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
return;
}
Uart_Printf("\nInput the target address to copy in memory[0x...]: ");
buf = (U8 *)Uart_GetIntNum();
Uart_Printf("\n\n");
Uart_Printf("Read data from %d block and copy data to 0x%x\n", s_blk_num, (int)buf);
if(NAND_read_block(s_blk_num, buf) == 1){
Uart_Printf("\nThis block is bad block\n");
}else{
Uart_Printf("\nReading block is completed\n");
}
Uart_Printf("\n\nDisplay data you read(page 0 of block %d) :", s_blk_num);
for(i=0;i<NAND_PAGE_SIZE/4;i++){
if(i%8==0) Uart_Printf("\n");
Uart_Printf("%08lx ", *(U32 *)(buf+(i*4)));
}
Uart_Printf("\n\n");
}
int NAND_read_block(U32 b_num, U8 *dst_addr)
{
U8 *buf = dst_addr;
char page_buf[NAND_PAGE_SIZE];
int i;
if(NAND_check_badblock(b_num)) return 1;
for(i=0;i<NAND_PAGE_COUNT;i++){
NAND_read_page(b_num, i, buf);
spin_wheel();
}
return 0;
}
int NAND_read_page(U32 block, U32 page, U8 *buffer)
{
U32 blockpage = (block*NAND_PAGE_COUNT)+(page&0x1f);
int i, ecc;
U8 *bufPt = buffer;
U8 se[16], ecc0, ecc1, ecc2;
NF_RSTECC();
NF_MECC_UnLock();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(NAND_CMD_READ0);
NF_ADDR(0);
NF_ADDR(blockpage&0xff);
NF_ADDR((blockpage>>8)&0xff);
NF_ADDR((blockpage>>16)&0xff);
NF_DETECT_RB();
for(i=0;i<NAND_PAGE_SIZE;i++) *bufPt++ = NF_RDDATA8();
NF_nFCE_H();
return 0;
}
void NAND_write(U32 blk_max_cnt)
{
U32 s_blk_num, i;
U8 *buf;
Uart_Printf("NAND flash Write Test\n");
Uart_Printf("This test reads data from memory and writes data to NAND flash\n");
Uart_Printf("This test writes only one block you select\n");
Uart_Printf("\nYou MUST be well aware that\n");
Uart_Printf("1. the block size of NAND flash is 0x%x\n", NAND_BLOCK_SIZE);
Uart_Printf("2. the page size of NAND flash is 0x%x\n", NAND_PAGE_SIZE);
Uart_Printf("\n\nblock number nust be between 0 and %d\n",blk_max_cnt-1);
Uart_Printf("Select the number of block to write: ");
s_blk_num = Uart_GetIntNum();
Uart_Printf("/n/nStart block number MUST BE 0 ~ %d.. Try again..\n",blk_max_cnt-1);
return;
}
Uart_Printf("\nInput the source data address to read in memory[0x...]: ");
buf = (U8 *)Uart_GetIntNum();
Uart_Printf("\n\n");
Uart_Printf("Read data from 0x%x and copy data to %d block\n", (int)buf, s_blk_num);
if(NAND_write_block(s_blk_num, buf) == 1){
Uart_Printf("\nThis block is bad block\n");
}else{
Uart_Printf("\nWriting block is completed\n");
}
Uart_Printf("\n\nDisplay data you write(page 0 of block %d) :", s_blk_num);
for(i=0;i<NAND_PAGE_SIZE/4;i++){
if(i%8==0) Uart_Printf("\n");
Uart_Printf("%08lx ", *(U32 *)(buf+(i*4)));
}
Uart_Printf("\n\n");
}
int NAND_write_block(U32 b_num, U8 *src_addr)
{
U8 *buf = src_addr;
char page_buf[NAND_PAGE_SIZE];
int i;
if(NAND_check_badblock(b_num)) return 1;
for(i=0;i<NAND_PAGE_COUNT;i++){
NAND_write_page(b_num, i, buf);
spin_wheel();
}
return 0;
}
int NAND_write_page(U32 block, U32 page, U8 *buffer)
{
U32 blockpage = (block*NAND_PAGE_COUNT)+(page&0x1f);
int i;
U8 *bufPt = buffer;
U32 mecc, secc;
NF_SOFT_UnLock();
NF_RSTECC();
NF_MECC_UnLock();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(NAND_CMD_READ0);
NF_CMD(NAND_CMD_SEQIN);
NF_ADDR(0);
NF_ADDR(blockpage&0xff);
NF_ADDR((blockpage>>8)&0xff);
NF_ADDR((blockpage>>16)&0xff);
for(i=0;i<NAND_PAGE_SIZE;i++) NF_WRDATA8(*bufPt++);
NF_MECC_Lock();
mecc = rNFMECC0;
seBuf[0] = (U8)(mecc & 0xff);
seBuf[1] = (U8)((mecc>>8) & 0xff);
seBuf[2] = (U8)((mecc>>16) & 0xff);
seBuf[3] = (U8)((mecc>>24) & 0xff);
seBuf[5] = 0xff;
NF_SECC_UnLock();
for(i=0;i<3;i++){
NF_WRDATA8(seBuf[i]);
}
NF_SECC_Lock();
secc = rNFSECC;
seBuf[8] = (U8)(secc & 0xff);
seBuf[9] = (U8)((secc>>8) & 0xff);
for(i=3;i<16;i++){
NF_WRDATA8(seBuf[i]);
}
NF_CLEAR_RB();
NF_CMD(NAND_CMD_PAGEPROG); // Write 2nd command
for(i=0;i<10;i++);
NF_DETECT_RB();
NF_CMD(NAND_CMD_STATUS); // Read status command
for(i=0;i<3;i++); //twhr=60ns
if (NF_RDDATA8()&0x1){// Page write error
NF_nFCE_H();
Uart_Printf("\n[WRITE ERROR:block#=%d]\n",block);
NAND_mark_badblock(block);
}else{
NF_nFCE_H();
}
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -