开发环境:主机:Window XP SP2;linux:VMware7.01+ubuntu9.10;目标板:扬创utu2440-F开发板
交叉编译器:arm-linux-gcc4.3.2(一开始用的是编译内核的版本arm-linux-gcc3.4.1,但出现了软浮点问题,于是换成了现在用的版本,从本文章开始,内核编译也改用该交叉编译器)
摘要:在上一节中,完成了u-boot-2011.03移植过程中相对较难和复杂的部分:移植NAND FLASH部分,使u-boot支持从NAND FLASH启动和读写,虽然可支持从NAND FLASH启动了,但u-boot还不能引导内核启动。
本节介绍u-boot-2011.03移植的最后一部分:u-boot引导启动nand flash中的内核和cramfs格式根文件系统以及用户文件系统yaffs2的支持,使u-boot具有一个正常的bootload功能。
此外,u-boot的后续工作根据个人需求进行添加,比如添加u-boot命令、相应设备的驱动、LED指示灯等。
1. u-boot引导启动NAND FLASH中内核
在上篇中,u-boot可以支持从NAND FLASH启动了,但这时还不能引导内核启动。另外,还注意到,u-boot从NAND FLASH启动时会提示:”NAND_ECC_NONE selected by board driver“,如下所示:
U-Boot 2011.03 (Jun 26 2011 – 02:40:58)
DRAM: 64 MiB
NAND: NAND_ECC_NONE selected by board driver. This is not recommended !!
64 MiB
*** Warning – bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
[reille2440]#
这个问题暂不处理,请接着往下看。
1.1 修改和设置u-boot环境参数
u-boot环境参数可以在u-boot源码中设置,也可以在烧录到NAND FLASH后重新设置。
1.1.1 在u-boot源码中设定默认的环境参数,修改文件u-boot-2011.03/include/configs/reille2440.h
#define CONFIG_BOOTDELAY 3 /*#define CONFIG_BOOTARGS "root=ramfs devfs=mount console=ttySA0,9600" */ /*#define CONFIG_ETHADDR 08:00:3e:26:0a:5b ethaddr=00:0c:20:02:0a:5b */ #define CONFIG_ETHADDR 00:0c:20:02:0a:5b #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.1.168 #define CONFIG_SERVERIP 192.168.1.125 /*#define CONFIG_BOOTFILE "elinos-lart" */ /*#define CONFIG_BOOTCOMMAND "tftp; bootm" */ /***************added by guoyirong 2011.06.19**************/ #define CONFIG_SETUP_MEMORY_TAGS 1 // 如果没有定义这个参数,则uboot参数必须加入men=内存大小 #define CONFIG_INITRD_TAG 1 #define CONFIG_CMDLINE_TAG 1 // 设置bootargs出入内核必须 // nand flash boot |added by guoyirong 2011.07.02 #define CONFIG_BOOTARGS \ "root=/dev/mtdblock2 console=ttySAC0,115200 rootfstype=cramfs noinitrd mem=64M" // boot default |added by guoyirong 2011.07.02 #define CONFIG_BOOTCOMMAND \ "nand read 0x30008000 0x60000 0x200000;bootm 0x30008000"
1.1.2 修改文件env_common,在default_environment[]中添加如下信息:
// added by guoyirong 2011.07.08 "install-uboot=" "tftp 30000000 u-boot.bin;\ nand erase 0 60000;nand write 30000000 0 60000" "" "install-kernel=" "tftp 30000000 uImage;nand erase 60000 200000;\ nand write 30000000 60000 200000" "" "install-filesystem=" "tftp 30000000 rootfs.cramfs;nand erase 260000 300000;\ nand write.jffs2 30000000 260000 300000" "" "erase-env=" "nand erase 40000 20000" ""
在u-boot中分别运行run install-uboot、run install-kernel、run install-filesystem来烧写u-boot、kernel(uImage)、文件系统的镜像到NAND FLASH中,使镜像文件的烧写更加方便。
环境参数如下:
[reille2440]# print
baudrate=115200
bootargs=root=/dev/mtdblock2 console=ttySAC0,115200 rootfstype=cramfs noinitrd mem=64M
bootcmd=nand read 0x30008000 0x60000 0x200000;bootm 0x30008000
bootdelay=3
ethact=CS8900-0
ethaddr=00:0c:20:02:0a:5b
ipaddr=192.168.1.168
netmask=255.255.255.0
serverip=192.168.1.125
stderr=serial
stdin=serial
stdout=serial
1.2 内核引导
环境参数正确之后,就可以正确引导NAND FLASH的内核镜像。
2. 文件系统
选用只读的cramfs作为根文件系统,而用户文件系统采用yaffs2。
cramfs是压缩的只读根文件系统,u-boot直接支持。
而像yaffs/yaffs2,则是未压缩的可读可写的文件系统,如果用作根文件系统,u-boot需要修改之后才能支持。
2.1 NAND FLASH分区
NAND FLASH分区信息如下:
Creating 4 MTD partitions on “NAND 64MiB 3,3V 8-bit”:
0x000000000000-0x000000060000 : “uboot”
0x000000060000-0x000000260000 : “kernel”
0x000000260000-0x000000560000 : “rootfs”
0x000000560000-0x000004000000 : “user”
ohci_hcd: USB 1.1 ‘Open’ Host Controller (OHCI) Driver
开始的时候,由于粗心大意,分区有点错误,启动时出现如下信息:
mtd: partition “user” extends beyond the end of device “NAND 64MiB 3,3V 8-bit” — size truncated to 0x3ba0000
意思是说,我的第4个分区超过了最大大小。
上面分区中,rootfs表示根文件系统分区,包括了动态链接库、命令程序等;user是用户文件系统分区,要运行的程序、数据都是放在此分区上
2.2 制作根文件系统
本来是想通过移植busybox1.16.0来制作一个.cramfs的根文件系统,移植busybox1.16.0没问题,编译通过,但是建立的根文件系统,用NFS挂载的时候出现如下问题:
Freeing init memory: 104K
Kernel panic – not syncing: Attempted to kill init!
Backtrace:
[<c0026908>] (dump_backtrace+0x0/0x12c) from [<c0026a4c>] (dump_stack+0x18/0x1c)
r7:c381c000 r6:c381a000 r5:c039793c r4:00000004
[<c0026a34>] (dump_stack+0x0/0x1c) from [<c0033b6c>] (panic+0x40/0x118)
[<c0033b2c>] (panic+0x0/0x118) from [<c0036338>] (do_exit+0x1bc/0x670)
r3:c03728f4 r2:60000013 r1:c0375730 r0:c031a688
[<c003617c>] (do_exit+0x0/0x670) from [<c00368b8>] (do_group_exit+0x94/0xc0)
[<c0036824>] (do_group_exit+0x0/0xc0) from [<c0040558>] (get_signal_to_deliver+0x278/0x364)
r4:00000004
[<c00402e0>] (get_signal_to_deliver+0x0/0x364) from [<c0025658>] (do_signal+0x5c/0x4b4)
[<c00255fc>] (do_signal+0x0/0x4b4) from [<c0025c70>] (do_notify_resume+0x2c/0x30)
[<c0025c44>] (do_notify_resume+0x0/0x30) from [<c0022e6c>] (work_pending+0x1c/0x20)
不管busybox采用动态库,还是采用静态管;也不管是用交叉编译器arm-linux-gcc-3.4.1还是arm-linux-gcc-4.3.2,即使内核中配置了EABI选项,问题找不到解决方法,因此后面放弃,改为用现成的根文件系统和用户文件系统。
这个问题,我估计是文件系统相关配置不正确导致的。
2.3 制作CRAMFS根文件系统镜像
制作前,建议先用NFS挂载自己的根文件系统检测其是否可行,如果NFS可成功挂载,则说明你的根文件系统没问题了。
制作CRAMFS根文件镜像需要工具mkcramfs,我采用的是现成的且为静态编译mkcramfs工具,可直接使用
mkcramfs rootfs rootfs.cramfs
其中,rootfs 是根文件系统目录,rootfs.cramfs即生成的cramfs根文件系统镜像文件
生成后,在u-boot中把根文件系统镜像烧写到NAND FLASH对应的分区中。nand write.jffs2命令是u-boot本身自带中。
tftp 30000000 rootfs.cramfs;nand erase 260000 300000;nand write.jffs2 30000000 260000 300000
2.4 烧录CRAMFS文件系统镜像文件后出现错误
用mkcramfs工具生成了.cramfs镜像文件,同时烧写到NAND FLASH相应分区中。但启动时出现了如下错误:
rivers/rtc/hctosys.c: unable to open rtc device (rtc0)
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2, sector 0
Buffer I/O error on device mtdblock2, logical block 0
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2, sector 0
Buffer I/O error on device mtdblock2, logical block 0
end_request: I/O error, dev mtdblock2, sector 8
Buffer I/O error on device mtdblock2, logical block 1
end_request: I/O error, dev mtdblock2, sector 8
Buffer I/O error on device mtdblock2, logical block 1
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2, sector 16
Buffer I/O error on device mtdblock2, logical block 2
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2, sector 16
Buffer I/O error on device mtdblock2, logical block 2
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2, sector 24
Buffer I/O error on device mtdblock2, logical block 3
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2, sector 24
Buffer I/O error on device mtdblock2, logical block 3
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2, sector 0
FAT: unable to read boot sector
VFS: Cannot open root device “mtdblock2” or unknown-block(31,2)
Please append a correct “root=” boot option; here are the available partitions:
1f00 384 mtdblock0 (driver?)
1f01 2048 mtdblock1 (driver?)
1f02 2048 mtdblock2 (driver?)
1f03 61056 mtdblock3 (driver?)
Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(31,2)
Backtrace:
[<c0026908>] (dump_backtrace+0x0/0x12c) from [<c0026a4c>] (dump_stack+0x18/0x1c)
r7:c3809000 r6:c001e8d0 r5:c03958fc r4:c3809007
[<c0026a34>] (dump_stack+0x0/0x1c) from [<c0033b6c>] (panic+0x40/0x118)
[<c0033b2c>] (panic+0x0/0x118) from [<c0008d78>] (mount_block_root+0xfc/0x24c)
r3:00000000 r2:20000013 r1:c381df54 r0:c0315f3c
[<c0008c7c>] (mount_block_root+0x0/0x24c) from [<c0008f94>] (mount_root+0xcc/0xec)
[<c0008ec8>] (mount_root+0x0/0xec) from [<c00090ac>] (prepare_namespace+0xf8/0x194)
r6:c03952c4 r5:c001e888 r4:c001e88c
[<c0008fb4>] (prepare_namespace+0x0/0x194) from [<c0008a2c>] (kernel_init+0xc8/0xf4)
r6:c001d44c r5:c001d0fc r4:c03952b8
[<c0008964>] (kernel_init+0x0/0xf4) from [<c003617c>] (do_exit+0x0/0x670)
r6:00000000 r5:00000000 r4:00000000
开始以为是u-boot的启动参数不对所致,但改来改去,终是这个错误。后面在网上找到了解决方法,原因不是u-boot的启动参数导致的,而是自己移植的linux内核中NAND FLASH的ECC所致。
本人移植的内核版本是linux-2.6.30.4,修改内核文件:drivers/mtd/nand/s3c2410.c
在s3c2410_nand_init_chip()函数中,把
chip->ecc.mode = NAND_ECC_SOFT;
改为
chip->ecc.mode = NAND_ECC_NONE;
重新编译内核并下载到NAND FLASH则可以正常挂载NAND FLASH中的cramfs根文件系统了。
2.5 用户文件系统
用户文件系统位于NAND FLASH的mtdblock3分区中,采用适用于NAND FLASH的yaffs2格式文件系统。
当根文件系统挂载成功后,在相应启动脚本中把mtdblock3分区挂载到/mnt目录中。这样,当linux和文件系统启来后,文件系统中的mnt目录则我们的用户文件系统了。
到这里,或许有个疑问,用户文件系统是怎么烧写到的NAND FLASH的mtdblock3分区中呢?
其实这个问题很简单,也有多种方法。
1) 根文件系统启来后,用FTP把用户文件系统直接上传到mnt目录即可
当然,第一次使用之前,需要把mnt目录“格式化”一下,即先擦除一次mtdblock3分区。
2) 把用户文件系统打包,放在根文件系统某目录中如usr目录中,当根文件系统启动并挂载mtdblock3分区后,检测mnt目录下是否有标志文件,如果没有,则先擦除mtdblock3分区,再把用户文件系统解压到mnt目录中,同时在mnt目录中建立标志文件,防止以后每次启动根文件系统时都执行这样的操作。
本人采用了第二种方式,同时用户文件系统采用了高压缩率的7z格式。
宿主机安装7z命令方法:
sudo apt-get install p7zip-full
安装之后有7z和7za两个命令,7za是一个独立的命令,支持的格式比7z少
把用户文件系统用7z打包后,放在usr相关目录中,同时在根文件系统中建立相应的执行脚本,脚本如何实现,在此不放出来了!
3. 附记:使用交换机实现目标板和开发PC互联互通
在此之前,曾使用过路由器来实现目标板和开发PC(宿主机)互联互通,但宿主机不能上外网了,仍旧是要上网查资料时,要把目标板跟宿主机的网线拔掉,插上外网线。
不过,这次挺好,终于不用这么麻烦了,使用TPLINK交换机实现了
4. 参考资料
4.1 制作CRAMFS文件系统镜像文件:
http://blog.ednchina.com/xiong_gang_whut/240012/message.aspx
4.2 烧录CRAMFS文件系统镜像文件后出现错误:
http://blog.163.com/jant126@126/blog/static/12008366200791110249642/
http://blog.21ic.com/user1/1831/archives/2010/70196.html
http://blog.csdn.net/hfyinsdu/article/details/5953364
http://www.cnblogs.com/yyangblog/archive/2011/06/14/2080773.html
4.3 根文件系统制作:
http://blog.csdn.net/csuwzc/article/details/6527654
推荐阅读相关文章:
- u-boot-2011.03移植系列专题汇总
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###6.使用AXD和JLINK调试u-boot方法与步骤
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###5.使用JLINK间接烧写u-boot至FLASH的方法与步骤
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###4.支持内核启动
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###3.移植和配置CS8900网卡
- 移植u-boot-2011.03到S3C2440(utu2440)方法与步骤###1. 配置和初步编译
- 三星6410裸机程序开发1:tiny6410开发板和裸机开发环境
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###7.NAND FLASH部分移植和支持NAND FLASH启动和读写