OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4063|回复: 4

关于NANDFLASH中ECC校验的问题

[复制链接]

0

主题

2

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2020-6-6
在线时间
8 小时
发表于 2020-11-30 21:27:04 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 luxinchun 于 2020-12-1 08:40 编辑

最近看原子哥的NANDFLASH应用。其中,在u8 NAND_ReadPage(u32 PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToRead)函数中,有ECC的校验,有一个疑惑,请大侠解惑。
比如我读列地址为2到513的值,正好是512个字节,所以要进行ECC校验。硬件自动进行计算出ECC值。但读出的原来NANDFLASH的spare区的ECC值是0到511的,这两者怎么比较啊,明显的对不上的啊。哪位大侠解惑一下。

最佳答案

查看完整内容[请看2#楼]

if(NumByteToRead % NAND_ECC_SECTOR_SIZE) //不是NAND_ECC_SECTOR_SIZE的整数倍,不进行ECC校验 { //读取NAND FLASH中的值 for(i=0;i
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2020-6-6
在线时间
8 小时
 楼主| 发表于 2020-11-30 21:27:05 | 显示全部楼层
        if(NumByteToRead % NAND_ECC_SECTOR_SIZE)        //不是NAND_ECC_SECTOR_SIZE的整数倍,不进行ECC校验
        {
                //读取NAND FLASH中的值
                for(i=0;i<NumByteToRead;i++)
                {
                        *(vu8*)pBuffer++ = *(vu8*)NAND_ADDRESS;
                }
        }else
        {
                eccnum = NumByteToRead/NAND_ECC_SECTOR_SIZE;                                //得到ecc计算次数
                eccstart = ColNum/NAND_ECC_SECTOR_SIZE;               
                p = pBuffer;               
                for(res=0;res<eccnum;res++)               
                {               
                        FMC_Bank2_3->PCR3 |= 1<<6;                                                                //使能ECC校验
                        for(i=0;i<NAND_ECC_SECTOR_SIZE;i++)                                                //读取NAND_ECC_SECTOR_SIZE个数据
                        {               
                                *(vu8*)pBuffer++ = *(vu8*)NAND_ADDRESS;               
                        }                               
                        while(!(FMC_Bank2_3->SR3&(1<<6)));                                                //等待FIFO空       
                        nand_dev.ecc_hdbuf[res+eccstart] = FMC_Bank2_3->ECCR3;        //读取硬件计算后的ECC值
                        FMC_Bank2_3->PCR3 &= ~(1<<6);                                                        //禁止ECC校验
                }                
                i = nand_dev.page_mainsize + 0X10 + eccstart*4;                                //从spare区的0X10位置开始读取之前存储的ecc值
                NAND_Delay(NAND_TRHW_DELAY);                                                                //等待tRHW
                *(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(NAND_TWHR_DELAY);                                                                //等待tWHR
                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\r\n",nand_dev.ecc_hdbuf[i+eccstart],nand_dev.ecc_rdbuf[i+eccstart]);
                                printf("eccnum,eccstart:%d,%d\r\n",eccnum,eccstart);       
                                printf("PageNum,ColNum:%d,%d\r\n",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错误
                        }
                }                

原子哥,帮忙看一下,没想通啊!!!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165537
金钱
165537
注册时间
2010-12-1
在线时间
2117 小时
发表于 2020-12-2 02:16:26 | 显示全部楼层
NAND的读写一般以扇区为单位。。。。一次都512字节,每次都是512的首地址。。。这就明白了吧?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2020-6-6
在线时间
8 小时
 楼主| 发表于 2020-12-2 10:51:14 | 显示全部楼层
本帖最后由 luxinchun 于 2020-12-2 12:14 编辑
正点原子 发表于 2020-12-2 02:16
NAND的读写一般以扇区为单位。。。。一次都512字节,每次都是512的首地址。。。这就明白了吧?

谢谢原子哥的解答。好像明白了。也就是说如果我要读列地址为2-513的值,真正进行校验的是列地址为0-511的值的ECC。由于eccnum = NumByteToRead/NAND_ECC_SECTOR_SIZE; 此时,eccnum=1, nand_dev.ecc_hdbuf[res+eccstart] = FMC_Bank2_3->ECCR3;就只循环一次,这样,对于列地址为512和513的两个值所在的那个扇区,是不校验ECC的。这样理解对吗?谢谢,谢谢!如果我要读的列地址为511-1022呢?也只校验列地址为0-511的吗?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165537
金钱
165537
注册时间
2010-12-1
在线时间
2117 小时
发表于 2020-12-3 01:43:14 | 显示全部楼层
luxinchun 发表于 2020-12-2 10:51
谢谢原子哥的解答。好像明白了。也就是说如果我要读列地址为2-513的值,真正进行校验的是列地址为0-511的 ...

按512字节分段的。。。你记住这个就行了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-14 13:52

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表