增加Nand Flash ECC的支持
又参考了网址http://blog.csdn.net/fulinus/article/details/8737129
修改相关文件:
1.u-boot-2011.03driversmtdnands3c2440_nand.c
2.u-boot-2011.03includeconfigsmini2440.h
一开始一直不能确定的是:nand->ecc.size 和nand->ecc.bytes到底是多少?板子上带的Nand Flash是:K9F1208U0B:64MB,8位。每1页包含512字节的main数据区和16字节的spare数据区。main区用于存储数据,spare区用于存储其它附加信息。S3C2440一次可以产生4个字节的ECC,对于K9F1208U0B,页大小是512字节的nand flash,只要读取1页(512字节)就产生4个字节的main区ECC。对于页是2048字节的nand flash,同样也是读取1页(2048字节)就产生4字节的ECC。参考网址,将nand->ecc.size=512,nand->ecc.bytes=4。
@2014-04-26:关于产生ECC字节数之前的误解:
S3C2440到底读/写一页数据上产生多少个字节的main区ECC和多少个字节的spare区ECC,是和Nand Flash的位数关联的。如果Nand Flash是8位的,那么一页产生4字节的Main区ECC(在NFMECC0寄存器里)和2个字节的spare区ECC(在NFSECC寄存器的低16位),如果Nand Flash是16位的,那么一页产生8个字节的Main区ECC(在NFMECC0和NFMECC1寄存器里)和4个字节的spare区ECC(在NFSECC寄存器里)。但是目前我们并没有是spare区的ECC码。
如下图(摘自S3C2440A datasheet)
关于怎么产生ECC:
在S3C2440数据手册第6章有这么一段。
产生ECC校验码的过程为:在读取或写入哪个区的数据之前,先解锁该区的ECC,以便产生该区的ECC。在读取或写入完数据之后,再锁定该区的ECC,这样系统就会把产生的ECC码保存到相应的寄存器中。
以主数据区域为例:解锁ECC,将NFCONT中第5位MainECCLock置0。锁定ECC,将NFCONT中第5位MainECCLock置1。
当读或写数据时,自动产生的ECC校验在寄存器NFMECC0/1中。
ECC校验可以纠正1个比特的错误和检测2个比特的错误。
关于出现1位错误根据下图校正。
1.先计算哪个数据出错:(NFESTAT0>>7) & 0x7ff;
2.再计算哪个位出错:(NFESTAT0>>4) & 0x7;
3.校正:我们知道,1位出错,要么是0变1,要么是1变0。用1与这位异或即可。
Repaired = Data[(NFESTAT0>>7)& 0x7ff] ^ (1<<((NFESTAT0>>4) & 0x7));
测试:
调试运行后的串口输出如下图:
读参数时报了一个-74的错误,应该就是ECC校验不过的原因。具体还没有去查。下面还有一个warning。在串口中输入saveenv,然后再次调试运行,如下图。这时候没有报上图的错误了。
查看参数0x80000的nand flash值,发现oob的前4个字节已经与之前的不同了。其中0x80000是在mini2440.h文件内定义的nand flash 参数起始地址。nand dump命令并不会去进行数据的ECC校验检测,只是读取数据,这区别与下面的nand read命令
当执行:nand read 0x31100000 0x80000 0x200时,程序会调用到这里,在文件drivers/mtd/nand/nand_base.c,函数nand_read_page_hwecc。如下图:
根据上图可做函数简要说明:
staticint s3c2440_nand_calculate_ecc(structmtd_info *mtd, const u_char *dat,
u_char *ecc_code)
当读或写完一页后,调用该函数,读取NFMECC0寄存器,就可以将该页main区的ECC校验码取出。参考源码
其中,u_char *ecc_code就是存取读取的ECC校验码
staticint s3c2440_nand_correct_data(structmtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
该函数用来比较read_ecc和calc_ecc的校验是否相等的。
其中,read_ecc是在spare区读出来的ECC校验值。
calc_ecc是读完1页后自动产生的ECC校验值。针对main区的ECC校验码,此值同样存在于NFMECC0寄存器内。
但是在该函数中并没有直接去比较read_ecc和calc_ecc,而是将read_ecc的值写入NFMECCD0和NFMECCD1,用硬件去比较,然后读取寄存器NFSTAT的值来判断。
其实直接比较read_ecc和calc_ecc,也是可以的,有的移植就是直接比较的。
本部分代码下载地址:360云盘http://yunpan.360.cn/,在《Uboot相关代码》文件夹里的《u-boot-2011.03_SRAM调试.zip》文件。
《u-boot-2011.03源码无修改.tar.bz2》是从官网下的无修改代码
上一篇:Windows下u-boot-2011.03在Mini2440移植详解(6)
下一篇:Windows下u-boot-2011.03在Mini2440移植详解(4)
推荐阅读最新更新时间:2024-11-20 08:25
设计资源 培训 开发板 精华推荐
- 使用 ON Semiconductor 的 ASM8P18S42ER 的参考设计
- EVAL-ADXRS645Z,用于评估 ADXRS645 高温、抗振 ±2000 度/秒陀螺仪的评估板
- 2.8元 1.54寸IPS屏幕 st7789 15pin
- AP0100CSSL00SPGAD-GEVK:1 MP 协处理器 DK
- AM1S-4809SH30Z 1W DC-DC转换器典型应用
- LTC1174-5 降压-升压转换器的典型应用电路
- LTC1474-3.3,从 4mA 至 20mA 环路的高效率 3.3V/10mA 输出
- AM2G-0509SZ 9V 2 瓦 DC-DC 转换器的典型应用
- NCP5007EVB:NCP5007 紧凑型白光 LED 驱动器评估板
- 具有峰值电流软启动、小尺寸的 LTC3632EMS8E、3.3V、20mA 稳压器的典型应用电路