📄 k9f1208.c
字号:
UINT32 blockpage;
UINT32 i;
UINT8 r_ecc0,r_ecc1,r_ecc2;
blockpage=(block<<5)+page;
/*NF_RSTECC(); */ /*ECC使能*/
nand_ce_low(); /*片选有效*/
nand_write_command(CMD_READ0); /*从0x00位置开始写一页*/
nand_ale_high();
nand_write_address(0x00); /*A7-A0为0x00*/
nand_write_address(blockpage&0xff); /*A9-A16*/
nand_write_address((blockpage>>8)&0xff);/*A17-A24*/
nand_write_address((blockpage>>16)&0x01); /*A25*/
nand_ale_low();
taskDelay(1);
for(i=0;i<512;i++)
{
buf_ret[i]=nand_read_data(); /*读取数据*/
if(buf_ret[i] !=0xaa)
{
return -1;
}
}
/*读取该页的3个字节ECC(写的时候的ECC)*/
for(i=0;i<3;i++)
{
eccbufr[i]=nand_read_data();
}
/*printf("W_EEC0:0x%x,W_EEC1:0x%x,W_EEC2:0x%x\n",eccbuf[0],eccbuf[1],eccbuf[2]);
*/
nand_ce_high(); /*片选取消*/
if((eccbufr[0]!=eccbufw[0])&&(eccbufr[1]!=eccbufw[1])&&(eccbufr[2]!=eccbufw[2]))
{
return -2;
}
return 0;
#if 0
/*读出此时的ECC校验码(读出数据后产生的ECC)*/
r_ecc0=rNF_ECC0;
r_ecc1=rNF_ECC1;
r_ecc2=rNF_ECC2;
printf("R_ECC0:0x%x,R_EEC1:0x%x,R_EEC2:0x%x\n",r_ecc0,r_ecc1,r_ecc2);
if( (r_ecc0==eccbuf[0]) && (r_ecc1==eccbuf[1]) && (r_ecc2==eccbuf[2]) )
{
printf("ECC check is ok\n");
return TRUE;
}
else
{
printf("ECC check is error\n");
return FALSE;
}
#endif
}
/*********************************************************************************************************
** Function name: nand_write_byte()
** Descriptions: 向某个块的某个页中的某个地址写入n个字节
** Input: blcok 块地址 (0-4096)
** page 页地址 (0-31)
** addr 字节地址 (0-527)
** num 写入字节的个数
** Output:
** Created by:
** Created Date: 2007-11-14
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int nand_write_byte(UINT32 block,UINT8 page,UINT32 addr,UINT32 num,UINT8 *buf)
{
UINT32 blockpage;
UINT32 i;
UINT8 status;
UINT32 n = 0;
blockpage=(block<<5)+page;
/*NF_RSTECC(); */ /*ECC使能*/
nand_ce_low(); /*片选有效*/
if(addr>=512)
nand_write_command(CMD_READOOB); /*0x50(C区)*/
else if(addr>=256)
nand_write_command(CMD_READ1); /*0x01(B区)*/
else
nand_write_command(CMD_READ0); /*0x00(A区)*/
nand_write_command(CMD_SEQIN); /* 装载数据命令0x80*/
nand_ale_high();
nand_write_address(addr&0xff); /* 发送地址A0-A7*/
nand_write_address(blockpage&0xff); /* 发送地址A9--A16*/
nand_write_address((blockpage>>8) & 0xff); /*发送地址A17--A24*/
nand_write_address((blockpage>>16) & 0x01); /* 发送地址A25*/
nand_ale_low();
/*load data to nandflash*/
for(i=0;i<num;i++)
{
nand_write_data(buf[i]);
}
#if 0
eccbuf[0]=rNF_ECC0;
eccbuf[1]=rNF_ECC1;
eccbuf[2]=rNF_ECC2; //两种方法都可以
printf("W_EEC0:0x%x,W_EEC1:0x%x,W_EEC2:0x%x\n",eccbuf[0],eccbuf[1],eccbuf[2]);
#endif
nand_write_command(CMD_PAGEPROG); /*发送编程命令0x10*/
nand_write_command(CMD_STATUS); /* 发送读取状态命令0x70 */
status = nand_read_data();
/*等待操作完成*/
while(!(status&0x40)) /* I/O(6) ==1 */
{
n++;
nand_write_command(CMD_STATUS);
status = nand_read_data();
if(n>10000)
{
printf("nand_write_byte time out!\n");
break;
}
}
nand_ce_high(); /*片选取消*/
/*printf("status = 0x%x\n",status);*/
if(status&0x01)
{
return -1;
}
else
{
return 0;
}
}
/*********************************************************************************************************
** Function name: nand_read_byte()
** Descriptions: 从某个块的某个页中的某个地址读出n个字节
** Input: blcok 块地址 (0-4096)
** page 页地址 (0-31)
** addr 字节地址 (0-527)
** num 写入字节的个数
** Output:
** Created by:
** Created Date: 2007-10-25
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int nand_read_byte(UINT32 block,UINT8 page,UINT32 addr,UINT32 num,UINT8 *buf_ret)
{
UINT32 blockpage;
UINT32 i;
UINT8 r_ecc0,r_ecc1,r_ecc2;
UINT8 status;
int n = 0;
blockpage=(block<<5)+page;
/*NF_RSTECC();*/ /*ECC使能*/
nand_ce_low(); /*片选有效*/
if(addr>=512)
nand_write_command(CMD_READOOB); /*0x50(C区)*/
else if(addr>=256)
nand_write_command(CMD_READ1); /*0x01(B区)*/
else
nand_write_command(CMD_READ0); /*0x00(A区)*/
nand_ale_high();
nand_write_address(addr&0xff); /*A7-A0*/
nand_write_address(blockpage&0xff); /*A9-A16*/
nand_write_address((blockpage>>8)&0xff);/*A17-A24*/
nand_write_address((blockpage>>16)&0x01); /*A25*/
nand_ale_low();
taskDelay(1);
for(i=0;i<num;i++)
{
buf_ret[i]=nand_read_data(); /*读取数据*/
printf("data=0x%x\n",buf_ret[i]);
}
/*
for(i=0;i<num;i++)
{
printf("buf_ret %d = 0x%x\n",i,buf[i]);
}
*/
nand_ce_high(); /*片选取消*/
return 0;
#if 0
//读出此时的ECC校验码(读出数据后产生的ECC)
r_ecc0=rNF_ECC0;
r_ecc1=rNF_ECC1;
r_ecc2=rNF_ECC2;
printf("R_ECC0:0x%x,R_EEC1:0x%x,R_EEC2:0x%x\n",r_ecc0,r_ecc1,r_ecc2);
if( (r_ecc0==eccbuf[0]) && (r_ecc1==eccbuf[1]) && (r_ecc2==eccbuf[2]) )
{
printf("ECC check is ok\n");
return TRUE;
}
else
{
printf("ECC check is error\n");
return FALSE;
}
#endif
}
/*********************************************************************************************************
** Function name: nand_read_spare_data
** Descriptions: 读出block块中第page页的OOB区的第num个字节
** Input: blcok 块地址
** page 页地址
** num 第n个字节
** Output:
** Created by:
** Created Date:2007-11-14
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
UINT8 nand_read_spare_data(UINT32 block,UINT8 page, UINT8 num)
{
UINT32 blockpage;
UINT8 ret_data;
blockpage=(block<<5)+page;
/* 发送命令和地址*/
nand_ce_low(); /*片选有效*/
nand_write_command(CMD_READOOB); /* 读取空闲区数据*/
nand_ale_high();
nand_write_address(num&0x0f); /* 发送地址地址的A3-A0,A7-A4无效*/
nand_write_address(blockpage&0xff); /* 发送地址A9--A16*/
nand_write_address((blockpage>>8)&0xff); /* 发送地址A17--A24*/
nand_write_address((blockpage>>16)&0x01); /* 发送地址A25 */
nand_ale_low();
taskDelay(1);
ret_data=nand_read_data(); /* 读出一个字节的数据 */
nand_ce_high(); /*片选取消*/
return ret_data;
}
/*********************************************************************************************************
;** 函数名称: nan_poll_bad_blocks
;** 功能描述: 查询NAN 坏块并保存在缓存区里
;**
;** 参 数: 无
;**
;** 返 回 值: 无
;**
;** 作 者:
;** 日 期: 2007年11月14日
;**-------------------------------------------------------------------------------------------------------
;** 修 改 人:
;** 日 期:
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
void nan_poll_bad_blocks(void)
{
UINT16 block_num = 0;
UINT8 temp = 0;
BOOL block_valid = TRUE;
UINT32 page_num = 0;
for(block_num = 0; block_num < MAX_BLOCK_NUM; block_num++)
nan_valid_block_bitmap[block_num] = 0;
nand_ce_low(); /*片选有效*/
for(block_num = 0; block_num < MAX_BLOCK_NUM; block_num++)
{
page_num = block_num * 32;
block_valid = TRUE;
for(temp = 0; temp < 2; temp++)
{
nand_write_command(0x50);
nand_ale_high();
nand_write_address(5);
nand_write_address(page_num&0xff);
nand_write_address((page_num>>8)&0xff);
nand_write_address((page_num>>16)&0x01);
nand_ale_low();
page_num++;
taskDelay(1);
if(0xff != nand_read_data())
{
block_valid = -1;
break;
}
}
nan_valid_block_bitmap[block_num / 8] |= block_valid << (block_num % 8);
}
nand_ce_high(); /*片选取消*/
}
/*判断当前块是否为坏块*/
int nand_is_bad_block(UINT32 block)
{
/*读出每个块的1,2页的起始第517个字节*/
if((nand_read_spare_data(block,PAGE0,5)!=0xff)
|| (nand_read_spare_data(block,PAGE1,5)!=0xff))
{
return 1;
}
return 0;
}
/*********************************************************************************************************
** Function name: k9f1208_test
** Descriptions: 主函数,程序入口。
** Input: 无
** Output: 系统返回值0
** Created by:
** Created Date: 2007-11-14
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int k9f1208_test(void)
{
UINT32 id_code=0;
UINT32 block_num;
int page_num;
UINT8 ret,w_buf[512],r_buf[512];
UINT32 bad_block_num=0; /*坏块计数器*/
UINT32 i=0;
printf("*********************nandflash test******************\n");
nand_init(); /*nand 初始化*/
id_code=nand_get_id(); /*读出芯片的ID信息*/
printf("manufacture id:0x%x,device code:0x%x,",((id_code&0xff000000)>>24),((id_code&0x00ff0000)>>16));
printf("id_code:0x%x\n",id_code);
/*/////////////////////erase all block:4096////////////////////////////////////*/
#if 1
printf("*********************erase all block******************\n");
for(block_num=0;block_num<MAX_BLOCK_NUM;block_num++)
{
ret=nand_erase_block(block_num);
if(-1 == ret)
{
printf("bad block num:%d\n",block_num);
}
}
printf("erase all block is ok!\n");
/****************************check bad block******************************************************/
printf("*********************check bad block******************\n");
for(block_num=0;block_num<MAX_BLOCK_NUM;block_num++)
{
if(1 == nand_is_bad_block(block_num)) /*读出每个块的1,2页的起始第517个字节*/
{
bad_block_num++;
printf("block%d is bad\n",block_num);
}
}
printf("total num of bad block is:%d\n",bad_block_num); /*打印出总的坏块*/
/*//////////////////////////////////////////////////////////////////////////////////////////////////*/
#endif
for(i=0;i<512;i++)
{
w_buf[i]=0xaa; /*初始化写buf,注意uint8只能到0xf,所以后面的是256个字节又重复0-0xff */
}
for(i=0;i<512;i++)
{
r_buf[i]=0; /*初始化读buf*/
}
#if 0
ret=nand_erase_block(0); /*擦除第二块*/
if(-1 == ret)
{
printf("bad block\n");
}
ret=nand_wite_page(0,0,w_buf); /*向第2块的第1页写入512字节 */
if(-1 == ret)
{
printf("write page error \n");
}
nand_read_page(0,0,r_buf); /*从第2块的第1页读出512字节 */
for(i=0;i<512;i++)
{
printf("%d**",r_buf[i]);
}
#endif
printf("*********************ECC all block******************\n");
for(block_num=0;block_num<MAX_BLOCK_NUM;block_num++)
{
for(page_num=0;page_num<32;page_num++)
{
ret = nand_wite_page(block_num,page_num,w_buf);
if(-1 == ret)
{
printf("block_num=%d,page_num=%d :write error!\n",block_num,page_num);
}
}
for(page_num=0;page_num<32;page_num++)
{
ret = nand_read_page(block_num,page_num,r_buf);
if(-1 == ret)
{
printf("block_num=%d,page_num=%d :read error!\n",block_num,page_num);
}
if(-2 == ret)
{
printf("block_num=%d,page_num=%d :ECC error!\n",block_num,page_num);
}
}
}
return(0);
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -