经过差不多一周时间的折腾(当然是业余时间)终于在我的FS2410开发板上将自己亲手编译的U-boot 1.1.6和Linux内核2.6.24跑起来了,在此以图为证,呵呵,
这其中的曲折岂能用一两句能表达清楚呀,可以说是酸甜苦辣咸五味俱全了。
首先说明一下我的操作环境:
OS:Deepin 11.06
GCC:4.5.2
ARM-Linux-GCC:gcc version 4.6.1 (Sourcery CodeBench Lite 2011.09-70)
为了能正常编译busybox 1.19.4,还专门下载了友善之臂提供的arm-linux 4.4.3
网上有关此类技术的文件可以说是一抓一大把,但按其说明操作下来,成功的不算多,也许是因为文件年头太老,用现在的新编译器可能不支持了,(当然是不同的Linux内核版本都有对应的
GCC版本的)。这里特别感谢一下http://bbs.ednchina.com/BLOG_ARTICLE_179329.HTM这系列的三篇文章,按这里的操作,慢慢走出迷茫,找到其中的门道。
具体步骤不再详述,可直接参考上述文章内容,这里只记录一下大概步骤及我所碰到的一个个‘拦路虎’
一、根据FS2410配置,修改u-boot 1.1.6的代码,并添加一些代码让它具有读写NandFlash功能及常用的基本命令,如tftp,printenv,nand erase , nand write等关键功能。
编译生成U-boot产物通过DWN软件写入Nandflash的开头位置(即从0x00000000位置开始),将开发板切换到Nor Flash启动方式,通过自带bootloader来将自己的u-boot写入Nand中。
然后再切换为Nand Flash启动模式,可以通过printenv命令来查看当前的设置,如下图所示:
二、Linux内核2.6.24移植
此类文件网上也很丰富,这里我主要参考了http://hi.chinaunix.net/?uid-20754091-action-viewspace-itemid-36292的步骤,特别的是我这为Nand Flash重新划分为四个区如下:
arch/arm/plat-s3c24xx/common-smdk.c
/* NAND parititon from 2.4.18-swl5 */
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "BootLoader",
.size = 0x00040000, /* 256KB */
.offset = 0,
},
[1] = {
.name = "Kernel",
.size = 0x00200000, /* 2MB */
.offset = 0x00040000,
},
[2] = {
.name = "Rootfs",
.size = 0x01000000, /* 16MB */
.offset = 0x00240000,
},
[3] = {
.name = "Appfs",
.size = 0x02DC0000, /* 44MB + 792KB */
.offset = 0x01240000,
}
};
Linux内核编译成功后,又将产物做成u-boot支持的镜像形式,即在原镜像头部添加一段数据,(这也是为什么内核镜像文件从Nand 上读到0x30007fc0位置,而不是0x30008000)
这部分操作主要参考了http://blog.chinaunix.net/uid-20662820-id-3073461.html,生成uImage的命令是:
mkimage -n "linux-2.6.29.6-maguicai-arm" -A arm -O linux -T kernel -C none -a 0x30007fc0 -e 30008000 -d zImage uImage
注:
-A == set architecture to 'arch'
-O == set operating system to 'os'
-T == set image type to 'type'
-C == set compression type 'comp'
-a == set load address to 'addr' (hex)
-e == set entry point to 'ep' (hex)
-n == set image name to 'name'
-d == use image data from 'datafile'
-x == set XIP (execute in place)
1)有所不同的地方就是写内核文件到Nand Flash时,命令是:
nand erase 0x00040000 0x200000;tftp 0x30008000 uImage;nand write 0x30008000 0x00040000 0x200000
注:这里nand earse和nand write对应的nand flash上的地址范围是与上面的第二分区(name为kernel)的范围对应的,
另注:要理解tftp和nand write第一个参数是指RAM上的地址,通过tftp下载镜像,是先下载到RAM中,然后再写入到nand flash里去的。
2)设置bootcmd
这个U-boot变量是用来启动内核用的,在U-boot运行状态下,执行如下命令,
set bootcmd nand read 0x30007fc0 0x00040000 0x200000\;bootm 0x30007fc0;saveenv
3)设置启动参数bootargs
这个参数是U-Boot传给Linux内核的,在Linux内核编译时可以设置,但没在U-boot里设置灵活,
设置后,通过printenv命令,查看如下图所示:
这其中设置了根文件系统在mtdblock2即Nand Flash的第三分区,根文件系统类型为jffs2,加载内核文件后,执行linuxrc文件来启动相关程序。
三、根文件系统的制作
根文件系统和Linux内核是两个独立的部分,但又是不可分割的。具体操作可参考网上其它资源,
这里只记录一下主要注意的地方,
(1)生成根文件系统:
mkfs.jffs2 -r my_rootfs -o jffs2.img -e 0x4000 --pad=0x01000000 -n
注:1)my_rootfs是我本地搭建的根文件系统的目录,用来生成镜像的,
2) -o jffs2.img是指生成为jffs2.img镜像文件
3) -e 0x4000 ,是指块大小,这与不同的Nand Flash相关,这里是三星的K9F1208U0B.固定为0x4000
4) --pad=0x01000000 用16進制來表示所要輸出檔案的大小,即jffs2.img的大小,为了不浪费Nand Flash空间,这里设成与当前第三分区大小一致。
(2)烧写根文件系统:
tftp 0x30008000 jffs2.img;nand erase 0x00240000 0x01000000;nand write 0x30008000 0x00240000 0x01000000
注:1)nand erase时一定要是当前分区 的全部,nand write时,大小为当前文件的实际大小,这里与当前分区一致了即 0x01000000
常见问题:(我所遇到的几个问题)
1)错误信息:
到内核启动时,报:Error: unrecognized/unsupported machine ID
原因及解决办法:
原因大致是u-boot 传递给
内核的machine ID错误,可以手动在内核源代码中添加machine ID.
解决方法:
在u-boot 命令行中输入bdinfo
查看板卡信息,我的输出如下:
FS2410# bdinfo
arch_number = 0x000000C1
env_t = 0x00000000
boot_params = 0x30000100
DRAM bank = 0x00000000
-> start = 0x30000000
-> size = 0x04000000
ethaddr = 08:00:3E:26:0A:5B
ip_addr = 10.1.8.245
baudrate = 115200 bps
修改内核的arch/arm/kernel/head.S,直接将s3c2410的参数赋给内核
# cd linux-2.6.19
# vi arch/arm/kernel/head.S +72
----------------------------------------------
70 __INIT
71 .type stext, %function
72 ENTRY(stext)
/********* add here *********/
mov r0, #0
mov r1, #0xc1
ldr r2, =0x30000100
/********* end add *********/
73 msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
2)错误信息:在加载Linux内核时报:Verifying Checksum ... Bad Data CRC
一般原因是由于内核所点区域被其它所侵占,导致检测异常,我这里是nand erase和nand write时,没有与该分区大小对应上。
3)错误信息:
在启动内核加载根文件系统过程中,报
Further such events for this erase block will not be printed
Node at 0x00147fbc with length 0x0000004b would run over the end of the erase block
Perhaps the file system was created with the wrong erase size?
原因及解决办法:
根文件系统写入到Nand Flash时,要指定文件的实际大小,即nand write 0x30008000 0x00240000 0x01000000 中,最后一个数目是文件的实际大小。
4)错误信息:
加载内核根文件系统时,报错:
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e154: 0xfbeb instead
一般原因是
是制作文件系统时使用 mkfs.jffs2 命令有误,FS2410板的nand flash是三星的K9F1208U0B。使用的命令是:
mkfs.jffs2 -r /source/rootfs -o rootfs.jffs2 -e 0x4000 --pad=0x800000 -n
各参数的意义:
(1)-r : 指定要做成image的源資料夾.
(2)-o : 指定輸出image檔案的文件名.
(3)-e : 每一塊要抹除的block size,預設是64KB.要注意,不同的flash, 其block size會不一樣.我的是三星的K9F1208U0B.
(4)--pad (-p): 用16進制來表示所要輸出檔案的大小,也就是root.jffs2的size。很重要的是, 為了不浪費flash空間, 這個值最好符合flash driver所規劃的區塊大小.这里使用的是8MB.
(5)如果挂载后会出现类似:CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0 的警告,则加上 -n 就会消失。
(6) 还有的选项,自己看帮助!-h
我这里是-e参数值错误所导致。
5)启动最后报:
Warning: unable to open an initial console.
这个一般是因为在创建根文件系统时,并没有创建 console设备。