现在的位置: 首页 > 综合 > 正文

构建嵌入式linux操作系统过程

2012年06月25日 ⁄ 综合 ⁄ 共 6712字 ⁄ 字号 评论关闭

 

开发环境

宿主机:Linux fedora 2.6.27.5-117.fc10.i686
交叉编译环境:arm-linux-gcc-3.4.5 glibc-2.3.6
软件工具:H-JTAG V1.0 , SEGGER J-Link Commander V4.10i , CodeWarrior for ARM Developer Suite V1.2 , busybox-1.19.2.tar.bz2
内核版本:linux-2.6.28.7
开发板硬件:
(处理器:arm920t
(Nor flash:INTEL JS28F320J3 位宽16bit 4MB
(Nand flash:SAMSUNG K9F2G08 位宽8bit 128MB*2
(主板:飞凌 S3C2440
(网卡:DM9000 10/100Mb/s

操作步骤

【交叉编译环境的搭建】

 

首先搭建交叉编译环境,我这里直接将光盘中给出的交叉编译器进行解包,放到相应的目录,然后添加环境变量,指明交叉编译器所在的目录。
tar -jxvf arm-linux-gcc-3.4.5-glibc-2.3.6.tar.bz2

一般的添加环境变量的方法是:
export PATH=$PATH:/opt/work/tools/gcc-3.4.5-glibc-2.3.6/bin

为了以后的方便,不必每次开机后都输入一遍 export 语句,可以把上面这句命令写进一个文件,
我这里命名为 env.sh,以后每次只要输入下面的命令就可以了:
. env.sh文件所在的路径

 

【bootloader】


关于bootloader可以有2种推荐的方法,使用 u-boot 或是开发板自带的 bootloader。
u-boot的移植我这里不做说明,下面讲解烧写bootloader到开发板的flash的方法。

首先查阅开发板的跳线说明,一般跳线在开发板的核心板上,进过查询相关资料发现,
"FL2440上的两个跳线帽子J2和J5,J5这个跳线帽子,它是为了设置究竟是从Nandflash启动,还是从Norflash启动,如果我们要从Norflash启动的话,一定不要接上J5这个跳线帽子,如果从Nandflash启动的话,就要短接上。如果要从Norflash启动,J5跳线帽子拔掉,J2跳到0上"

使用H-JTAG烧写
将开发板的JTAG口与PC的并口连接,打开板子电源,打开H-JTAG,在菜单中选择‘Settings’->‘USB/LPT Selection’,选中LPT,点击OK,软件将自动检测开发板芯片,如果出现“Unable to find target.Please make sure that the hardware is properly connected and powered up.”原因可能是并口没有连接好、并口驱动没有安装、板子没有上电。
当检查到板子芯片后,启动 H-Flasher,在Flash Selection 中选中板子对应的Flash(H-JTAG 1.0版本已经有了本开发板的Nor flash  和Nand flash型号),在Configuration中填好RAM Start Address,然后在Programming 中点击Check检测芯片和Flash,检测成功后会显示Flash型号,然后选择Src File,就是bootloader所在的路径,最后点击Program,等待烧写完成,烧写成功后会显示successful。
此时,断电,拔掉JTAG连线,连接上串口,然后通电,就可以看到串口中的信息了。

使用J-Link Commander烧写
init.bin文件是用来初始化内存设备的程序,可以网上下载,这个一般是通用的。
将J-Link连接好板子的JTAG口,另一端连接好PC的USB,先给板子通电,然后打开J-Link Commander,在命令行下面依次输入下面的命令:
speed 12000
loadbin "F:\Program Files\tftp\init.bin" 0x40000000  //如果是Nand falsh 启动,将地址设置为0x0
setpc 0x40000000
g
h
loadbin "F:\Program Files\tftp\u-boot.bin" 0x33f80000
setpc 0x33f80000
g
好了,到这里在串口中应该可以看到uboot的输出了。
如果串口没有任何输出,可能的原因是uboot没有移植成功,导致与板子不兼容。
下面就将uboot从内存中写进flash中,可以使用J-Link下载u-boot.bin,也可以使用uboot的命令tftp。
注意不能使用刚才已经下载到0x33f80000地址的文件,因为uboot一旦运行起来,内存中的数据就改变了,所以必须重新下载到另外一个没有使用的内存地址处。
使用J-Link :
h   //首先将内存中的正在运行的u-boot暂停
loadbin "F:\Program Files\tftp\u-boot.bin" 0x35000000
g   //恢复运行

使用uboot:
tftp 0x35000000 u-boot.bin   //首先确保PC机上的tftp服务器已经运行,并且设置好下载目录
下面就是烧写到flash中,
对于Nor flash:
先使用flinfo查看Nor flash的信息,确定有多少块,每一块存储容量多大,然后执行下面的命令
protect off all
erase 0 3ffff
cp.b 0x35000000 0 40000
对于erase 和cp命令,如果有不清楚的可以输入?或help查看用法

对于Nand flash:
nand erase 0 40000
nand write 0x35000000 0 40000

到此已经完成bootloader的烧写。

 

【内核】


下面讲解内核的移植。
首先需要弄明白内核与bootloader有哪些交互的地方:
1、传递给内核的参数存放的地址;
2、传递给内核的参数的格式;
3、机器类型ID;
4、启动命令。

我这里直接使用光盘里面的内核,里面有个已经修改好的配置文件。
首先确保交叉编译器已经在系统环境中给出
解压缩内核
tar -zxvf 2440-linux-2.6.28.tar.gz
cd linux-2.6.28.7
make menuconfig
选择 ‘Load an Alternate Configuration File’然后载入配置文件
make zImage

最后在 arch/arm/boot 目录下会生成 zImage 映像文件。
对于飞凌的bootloader,它给 wince分了一半的nand flash,由于我并不需要wince系统,所以修改bootloader源代码,把wince的分区删除,需要修改nand.c源文件
将下面的数据结构修改

//可更改删除分区,分区名字不可改
static struct Partition NandPart[] = {
	{0, 		 0x00020000, "boot"},		//128K one block
	{0x00020000, 0x00060000, "bootParam"},	//384K three blocks
	{0x00080000, 0x00100000, "pic"},		//1M
	{0x00180000, 0x00380000, "MyApp"},		//3.5M
	{0x00500000, 0x00300000, "kernel"},		//3M
	{0x00800000, 0x03c00000, "fs_yaffs"},	//60M
	{0x04400000, 0x00080000, "eboot"},		//512K
	{0x04480000, 0x03b80000, "wince"},		//59.5M
	{0,			 0         , 0}
};

 

改为:

 

static struct Partition NandPart[] = {
	{0, 		 0x00020000, "boot"},		//128K one block
	{0x00020000, 0x00060000, "bootParam"},	//384K three blocks
	{0x00080000, 0x00100000, "pic"},		//1M
	{0x00180000, 0x00380000, "MyApp"},		//3.5M
	{0x00500000, 0x00300000, "kernel"},		//3M
	{0x00800000, 0x0F800000, "fs_yaffs"},	//248M
	//{0x0fe80000, 0x00080000, "eboot"},		//512K
	//{0x0FF00000, 0x00100000, "wince"},		//1M
	{0,			 0         , 0}
};

然后修改内核源文件,使之与bootloader对应,修改的源文件路径为
arch/arm/plat-s3c24xx/common-smdk.c

需要修改下面的数据结构,修改后的结果如下:

static struct mtd_partition smdk_default_nand_part[] = {

[0] = {
                .name   = "Boot",
                .size   = 0x00100000,
                .offset = 0
        },
        [1] = {
                .name   = "MyApp",
                .size   = 0x003c0000,
                .offset = 0x00140000,
        },
        [2] = {
                .name   = "Kernel",
                .size   = 0x00300000,
                .offset = 0x00500000,
        },
        [3] = {
                .name   = "fs_yaffs",
                .size   = 0x0F800000,    //248M
                .offset = 0x00800000,
        }
        /*
        ,
        [4] = {
                .name   = "WINCE",
                .size   = 0x00180000,
                .offset = 0x0fe80000,
        }
        */
};

上面只需要注意内核和文件系统的起始地址和大小一定要和bootloader对应。

当烧写内核和文件映像后如果出现下面的错误
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,3)
,可能的原因是:
1、yaffs文件系统补丁没有打上;
2、内核配置的时候没有选中 YAFFS file system support;
3、内核中文件系统的分区与烧写进flash的地址不对应;
4、制作文件系统的工具mkyaffs2image,与给内核打补丁中的工具不一致;
5、烧写文件系统之前没有清除原先的flash

 

【文件系统】


最后讲讲制作根文件系统
基本原理就是把一个制作好的目录按照一定的格式转换成一个文件,然后烧写到Nand flash中的文件系统分区的开始位置。

一个根文件系统推荐按照FHS规定的格式制作,一个最小的根文件系统应该具备下面的目录

/
 |_ /bin   //存放所有用户都可以使用的、基本的命令
 |_ /sbin  //存放只有管理员才能够使用的命令,用于启动系统、修复系统
 |_ /dev   //存放设备文件,包括字符设备和块设备
 |_ /etc   //存放各种配置文件启动脚本
 |_ /lib   //存放共享库和加载模块
 |_ /home  //用户目录
 |_ /root  //root用户的目录
 |_ /usr   //里面存放的是用户程序
 |_ /var   //存放可变的数据
 |_ /proc  //通常是个空目录,常用于proc文件系统的挂载点
 |_ /mnt   //用于临时挂载文件系统
 |_ /tmp   //存放临时文件,通常是空目录

首先移植busybox,此程序集成了众多的Linux工具,编译后安装,会生成下面的文件和目录
drwxr-xr-x 2 root root 4096 2011-11-25 11:17 bin
lrwxrwxrwx 1 root root   11 2011-11-25 11:17 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 4096 2011-11-25 11:17 sbin
drwxr-xr-x 4 root root 4096 2011-11-25 11:17 usr

其实里面的文件都是一个bin/busybox的软链接。
编译busybox的步骤为:
tar -jxvf busybox-1.19.2.tar.bz2
cd busybox-1.19.2
make menuconfig
make
make install
安装后会在本层目录下生成 _install 目录,里面就是编译好的可执行文件

编译过程中如果遇到错误:
miscutils/ionice.c: In function 'ioprio_set':
miscutils/ionice.c:16: error: 'SYS_ioprio_set' undeclared (first use inthis function)
,方法如下:
在 make menuconfig的时候将Miscellaneous Utilities  ---> ionice  取消选中

miscutils/ubi_tools.c:63:26: error: mtd/ubi-user.h: No such file or directory
miscutils/ubi_tools.c: In function 'ubi_tools_main':
miscutils/ubi_tools.c:133: error: 'UBI_DEV_NUM_AUTO' undeclared (first use in this function)
,方法如下:
将内核源代码中的include\mtd\ubi-user.h拷贝到busybox下的include\mtd下。

接下来把glibc-2.3.6的加载器和动态库拷贝到 /lib目录下。
制作启动脚本,/etc目录下必须存在这几个文件 fstab inittab /init.d/rcS
其中各个文件的内容如下:

[root@wayos-fedora etc]# cat inittab

::sysinit:/etc/init.d/rcS
s3c2410_serial0::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

[root@wayos-fedora etc]# cat fstab
# device     mount-point    type   options        dump  fsck order
proc           /proc        proc   defaults        0     0
tmpfs          /tmp         tmpfs  defaults        0     0
sysfs          /sys         sysfs  defaults        0     0
tmpfs          /dev         tmpfs  defaults        0     0

[root@wayos-fedora init.d]# cat rcS
#!/bin/sh
ifconfig eth0 192.168.61.110 up
ifconfig lo up
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

dev目录我使用的是mdev创建,在 /dev 目录下必须存在2个文件:
[root@wayos-fedora fs_mdev_busybox-1.19.2]# ls -l dev/
total 0
crw-r--r-- 1 root root 5, 1 2011-11-25 14:27 console
crw-r--r-- 1 root root 1, 3 2011-11-25 14:27 null

默认串口登陆是没有要求输入用户名和密码的,当使用telnet登陆开发板的时候需要输入用户名和密码,而当前我们没有创建任何用户,所以为了能够远程登陆进开发板,需要创建一个用户,我们创建root 用户,方法为在 etc目录下创建 group passwd 2个文件,内容如下:
[root@wayos-fedora etc]# cat group
root::0:root
[root@wayos-fedora etc]# cat passwd
root::0:0:root:/root:/bin/sh
用户名是root ,密码为空。默认登陆后在/root目录下。

根目录做好后使用下面的命令制作文件映像:
./mkyaffs2image ./fs_mdev_busybox-1.19.2/ ./fs_mdev_busybox-1.19.2.yaffs
然后将这个映像文件烧写到flash的文件分区即可。

抱歉!评论已关闭.