Helper2416是基于三星S3C2416处理器的开发板,现在当下在CPU主频飞速发展的环境下基于ARM9的S3C2416处理器已然落伍,但是用作学习和对性能要求不高的产品还是绰绰有余的。我是通过论坛得到的,之前一直在吃灰,现在正好在学习嵌入式Linux,前面也用了不少用全志处理器的板子,但是总感觉全志的板子给人的自由度不高,最要命的是全志处理器的学习资料不多,真的很难在网上找到,三星提供的资料还是非常全的,学习起来应该比较顺手,那就尝尝这块板子吧。
板子自带的资源里面有编译器、板载所有芯片的数据手册、三星官方文档、硬件资料、烧录镜像、源码和工具。编译器的版本比较旧了,我使用我之前文章:
http://blog.csdn.net/tq384998430/article/details/77864324里面转载的ARM交叉编译工具,使用的版本是 Codesourcery 公司的arm-none-linux-gnueabi-gcc编译器,gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29)不支持硬件浮点(hf)。
下载编译器之后解压到工作目录,不用设置环境变量,后面使用到直接引用全路径就行了。将提供的Linux kernel和uboot源码解压到工作目录中去。需要搭建根文件系统,可以使用busybox工具,从官方下载最新的busybox解压即可。现在工作目录下应该有下面文件:
tq@ubuntu:~/work/helper2416$ ls
arm-jyxtec-linux-gnueabi busybox-1.27.2 s3c-linux.jyx u-boot-1.3.4.jyx
编译源代码之前先将宿主系统的环境搭建好,学习阶段为了避免频繁的烧写内核和方便的修改板子的根文件系统,我们使用TFTP服务器和NFS服务器,u-boot启动的时候从TFTP服务器中获取内核镜像uImage或者zImage,内核起来之后挂载NFS服务器的根文件系统。搭建TFTP服务器和NFS服务器网上教程非常多,不再敖述,不能挂载Windows的NFS服务器,Windows文件系统不支持Linux的软连接等特性。另外板子已经烧写了uboot在nandflash中了,我们的可以直接使用,烧写uboot倒是不难,可以烧写到nandflash中启动uboot也可以烧写到SD卡中启动。
现在一切就绪了,可以编译内核了,内核源码中已经有提供好的配置文件了Helper2416,复制Helper2416文件成“.config”文件或者使用
make ARCH=arm CROSS_COMPILE=compiler_path/arm-linux- menuconfig
在最下面的load a alternative configuration file加载Helper2416文件。可以自己在此基础上对系统进行剪裁,从头开始配置一个Linux源码是很麻烦的,初级阶段使用现成的配置文件进行修改是明智的选择,等哪天熟悉了之后尝试从头剪裁一个Linux内核。然后执行编译命令:
make ARCH=arm CROSS_COMPILE=compiler_path/arm-linux- uImage
编译完成之后Image、zImage、uImage和都放在archarmoot目录下面,但是实际上没有生成uImage只有zImage和Image文件,没有将zImage转成uImage,无所谓,提供的uboot源码修改过了是支持zImage启动的(反而不支持uImage了)。现在得到了内核镜像了,完成了最重要的一步。试试从TFTP服务器启动内核试试。
1、将zImage拷贝到TFTP服务器根目录中。
2、进入uboot命令行模式,查看当前的bootcmd:
Helper2416
bootcmd=nand read.i c0008000 40000 300000;bootm c0008000
现在是从nandflash中的40000地址处读取300000个字节的数据到内存地址c0008000处,那我们就仿造这个从TFTP中读取zImage到内存的c0008000处:
Helper2416
smc911x: initializing
smc911x: detected LAN9220 controller
smc911x: phy initialized
smc911x: MAC 00:40:5c:26:0a:5b
TFTP from server 192.168.1.106; our IP address is 192.168.1.111
Filename 'zImage'.
Load address: 0xc0008000
Loading:
done
Bytes transferred = 1924944 (0x1d5f50)
顺利读取到zImage,然后我们注意到bootcmd后面还有一个bootm c0008000,意思就是从c0008000地址处启动内核,我也照做:
Helper2416
Boot with zImage
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Linux version 3.2.50 (root@ubuntu) (gcc version 4.4.6 (crosstool-NG 1.13.3) )
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: SMDK2416
Memory policy: ECC disabled, Data cache writeback
CPU S3C2416/S3C2450 (id 0x32450003)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
CPU: MPLL on 534.000 MHz, cpu 534.000 MHz, mem 133.500 MHz, pclk 66.750 MHz
CPU: EPLL on 96.000 MHz, usb-bus 48.000 MHz
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: root=/dev/mtdblock2 console=ttySAC0,115200 rootfstype=yaffs2 mem=64m
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 59612k/59612k available, 5924k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
vmalloc : 0xc4800000 - 0xf6000000 ( 792 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0xc0008000 - 0xc048f598 (4638 kB)
.init : 0xc0490000 - 0xc04d4000 ( 272 kB)
.data : 0xc04d4000 - 0xc04ff500 ( 174 kB)
.bss : 0xc04ff524 - 0xc052c81c ( 181 kB)
......
Please press Enter to activate this console. smc911x smc911x: eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1
[root@jyxtec /]
启动内核成功!!!
到现在我们已经可以编译自己的内核了,可以添加自己的驱动代码了,但是先不急着写驱动程序,还有一个重要的步骤要做,那就是搭建自己的根文件系统,前面使用的是烧写到nandflash中的根文件系统。其实根文件系统就是内核起来之后可以使用到的文件目录,文件目录下有/dev /etc /lib /usr /var /proc /tmp /home /root /mnt /bin /sbin /sys等文件夹,其中有的文件夹必不可少,例如bin文件夹中的文件都是可执行的文件或者脚本,如果没有的话我们连ls命令都没法用。所以我们需要制作一个基本的根文件系统所需要的内容。
首先我们在宿主Ubuntu系统的NFS服务器指定的根目录nfsroot下建立一个文件夹helper2416-rootfs作为根文件系统,这样NFS客户端挂载到NFS主机的时候就能指定挂载到helper2416-rootfs文件夹,所有我们在根文件夹中存放上面说的dev、bin、lib、usr等文件夹,很简单,mkdir创建文件夹就行了:
mkdir dev etc lib usr var proc tmp home root mnt sys
然后我们修改uboot的bootargs参数使得内核挂载到NFS根文件系统上去。启动板子进入到uboot的命令行模式修改bootargs。我们先查看当前的bootargs参数:
Helper2416
bootargs=root=/dev/mtdblock2 console=ttySAC0,115200 rootfstype=yaffs2 mem=64m
我们修改成:
setenv bootargs 'root=/dev/nfs console=ttySAC0,115200 nfsroot=192.168.1.106:/home/tq/work/nfsroot/helper2416-rootfs/ rw ip=dhcp rootfstype=nfs mem=64m'
然后执行boot命令启动Linux内核,但是由于我们创建的根文件系统中的文件夹都是空的,还不能用,挂载上去了也没用,输出最后部分信息如下:
IP-Config: Complete:
device=eth0, addr=192.168.1.178, mask=255.255.255.0, gw=192.168.1.1,
host=192.168.1.178, domain=, nis-domain=(none),
bootserver=0.0.0.0, rootserver=192.168.1.106, rootpath=
VFS: Mounted root (nfs filesystem) on device 0:12.
Freeing init memory: 272K
Kernel panic - not syncing: No init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
[] (unwind_backtrace+0x0/0xf0) from [] (panic+0x54/0x190)
[] (panic+0x54/0x190) from [] (init_post+0xa0/0xc4)
[] (init_post+0xa0/0xc4) from [] (kernel_init+0xf8/0x12c)
其中Kernel panic - not syncing: No init found. Try passing init= option to kernel表示init进程没有找到,说明这个init进程是必须的,我们还是使用busybox来创建一个最简单的根文件系统吧。busybox的使用参见我转载的文章:
http://blog.csdn.net/tq384998430/article/details/77853165,简单来说就是下载最新的busybox源码并解压之后使用menuconfig进行配置,进入到Busybox Settings->Build Options目录下配置:
[*] Build BusyBox as a static binary (no shared libs)
[ ] Force NOMMU build
[*] Build with Large File Support (for accessing files > 2 GB)
(/home/tq/work/arm-2014.05/bin/arm-none-linux-gnueabi-) Cross Compiler prefi
对busybox进行静态编译,不需要动态链接库的支持,方便我们进行开发调试,只是文件较动态编译更大。然后在下面进行Cross Compiler prefix配置,将自己的交叉编译器的路径写进去,相当于使用make的时候制定CROSS_COMPILE一样。配置完这两样之后进行make编译,编译完成之后执行make install,生成的内容存放在“_install”文件夹中:
tq@ubuntu:~/work/helper2416/busybox-1.27.2$ ls _install/
bin linuxrc sbin usr
哈哈,很顺利,我们得到了三个重要的文件和一个linuxrc文件。查看bin文件夹中的内容:
tq@ubuntu:~/work/helper2416/busybox-1.27.2$ ls _install/bin/ -al
total 1992
drwxr-xr-x 2 root root 4096 Sep 6 08:08 .
drwxr-xr-x 5 root root 4096 Sep 6 08:08 ..
lrwxrwxrwx 1 root root 7 Sep 6 08:08 ash -> busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 base64 -> busybox
-rwxr-xr-x 1 root root 2029316 Sep 6 08:08 busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 cat -> busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 chattr -> busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 chgrp -> busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 chmod -> busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 chown -> busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 conspy -> busybox
lrwxrwxrwx 1 root root 7 Sep 6 08:08 cp -> busybox
......
我们发现所有的文件都是busybox文件的链接文件,意思就是执行cat命令和ls命令的时候都会执行到busybox,那为什么执行cat和ls命令得到的结果不一样呢?其实很简单,执行ls命令的时候“ls”作为一个参数传入到了可执行文件busybox中去了,busybox文件会识别第一个参数的名称,如果识别到的是“ls”就会执行ls相应的处理,可以做一个测试,当help2416板子挂载到根文件系统之后执行命令:
/ # busybox ls
a.txt dev home linuxrc proc tmp var
bin etc lib mnt sbin usr
结果很明显。当然了这里命令的第一个参数是“busybox”而不是“ls”,我猜测busybox程序会判断第一个参数是不是“busybox”,不是的话以第一个参数作为实际命令,是的话则表示第二个参数为实际命令。总的来说busybox文件其实是一个功能十分多的文件,可以完成ls、cd、cat等等命令的功能,然后使用软连接的方式创建很多busybox所能完成的命令,我们可以理解busybox名字的意思了,busy box,的确是一个很忙碌的盒子,鸡贼!
我们将编译busybox生成的几个文件和文件夹都拷贝到我们创建的根文件夹helper2416-rootfs里面去,然后按照前面说的方法修改bootargs参数启动Linux内核,前面已经透露了挂载上这个根文件系统之后是可以使用的,因为bin文件夹里面已经有init文件了,也就是系统初始化程序(也是指向busybox的)。结尾部分log内容如下:
device=eth0, addr=192.168.1.182, mask=255.255.255.0, gw=192.168.1.1,
host=192.168.1.182, domain=, nis-domain=(none),
bootserver=0.0.0.0, rootserver=192.168.1.106, rootpath=
VFS: Mounted root (nfs filesystem) on device 0:12.
Freeing init memory: 272K
can't run '/etc/init.d/rcS': No such file or directory
Please press Enter to activate this console.
bingo,成功启动内核并挂载到根文件系统,尝试执行命令:
/ # ls
a.txt dev home linuxrc proc tmp var
bin etc lib mnt sbin usr
没有问题!
现在虽然可以正常使用Linux的各种命令了,但是我们的lib、etc、usr等文件夹下都是空的,很多事还是做不了的,例如lib目录下没有库文件,我们的程序连printf都调用不了!!!下一篇准备试试搭建一个完整可用的根文件系统,正好对Linux的根文件系统有个更清楚的认识。