最近课程在学习nandflash读写,分享一下代码,希望可以给大家一些思路
nandflash的读写需要根据实际的flash型号来操作,遇到问题要学会看datasheet,我使用的mini2440,板上是256M SAMSUNG的K9F2G08U0C,nandflash的存储结构是256M分为2048个块,每个块128k,每一块有上下分为64页,每一页2k,我们在读写时写入32位地址即可。
地址的读写分为5个周期,每个周期写入的地址规则如下
在写入前需要擦除flash上的数据,nandflash的擦除是以块为单位的,即只要写入块地址,即上表中提到的行地址。在实际过程中,擦除操作可能会操作失败,因此我使用状态机的方式,擦除失败后继续当前得擦除操作直到擦除成功。代码如下:
U8 nandflash_test()
{
//500k = 128k*3+2k*58
//由于从0开始算 500k的地址应该在第3块,第57页的首地址处0x7D000
//0x0007d000 =0000 0000 0000 0111 1101 0000 0000 0000
U32 add = 0x7d000;
U8 step=0;
U8 wbuf[2048]={0};
U8 rbuf[2048]={0};
U32 i=0;
U8 stat;
while(1)
{
switch (step)
{
case 0: //准备要写入的数据
Uart_Printf("准备要写入的数据\n");
Uart_Printf("this is write data \n");
for(i=0;i<20;i++)
{
wbuf[i]=i&0xff;
Uart_Printf("第 %d 个数据:%d\n",i,wbuf[i]);
}
step++;
break;
case 1://初始化nandflash
Uart_Printf("初始化nandflash\n");
Nand_Init();
step++;
break;
case 2://擦除要写入的整个块区
Uart_Printf("擦除要写入的整个块区\n");
//add &=~0x3f;
nandflash_enable();
nandflash_cmd(0x60);
NF_ADDR((add>>12)&0xff);//A19-A12 = 0111 1101
NF_ADDR((add>>20)&0xff);//A27-A20 = 0000 0000
NF_ADDR((add>>28)&0xff)//A28 = 0000 0000
//nandflash_addr(add);//A18-A19
//nandflash_addr(add>>8);//A20-A27
//nandflash_addr(add>>16);//A28
nandflash_cmd(0xd0);
do{
stat=NF_RDDATA8();
}while(!(stat&0x40));
NF_nFCE_H();//控制芯片使能拉高
if(stat&0x1)
{
Uart_Printf("clean lose\n");
break;
}
else
{
Uart_Printf(" clearn successful \n");
step++;
break;
}
case 3://向目标地址写入数据
Uart_Printf("向目标地址写入数据\n");
Nand_Reset();
NF_RSTECC();
NF_MECC_UnLock();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(0x80);
//总共五个传递周期
NF_ADDR(0x00);//A7-A0 = 0000 0000
NF_ADDR(0x00); //A10-A8 = 0000 0000
NF_ADDR((add>>12)&0xff);//A19-A12 = 0111 1101
NF_ADDR((add>>20)&0xff);//A27-A20 = 0000 0000
NF_ADDR((add>>28)&0xff)//A28 = 0000 0000
for (i = 0; i < 20; i++)
rNFDATA8 = wbuf[i];
NF_CMD(0x10); //发送写结束指令
NF_nFCE_H();//控制芯片使能拉高
Uart_Printf("write successfully\n");
step++;
break;
case 4://读取写入的数据
Uart_Printf("读取写入的数据\n");
Nand_Reset();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(0x00); // Read command
NF_ADDR(0x00);//A7-A0 = 0000 0000
NF_ADDR(0&0x00); //A10-A8 = 0000 0000
NF_ADDR((add>>12)&0xff);//A19-A12 = 0111 1101
NF_ADDR((add>>20)&0xff);//A27-A20 = 0000 0000
NF_ADDR((add>>28)&0xff)//A28 = 0000 0000
NF_CMD(0x30); //发送写结束指令
NF_DETECT_RB();//等待系统不忙
for (i = 0; i < 20; i++)
rbuf[i] = rNFDATA8;
NF_nFCE_H();//控制芯片使能拉高
step++;
break;
case 5:
Uart_Printf("\r\n this is read data \r\n");
for(i=0;i<20;i++)
{
rbuf[i]=i&0xff;
Uart_Printf("第 %d 个数据:%d\n",i,rbuf[i]);
}
return 1;
}
}
}