我的宿主机操作系统是RedHat9.0(建议安装的时候选择“完全安装”)
一个嵌入式Linux系统从软件的角度来看,分为四个层次:
以下是开发环境搭建过程中涉及到的知识点
minicom是Linux OS下功能强大的串口终端程序。具体使用方法在此不详述,有很多相关资料可供查阅。
NOTE:在minicom的设置中,波特率要设置正确(否则,终端上是乱码),软件流控制和硬件流控制都应设置为“无”或“NO”。
minicom的设置被保存到文件/etc/minirc.dfl中。
进入有颜色的minicom界面:# minicom -m8 -c on
在这里,我是通过网络下载kernel image和root fs到开发板的。
tftp服务器是由超级守护进程xinetd运行的,这使得tftp服务器的配置操作比独立运行守护进程的服务器(如 vsftpd)简单得多。一般,修改文件/etc/xinetd.d/tftp,当然,只有安装了tftp服务器,才会有这个文件。把“disable = yes”改成“disable = no”,然后保存,退出。重新启动超级守护进程xinetd,# service xinetd restart.把要下载的文件放到根目录下的tftpboot子目录中就ok了。
NOTE:在控制台终端输入“setup”,选中system services,回车进入系统服务选项菜单,选中[*] tftp(如果没有tftp服务,说明RedHat9.0安装的时候没有选择tftp服务,可以去安装包映像或安装光盘中找到相应的rpm包安装,ok),保存,退出setup界面。
NFS是由SUN公司发展出来的分散式文件系统。可以让用户通过连接的网络,将其他电脑所共享的文件目录,映射到自己的系统下。用户在操作这些文件和目录时,感觉如同存储在本机上一样。共享出目录的一方称为NFS服务端,另一端称为NFS客户端。这里,当然是在开发板和宿主机之间建立NFS共享。
NOTE:首先确认宿主机上安装了NFS(查看目录/etc/xinetd.d/下是否存在nfs文件)。
NFS服务器端操作如下:
# ifconfig eth0 down
# ifconfig eth0 192.168.1.1 up
/home/embeder/nfs 192.168.1.2(rw,sync,no_root_squash)
允许IP为192.168.1.2的ARMer9开发系统将宿主机上的/home/embeder/nfs这个目录mount到开发系统下,即,ARMer9开发系统可以通过网络访问宿主机上的/home/embeder/nfs目录。
# cd /etc/init.d
# exportfs -rav
# ./nfs restart
NFS客户端的操作如下:
# ifconfig eth0 down
# ifconfig eth0 192.168.1.2 up
# ping -c 5 192.168.1.1
# mkdir /tmp/nfs
# mount -t nfs -o nolock 192.168.1.1:/home/embeder/nfs /tmp/nfs
下面就可以用这种方式在开发板上调试自己的应用程序了。
这里,我已经有了目标开发系统的Linux移植源代码,否则,移植是一项烦杂的事情,有时间的话,这也是一件很值得尝试的事情。
编译内核的软件环境是KBuild系统,泛指构建一个完整并能够运行的Linux内核所需要的一切资源。这些资源包括构建程序,脚本,中间件,配置文件和Makefile。依次进行以下操作:
# make menuconfig进入Linux内核配置界面。
NOTE:在block device中选上ramdisk的支持并且根据需要修改ramdisk的默认大小,并且选上initrd的支持。还有,在file system中选上自己文件系统所用格式的相应支持(这里是ext3),否则,kernel将不能正确引导文件系统(一般出现kernel panic提示信息)。
我在这里静态编译进了目标开发板的声卡驱动,即Philip uda1341,在sound选项里面,当然,也可以用module的方式编译。
# make dep
kbuild调用中间件Script/mkdep来生成描述与核心文件形成依赖关系的.h文件(绝大多数)列表。这个列表保存在 .depend 中。用户即使不执行这一步,kbuild也会执行的。
# make clean
清除上次编译生成的 .o 文件。
# make zImage
构建内核映像
# make modules
编译被配置为模块的内核组件
# make modules_install
把编译好的内核模块按照功能copy到/lib/modules/2.4.23目录下
编译后,可安装模块将被存放的宿主机目录是:
/tmp/lib/modules/2.4.18-rmk7-pxa1/
驱动模块所在目录 /tmp/lib/modules/2.4.18-rmk7-pxa1/kernel/driver
uboot源代码的 tools/ 目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。
mkimage在制作可启动映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头,记录 mkimage 的参数所指定的信息,这样uboot才能识别这个映象是针对哪个CPU体系结构的,哪个OS的,哪种类型,加载到内存中的哪个位置,入口点在内存中的哪个位置以及映象名是什么。
root@Glym:/tftpboot# ./mkimage
Usage: ./mkimage -l image
-l ==> list image header information
./mkimage -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-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)
参数说明:
-A 指定CPU的体系结构:
取值表示的体系结构
alphaAlpha
armARM
x86Intel x86
ia64IA64
mipsMIPS
mips64MIPS 64 Bit
ppcPowerPC
s390IBM S390
shSuperH
sparcSPARC
sparc64SPARC 64 Bit
m68kMC68000
-O 指定操作系统类型,可以取以下值:
openbsd、netbsd、freebsd、4_4bsd、linux、svr4、esix、solaris、irix、sco、
dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos
-T 指定映象类型,可以取以下值:
standalone、kernel、ramdisk、multi、firmware、script、filesystem
-C 指定映象压缩方式,可以取以下值:
none不压缩
gzip用gzip的压缩方式
bzip2用bzip2的压缩方式
-a 指定映象在内存中的加载地址,映象下载到内存中时,要按照用mkimage制作映象时,这个参数所指定的地址值来下载
-e 指定映象运行的入口点地址,这个地址就是-a参数指定的值加上0x40(因为前面有个mkimage添加的0x40个字节的头)
-n 指定映象名
-d 指定制作映象的源文件
例:制作PowerPC体系结构,vxworks操作系统的不压缩kernel映象,准备下载到内存地址0x800000位置,映象名称为vxworks.image:
root@Glym:/tftpboot# ./mkimage -A ppc -O vxworks -T kernel -C none -a 0x800000 -e 0x800040 -n vxworks.image -d vxWorks image
最后会生成一个文件名称为image的映象文件,这个文件就是我们所需要的了。请注意-n参数中指定映象名不是生成的映象文件地文件名,映象名是记录在0x40个字节的头部信息中的。
# setenv ipaddr 192.168.1.2
# setenv serverip 192.168.1.1(确保开发板和宿主机在同一网段)
# tftpboot 0x30007fc0 uImage.s3c2410-f
# tftpboot 0x30800000 ramdisk.u-boot-f
# bootm 0x30007fc0 0x30800000
如果要下载档案并且写入到NOR Flash中,方法如下:
把uImage.s3c2410-f通过tftp download到SDRAM中的0x30007fc0的位置
SMDK2410> tftpboot 0x30007fc0 uImage.s3c2410-f
将0x30007fc0位置开始长度为0x100000(即1M,这个长度取决于uImage.s3c2410-f的大小,比uImage.s3c2410-f的大小要大,在256K字节的边界上即可)的字节烧写到flash中(地址为0x200000)
SMDK2410> cp.b 0x30007fc0 0x200000 0x100000
把ramdisk.u-boot-f通过tftpdownload到SDRAM中的0x30800000 的位置
SMDK2410> tftpboot 0x30800000 ramdisk.u-boot-f
将0x30007fc0位置开始长度为0x1000000(即16M,这个长度取决于ramdisk.u-boot-f的大小,比ramdisk.u-boot-f的大小要大,在256K字节的边界上即可)的字节烧写到flash中(地址为0x800000)
SMDK2410> cp.b 0x3080000 0x800000 0x1000000
这时候,linux kernel和ramdisk已经保存到flash的0x200000和0x800000这两个位置了。
如果不需要每次起来自动启动linux,就在复位后进入u-boot命令界面,输入下面的命令即可:
SMDK2410> cp.b 0x200000 0x30007fc0 0x100000
SMDK2410> cp.b 0x800000 0x30800000 0x1000000
SMDK2410> bootm 0x30007fc0 0x30800000
如果想每次复位后自动启动linux,就把上面3条命令通过setenv命令设置到u-boot的环境变量bootcmd中。
SMDK2410>setenv bootcmd cp.b 0x200000 0x30007fc0 0x100000; cp.b 0x800000 0x30800000 0x1000000; bootm 0x30007fc0 0x30800000
SMDK2410>protect off 0x00040000 0x0007ffff
SMDK2410>saveenv
SMDK2410>protect on 0x00040000 0x0007ffff
1. 编译zlib,因为libid3tag需要这个库
# ./configure --prefix=/opt/host/armv4l/
修改Makefile
AR=/opt/host/armv4l/bin/armv4l-unknown-linux-ar
CC=/opt/host/armv4l/bin/armv4l-unknown-linux-gcc
RANLIB=/opt/host/armv4l/bin/armv4l-unknown-linux-ranlib
最后AR命令要添加rcs,否则会出错
具体操作:
libz.a : $(OBJS)$(OBJA)
$(AR) rcs$@$(OBJS)$(OBJA)
-@($(RANLIB)$@||true)>/dev/null 2>&1
# make
# make install
2. 编译libid3tag
# ./configure --host=armv4l-unknown-linux
CC=/opt/host/armv4l/bin/armv4l-unknown-linux-gcc
--disable-debugging --disable-shared
--prefix-/opt/host/armv4l/
# make
# make install
3. 编译libmad
# ./configure --enable -fpm=arm --host=armv4l-unknown-linux
--disable-shared --disable-debugging
--prefix=/opt/host/armv4l/
CC=/opt/host/armv4l/bin/armv4l-unknown-linux-gcc
# make
# make install
4. 编译madplay
# ./configure --host=armv4l-unknown-linux
CC=/opt/host/armv4l/bin/armv4l-unknown-linux-gcc
--disable-debugging
--disable-shared
CPPFLAGS='-I/opt/host/armv4l/include'
LDFLAGS='-L/opt/host/armv4l/lib'
# make
NOTE:可以在Makefile里加上 -static 选项,从而得到静态链接的程序。
另外,madplay官方主页是:www.underbit.com
zlib下载地址是:http://www.zlib.net,当前版本是zlib 1.2.3 (2005.7)
Ramdisk是分配了一部分内存作为一个分区来使用。对于系统运行时不断使用的程序,将它们放在Ramdisk中将加快计算机的操作,如大数据量的网络服务器、无盘工作站等。为了能够使用Ramdisk,我们在编译内核时须将block device中的Ramdisk支持选上,它下面还有两个选项,一个是设定Ramdisk的大小,默认是4096k;另一个是initrd的支持。它既可以直接编译进内核,也可以编译成模块,在需要的时候加载。如果在启动时就用它(例如加载ramdisk作为rootfs),就必须将它直接编译进内核。
在Linux下建立目录/myramdisk,将在此目录下创建的文件系统对应的文件结构。一般不需要对于系统运行是完全无用的文件,如帮助手册、信息页,头文件、内核源码等。
General:要建立的目录是,dev,设备;etc,系统配置文件;sbin,重要的系统程序;bin,基本应用程序;lib,共享函数库;mnt,装载其他磁盘节点;usr,附加应用程序;proc,proc文件系统;其中,proc,mnt,usr可以是空的。
一些要包含在 Ramdisk 中的重要目录是:
/bin — 保存大多数如 init、busybox、shell、文件管理实用程序等二进制文件;
/sbin — 保存系统启动过程通常需要的命令,如e2fsck、mke2fs、fdisk、insmod、rmmod、depmod、modprobe、lsmod、shutdown、reboot、login、init、getty、mount、umount、等;
/dev — 包含用在设备中的所有设备节点,一定要有的是console,kmem,mem,null,ram,tty* 等文件;
/etc — 包含必不可少的系统配置文件,一般包含rc.d/* (系统启动脚本),fstab(列出要登陆的文件系统),inittab(包含启动过程参数),passwd(用户名和目录),group(用户组),shadow(用户加密密码)。如果不使用init作为登陆进程,而将init链接到/bin/bash,即,#ln –s /bin/bash /sbin/init,则/etc目录下可以不含任何文件,这种情况类似单用户登陆系统,同样,也不需要输入用户名和密码;
/proc — 这是一个必须设置的特殊目录,在系统运行之后它下面有许多内容,这些内容是实时、不断跟踪系统内核和正在运行的进程的状态而产生的,但不占用任何磁盘空间,而是驻留在内存中;在某些情况下,可以通过它来进行系统设置,许多工具从这里获取信息,如dmesg、ps、top等;在内核编译选项文件系统选择中,我们选择对文件系统proc的支持;
/lib — 包含所有必需的库,根据/bin和/sbin目录下的可执行文件需要的动态链接库来确定lib目录下的内容,其中必须有函数装载器,或是ld.so(对a.out库)或是ld-linux.so(对ELF库)。
文件系统制作完成,看看这个/myramdisk目录大小为多大,然后确定需要多大的Ramdisk,在内核编译的时候,修改Ramdisk大小(缺省为4096k)为所需要的尺寸。
现在我们以制作一个4M的Ramdisk为例子,步骤如下:
1.在宿主机上编译运行在目标机linux内核时,将block device中的Ramdisk支持选上,设定Ramdisk的大小为缺省的4096K,对initrd的支持也选上。
2.在宿主机上建立/myramdisk目录,按照上述的原则建立必要的目录和文件。
3.执行下列步骤:
# mkdir /images
# ddif=/dev/zeroof=/images/initrd.imgbs=1kcount=4096
# mke2fs-m0-F/images/initrd.img4096
也可以是:# mke2fs-F-v-m0/images/initrd.im
若要建立ext3类型的filesystem,命令是:
# mke2fs-j-m0-F/images/initrd.img4096 ,同样,也可以不指定大小)
# mkdir –p /mnt/rootfs
# mount–oloop/images/initrd.img/mnt/rootfs
# cp-av/myramdisk/*/mnt/rootfs
(NOTE:必须用命令拷贝的方式,否则可能出错)
# umount/mnt/rootfs
# gzip-9< images/initrd.img >images/initrd.bin
# ./mkimage -n 'RAM disk' -A arm -O linux -T ramdisk -C gzip -d initrd.bin initrd.boot
也可以是:
# ./mkimage –A arm –O linux –T ramdisk –C gzip –a 0x30800000 –e 0x30800000 –n‘ramdisk’–dinitrd.bininitrd.boot
………………………………………………………………………………………………………………………………
韩海锋email:hanhf@163.comMSN:springmagus@hotmail.comQQ:34196145