2019-07-20 18:49发布
zuozhongkai 发表于 2016-11-16 10:19 能,把底层驱动改好,其实就是数据的读写,如果数据读写正常的话应用层的代码基本都是一样的
正点原子 发表于 2016-11-17 21:36 你底层驱动正常了没有? 不带坏款管理,标准的读写函数。,
最多设置5个标签!
目前貌似改乱了啊,不改之前,还可以显示出好坏块,改成16位后,识别的都是错误的块,
u8 NAND_ReadPage(u32 PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToRead)
{
u16 i=0;
u8 res=0;
u8 eccnum=0;
目前貌似改乱了啊,不改之前,还可以显示出好坏块,改成16位后,识别的都是错误的块,
u8 NAND_ReadPage(u32 PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToRead)
{
u16 i=0;
u8 res=0;
u8 eccnum=0; //需要计算的ECC个数,每NAND_ECC_SECTOR_SIZE字节计算一个ecc
u8 eccstart=0; //第一个ECC值所属的地址范围
u8 errsta=0;
u8 *p;
*(vu8*)(NAND_ADDRESS|NAND_CMD) = NAND_AREA_A;
//发送地址
*(vu8*)(NAND_ADDRESS|NAND_ADDR) = (u8)ColNum;
*(vu8*)(NAND_ADDRESS|NAND_ADDR) = (u8)(ColNum>>8);
*(vu8*)(NAND_ADDRESS|NAND_ADDR) = (u8)PageNum;
*(vu8*)(NAND_ADDRESS|NAND_ADDR) = (u8)(PageNum>>8);
*(vu8*)(NAND_ADDRESS|NAND_ADDR) = (u8)(PageNum>>16);
*(vu8*)(NAND_ADDRESS|NAND_CMD) = NAND_AREA_TRUE1;
//下面两行代码是等待R/B引脚变为低电平,其实主要起延时作用的,等待NAND操作R/B引脚。因为我们是通过
//将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO,代码中通过读取NWAIT引脚的电平来判断NAND是否准备
//就绪的。这个也就是模拟的方法,所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
//闲状态,结果我们就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!大家也可以将下面两行
//代码换成延时函数,只不过这里我们为了效率所以没有用延时函数。
res = NAND_WaitRB(0); //等待RB=0
if(res)
{
#if NAND_FLASH_DEBUG_SWITCH > 0U
printf("NAND Wait 0 Error ?? ");
#endif
return NSTA_TIMEOUT; //超时退出
}
//下面2行代码是真正判断NAND是否准备好的
res = NAND_WaitRB(1); //等待RB=1
if(res)
{
#if NAND_FLASH_DEBUG_SWITCH > 0U
printf("NAND Wait 1 Error ?? ");
#endif
return NSTA_TIMEOUT; //超时退出
}
if(NumByteToRead % NAND_ECC_SECTOR_SIZE)//不是NAND_ECC_SECTOR_SIZE的整数倍,不进行ECC校验
{
//读取NAND FLASH中的值
for(i=0;i<NumByteToRead;i++)
{
*(vu8*)pBuffer++ = *(vu8*)NAND_ADDRESS; // 我吧这个 vu8 改成 vu16, u8 *pBuffer 这个定义的也改成了u16类型,其他没有改动,另外就是我需要读取的数据量 / 2 ,
// 结果就不对了,也不知道是不是我的硬件
// 上有两个 引脚没有接电源,根据资料要求,16位的39脚接 vcc,48脚接gnd,搞硬件时忘记了接,芯片型号
// MT29F4G16ABAEAWP TSOP48 封装的
}
}
else
{
eccnum = NumByteToRead / NAND_ECC_SECTOR_SIZE; //得到ecc计算次数
eccstart = ColNum/NAND_ECC_SECTOR_SIZE;
p = pBuffer;
for(res=0;res<eccnum;res++)
{
FMC_Bank3->PCR |= 1<<6; //使能ECC校验
for(i=0;i<NAND_ECC_SECTOR_SIZE;i++) //读取NAND_ECC_SECTOR_SIZE个数据
{
*(vu8*)pBuffer++ = *(vu8*)NAND_ADDRESS;
}
while(!(FMC_Bank3->SR&(1<<6))); //等待FIFO空
nand_dev.ecc_hdbuf[res+eccstart] = FMC_Bank3->ECCR;//读取硬件计算后的ECC值
FMC_Bank3->PCR &= ~(1<<6); //禁止ECC校验
}
i = nand_dev.page_mainsize+0X10+eccstart*4; //从spare区的0X10位置开始读取之前存储的ecc值
NAND_Delay(30);//等待tADL
*(vu8*)(NAND_ADDRESS|NAND_CMD) = 0X05; //随机读指令
//发送地址
*(vu8*)(NAND_ADDRESS|NAND_ADDR) = (u8)i;
*(vu8*)(NAND_ADDRESS|NAND_ADDR) = (u8)(i>>8);
*(vu8*)(NAND_ADDRESS|NAND_CMD) = 0XE0; //开始读数据
NAND_Delay(30);//等待tADL
pBuffer = (u8*)&nand_dev.ecc_rdbuf[eccstart];
for(i=0; i < (4 * eccnum); i++) //读取保存的ECC值
{
*(vu8*)pBuffer++ = *(vu8*)NAND_ADDRESS;
}
for(i=0;i<eccnum;i++) //检验ECC
{
if(nand_dev.ecc_rdbuf[i+eccstart] != nand_dev.ecc_hdbuf[i+eccstart] )//不相等,需要校正
{
printf("err hd,rd:0x%x,0x%x ",nand_dev.ecc_hdbuf[i+eccstart],nand_dev.ecc_rdbuf[i+eccstart]);
printf("eccnum,eccstart:%d,%d ",eccnum,eccstart);
printf("PageNum,ColNum:%d,%d ",PageNum,ColNum);
res = NAND_ECC_Correction(p+NAND_ECC_SECTOR_SIZE*i,nand_dev.ecc_rdbuf[i+eccstart],nand_dev.ecc_hdbuf[i+eccstart]);//ECC校验
if(res)
errsta = NSTA_ECC2BITERR; //标记2BIT及以上ECC错误
else
errsta = NSTA_ECC1BITERR; //标记1BIT ECC错误
}
}
}
if(NAND_WaitForReady(0x2FFFFFF) != NSTA_READY)
errsta = NSTA_ERROR; //失败
return errsta; //成功
}
我现在是吧 16bit的 nand flash 当成8位的来使用了,作为 8bit使用时貌似也没有什么问题,
如果作为16bit使用,在资料介绍里面没有找到如何开启16bit模式,貌似资料介绍的都是8bit读写的,还有 我配置数据宽度为16bit或者8bit都没有任何影响,也就是他都是按照8bit来进行读写的,
另外这个芯片 根据资料介绍 p39, p40, p34这三个引脚,如果是16bit的话,需要接电源,但是硬件只接了p34脚这一个已经到vcc上, p39(VCC), p40(GND)这两个引脚没有接,不知道是不是与这两个引脚
有关,他的引脚又那么密不好单独引线出来,所以现在就按照 8bit的操作拉倒了
,以后还是得搞8bit的好了
一周热门 更多>