利用uboot的nand read读取内核的时候会发生类似这样的错误。
nand read from offset xxx failed -74
发生这样的错误有80%的原因应该是nand flash控制器的ECC校验方面出了问题,想要解决这样的问题就必须要深入到底层硬件去探看。我花了很长时间来调试这个错误,最终解决的时候其实就是对NFCONF寄存器的其中一位进行了设置,但是就是这简单的一位,让我几乎了解了nand flash全部的知识。好了废话不多说了,我总结了一下解决这个问题的几点技巧。
1、最终要的先弄清楚开发板使用的Nand flash型号,page大小,block大小,SLC/MLC类型;在nand_ids.c中是否有定义。
2、uboot的nand驱动程序基本上是从linux内核当中移植过来的,只不过入口函数的形式有点差异而已;看看ecc在uboot当中使用的函数、对应的oob分区是否一致。
3、尤其注意以下NFCONF和NFCONT等寄存器在uboot当中是如何设置的,是否符合自己开发板上使用的nand flash型号。
4、适当使用prinf, printk, puts等打印函数进行调试。
说一说我的具体情况。
我的nand flash为K9F4G08U0E,大小如下所示
1 device=4096block=4096x64pages=4096x64x(2K+64)bytes=(512+16)Mbytes
在nand_ids.c中确实有定义
{"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, LP_OPTIONS}, 其中0xdc可以从内核启动时打印信息中查看。
最重要的信息是,我的nand flash是SLC类型,也就是只支持1位硬件ECC(吧),可悲的是网上流传的tiny210的uboot中大都使用的是MLC的驱动架构,也就是使用了4位,8位甚至是16位的ECC,而且我发现我的uboot也是用了8位ecc,所以这肯定不正确嘛。在board_nand_init函数中,打开这个宏开关
#define CONFIG_NAND_4BIT_ECC
#if defined(CONFIG_NAND_4BIT_ECC) //其实我一直怀疑这个地方似乎写错了,应该是CONFIG_NAND_1BIT_ECC
nand->ecc.read_page = s3c_nand_read_page_1bit;
nand->ecc.write_page = s3c_nand_write_page_1bit;
nand->ecc.read_oob = s3c_nand_read_oob_1bit;
nand->ecc.write_oob = s3c_nand_write_oob_1bit;
nand->ecc.layout = &s3c_nand_oob_64;
nand->ecc.hwctl = s3c_nand_enable_hwecc;
nand->ecc.calculate = s3c_nand_calculate_ecc;
nand->ecc.correct = s3c_nand_correct_data;
nand->options |= NAND_NO_SUBPAGE_WRITE;
#else
好了,最后的最后,一定别忘了再修改一下NFCONF中相关的寄存器,让它支持page = 2k 1位SLC的nand flash。
这些修改可以直接在board_nand_init中进行相应的位操作即可。接下来就是大功告成的样子拉
Hit any key to stop autoboot: 0
NAND read: device 0 offset 0x400000, size 0x500000
5242880 bytes read: OK
## Booting kernel from Legacy Image at 21000000 ...
Image Name: Linux-3.0.8-ZBL
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4633368 Bytes = 4.4 MiB
Load Address: 20008000
Entry Point: 20008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
u-boot sucesses!
Uncompressing Linux... done, booting the kernel.
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Linux version 3.0.8-ZBL (root@zbl-ThinkPad-Edge-E531) (gcc version 4.5.1 (ctng-1.8.1-FA) ) #32 PREEMPT Mon Mar 16 18:31:14 CST 2015
[ 0.000000] CPU: ARMv7 Processor [412fc082] revision 2 (ARMv7), cr=10c53c7f
[ 0.000000] CPU: VIPT nonaliasing data cache, VIPT aliasing instruction cache
[ 0.000000] Machine: MINI210
[ 0.000000] Memory policy: ECC disabled, Data cache writeback
[ 0.000000] CPU S5PV210/S5PC110 (id 0x43110220)
[ 0.000000] S3C24XX Clocks, Copyright 2004 Simtec Electronics
[ 0.000000] S5PV210: PLL settings, A=1000000000, M=667000000, E=80000000 V=54000000
[ 0.000000] S5PV210: ARMCLK=1000000000, HCLKM=200000000, HCLKD=166750000
[ 0.000000] HCLKP=133400000, PCLKM=100000000, PCLKD=83375000, PCLKP=66700000
[ 0.000000] sclk_dmc: source is sclk_a2m (0), rate is 200000000
[ 0.000000] sclk_onenand: source is hclk_dsys (1), rate is 166750000
下面这个地址是我上传的修改好的uboot源码下载地址,不妥支持还请见谅,欢迎大家继续完善。
点击打开链接