//***************************************************************
//功能:读写NAND Flash
//说明:K9F2G08U0A 共有2048个块,一块为64页,一页为(2048B+64)字节
// (2K 表示的是 main区容量的,64表示的是 spare区容量)
//坏块:686 967 1023 1600
//***************************************************************
#include <string.h>
#include "def.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "Nand_Test.h"
//**************************
void Nand_Test(void);
void Bad_Block_Num_Test(void);
void Nand_Buffer_Init(void);
void Nand_Buffer_Initff(void);
void Nand_Buffer_Print(void);
//**************************
void rNF_Init(void);
void rNF_Reset(void);
void rNF_ReadID(void);
void rNF_ReadPage(U32 page_number);
void rNF_WritePageTest(U32 page_number);
void rNF_WritePage(U32 page_number,U8 *buf,U32 len);
void rNF_EraseBlock(U32 block_number);
U8 rNF_RandomRead(U32 page_number,U32 add);
U8 rNF_RandomWrite(U32 page_number,U32 add,U8 data);
U8 rNF_IsBadBlock(U32 block);
U8 rNF_MarkBadBlock(U32 block);
U8 nand_buffer[2048];
U8 ecc_buffer[6];
volatile int bad_block_num=0;
U32 bad_block_addr_buffer[10];
//************************
//功能:Nand读/写/擦除实验
//************************
void Nand_Test(void)
{
U32 i;
U32 which_block=2000; //擦/写/读 第几块
U32 which_page=0; //擦/写/读 第几页
U32 random_block=2000; //随意读/写 第几块
U32 random_page=0; //随意读/写 第几页
U32 random_byte=15; //随意读/写 第几个字节
U32 random_data=0xaa; //随意写 数据
U8 temp;
rNF_Init(); //初始化
rNF_Reset(); //复位
rNF_ReadID(); //读ID
//*******擦出块******
rNF_EraseBlock(which_block);
//*******写页********
rNF_WritePageTest(which_block*64); //写一页 写之前必须擦除
//*******读页********
Nand_Buffer_Init(); //nand_buffer[]初始化
rNF_ReadPage(which_block*64+which_page); //读一页
Nand_Buffer_Print(); //串口打印nand_buffer[]
//*******擦出块******
rNF_EraseBlock(which_block);
//*******写页********
Nand_Buffer_Initff();
rNF_WritePage(which_block*64,nand_buffer,2048); //写一页 写之前必须擦除
//*******读页********
Nand_Buffer_Init(); //nand_buffer[]初始化
rNF_ReadPage(which_block*64+which_page); //读一页
Nand_Buffer_Print();
//*******擦出块******
rNF_EraseBlock(which_block);
//*******写页********
//Nand_Buffer_Init();
// rNF_WritePage(which_block*64,nand_buffer,2048); //写一页 写之前必须擦除
//*******读页********
Nand_Buffer_Init(); //nand_buffer[]初始化
rNF_ReadPage(which_block*64+which_page); //读一页
Nand_Buffer_Print();
//******随意写*******
//rNF_EraseBlock(random_block); //写之前必须擦除
//rNF_RandomWrite(random_block*64+random_page,random_byte,random_data=0xaa);
//******随意读*******
temp=rNF_RandomRead(random_block*64+random_page,random_byte);
Uart_Printf("\nRandom Read page %d clow %d finish!\n",random_block*64+random_page,random_byte);
Uart_Printf("Data is: %02x\n",temp);
}
//************************
//功能:检测Nand坏块数量
//坏块:686 967 1023 1600
//************************
void Bad_Block_Num_Test(void)
{
U32 i=0;
rNF_Init(); //初始化
rNF_Reset(); //复位
for(i=0;i<2048;i++) //总块数为2048
{
//通过擦除块来检查否为坏块 不能擦除的为坏块
rNF_EraseBlock(i); //输入参数不是地址 是"第几块"==页地址/64
Uart_Printf("i=%d Total block is 2048!!\n",i);
}
Uart_Printf("\nThose block is bad:\n");
//打印坏块位置 (页地址/64)
for(i=0;i<bad_block_num;i++)
{
Uart_Printf("%d\n",bad_block_addr_buffer[i]);
}
Uart_Printf("\nTotle bad block number is:%d\n",bad_block_num);
}
//************************
//功能:nand_buffer[]初始化
//************************
void Nand_Buffer_Init(void)
{
int i=0;
for(i=0;i<2048;i++)
{
nand_buffer[i]=0x0;
}
}
void Nand_Buffer_Initff(void)
{
int i=0;
for(i=0;i<2048;i++)
{
nand_buffer[i]=0xff;
}
}
//***************************
//功能:串口打印读到的nand数据
//***************************
void Nand_Buffer_Print(void)
{
int i=0;
for(i=0;i<512;i++)
{
Uart_Printf("%02x ",nand_buffer[i]);
if(!((i+1)%16))
Uart_Printf("\n");
}
}
//************************
//功能:Nand初始化
//************************
void rNF_Init(void)
{
//Nand端口配置 GPA17-20 22 17CLE 18ALE 19nFWE 20nFRE 21空 22nFCE
rGPACON|=(0x3f<<17);
//TACLS=1、TWRPH0=4、TWRPH1=0,8位 IO
rNFCONF=(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
//13禁止紧锁 12禁止上锁 10禁止中断 9禁止RnB中断 8RnB传输检测上升沿
//6锁定Spare区ECC 5锁定main区ECC 4初始化ECC 1禁止片选 0控制使能
rNFCONT=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
rNFSTAT=0x0;
}
//************************
//功能:Nand复位
//************************
void rNF_Reset(void)
{
NF_CE_L(); //打开Nand片选
NF_CLEAR_RB(); //清楚RnBx信号
NF_CMD(CMD_RESET); //写入复位命令
NF_DETECT_RB(); //等待RnB变高 即不忙
NF_CE_H(); //关闭片选
}
//************************
//功能:读ID
//************************
void rNF_ReadID(void)
{
char pMID;
char pDID;
char cyc3;
char cyc4;
char cyc5;
NF_CE_L(); //打开Nand片选
NF_CLEAR_RB(); //清楚RnBx信号
NF_CMD(CMD_READID); //读ID命令
NF_ADDR(0x00); //写入地址
//读5个周期的ID
pMID=NF_RDDATA8();
pDID=NF_RDDATA8();
cyc3=NF_RDDATA8();
cyc4=NF_RDDATA8();
cyc5=NF_RDDATA8();
//NF_DETECT_RB(); //等待RnB变高 即不忙
NF_CE_H(); //关闭片选
Uart_Printf("\nRead Nand Flash ID:\n");
Uart_Printf("pMID=%xh\n",pMID);
Uart_Printf("pDID=%xh\n",pDID);
Uart_Printf("cyc3=%xh\n",cyc3);
Uart_Printf("cyc4=%xh\n",cyc4);
Uart_Printf("cyc5=%xh\n",cyc4);
}
//************************
//功能:读一页
//入口:页地址
//************************
void rNF_ReadPage(U32 page_number)
{
U32 i=0;
U32 mecc0;
U32 secc;
U8 temp=0;
//****************
NF_RSTECC(); //复位ECC
NF_MECC_UnLock(); //解锁main区ECC
NF_nFCE_L(); //打开Nand片选
NF_CLEAR_RB(); //清RnB信号
//****************
NF_CMD(CMD_READ1); //页读命令周期1
//写入5个地址周期
NF_ADDR(0x00); //列地址A0-A7
NF_ADDR(0x00); //列地址A8-A11
NF_ADDR((page_number)&0xff); //行地址A12-A19
NF_ADDR(((page_number)>>8)&0xff); //行地址A20-A27
NF_ADDR(((page_number)>>16)&0xff); //行地址A28
NF_CMD(CMD_READ2); //页读命令周期2
NF_DETECT_RB(); //等待RnB变高,即不忙
//读取一页数据
for(i=0;i<2048;i++)
{
nand_buffer[i]=NF_RDDATA8(); //读取8位数据到buffer
}
NF_MECC_Lock(); //锁定main区ECC
//****************
//校验是否正确读取
NF_SECC_UnLock(); //解锁spare区ECC
mecc0=NF_RDDATA(); //读取spare区的前4字节,即2048-2051地址
//这4个字节为main区的ECC
//把读取到的main区的ECC校验码放入NFMECCD0/1的相应位置
rNFMECCD0=((mecc0&0xff00)<<8)|(mecc0&0xff);
rNFMECCD1=((mecc0&0xff000000)>>8)|((mecc0&0xff0000)>>16);
NF_SECC_Lock(); //锁定spare区ECC
secc=NF_RDDATA(); //继续读取spare区4字节,即2052-2055,
//其中
- 1
- 2
- 3
前往页