搭建uClinux+arm+skyeye软硬件开发环境
songbohr@gmail.com
http://blog.csdn.net/songbohr整理版
uClinux就是Micro-Control-Linux,它也是一个开放源码的项目,uClinux的源代码和开发工具可以免费从http://www.uclinux.org上下载得到。uClinux是专为那些没有MMU(内存
管理单元)的嵌入式处理器开发的,和主流的Linux相比,uClinux有以下的特点:
1.简化了内核加载方式,uClinux
的内核可以在Flash上直接运行:就是把uClinux的内核的可执行映象烧写到flash上,系统启动时从Flash的某个地址开始逐句执行;也可以加载到内存中运行
:把内核的压缩文件存放在Flash上,系统启动时读取压缩文件在内存里解压,然后开始执行。
2.采用了romfs文件系统作为root文件系统:这种文件系统相对于一般的ext2文件系统要求更少的空间,首先内核支持romfs文件系统比支持
ext2文件系统需要更少的代码,其次romfs文件系统相对简单,建立文件系统superblock需要更少的存储空间。Romfs文件系统不支持动态擦写,对于系统需
要动态保存的数据采用RAM盘的方法处理,RAM盘采用ext2文件系统。
3.使用了Flat可执行文件格式:elf格式有很大的文件头,flat文件对文件头和一些段信息做了简化。
4.重写了应用程序库:
uClibc对libc做了精简,uClinux对用户程序采用静态连接的形式。uClinux的开发环境
www.uclinux.org为uClinux提供了GNU的交叉编译器,包括以下组件:Gcc交叉编译器,即在宿主机上开发编译目标上可运行的二进制文件;Binut
ils辅助工具,包括objdump、as、ld等;Gdb调试器。
1、如何编译安装skyeye?
编译:
./configure --target=arm-elf --prefix=/usr/local
接下来执行:
make lib
make
sudo make install
sudo make install_lib
使用make命令的时候可以加入一些选项参数,例如:
不允许DBCT
$make NO_DBCT=1
不支持LCD
$make NO_LCD=1
不支持BFD库
$make NO_BFD=1
不支持网络设备
$make NO_NET=1
为了可以在shell 里面直接运用skyeye命令,将这个路径/home/phil/skyeye-tools 加入到系统环境变量中
代码:
$gedit /etc/environment
找到有PATH那一行,加入skyeye 路径,比如下面所示
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/slickedit/bin:/home/phil/skyeye-tools"
重启系统后生效
也可
#vim .bash_profile
//编辑.bash_profile文件,找到PATH=$PATH:$HOME/bin,在其后面添加编译器的路径:/home/phil/skyeye-tools
#source .bash_profile
//重新加载.bash_profile文件
2、用apt-get安装相关的库包:
在安装SkyEye之前,一定要确认你的系统中已经安装有如下软件包:
gcc,
make,
vim(optional),
ssh,
subversion
binutils-dev (bfd)
atk-dev (libatk1.0-dev)
gtk+-2.0-dev (libgtk2.0-dev)
pkg-config
pango-dev (libpango1.0-dev)
freetype2-dev (libfreetype6-dev)
glib-dev (libglib2.0-dev)
x11-dev (libx11-dev)
建议您在终端里输:
sudo apt-get install libgtk2.0-dev pkg-config libatk1.0-devlibpango1.0-dev libfreetype6-dev libglib2.0-dev libx11-dev binutils-devlibncurses5-dev libxpm-
dev
sudo apt-get install skyeye
用apt装了skyeye 但是运行出出错
phil@ubuntu-embedded:~$ skyeye
skyeye: error while loading shared libraries:libbfd-2.19.90.20090909.so: cannot open shared object file: No such fileor directory
解决方法:
phil@ubuntu-embedded:~$ ls /usr/lib -l | grep bfd
-rw-r--r-- 1 root root 863208 2009-10-29 23:51 libbfd-2.20.so
-rw-r--r-- 1 root root 6583840 2009-10-29 23:50 libbfd.a
lrwxrwxrwx 1 root root 14 2010-05-21 13:47 libbfd.so -> libbfd-2.20.so
phil@ubuntu-embedded:~$ sudo ln /usr/lib/libbfd-2.20.so /usr/lib/libbfd-2.19.90.20090909.so -s
phil@ubuntu-embedded:~$ ls /usr/lib -l | grep bfd
lrwxrwxrwx 1 root root 23 2010-05-21 16:11 libbfd-2.19.90.20090909.so -> /usr/lib/libbfd-2.20.so
-rw-r--r-- 1 root root 863208 2009-10-29 23:51 libbfd-2.20.so
-rw-r--r-- 1 root root 6583840 2009-10-29 23:50 libbfd.a
lrwxrwxrwx 1 root root 14 2010-05-21 13:47 libbfd.so -> libbfd-2.20.so
phil@ubuntu-embedded:~$ skyeye
3.安装arm-elf交叉编译器
//wget http://www.uClinux.org/pub/uClinux/m68k-elf-tools/arm-elf-tools-20030314.sh
wget http://opensrc.sec.samsung.com/download/arm-elf-tools-20040427.sh
执行:
chmod a+x arm-elf-tools-20030314.sh
然后:
./arm-elf-tools-20030314.sh
ls /usr/local/bin/
你应能看到以arm-elf开头的可执行文件,其中arm-elf-gcc就是用来编译你目标平台的编译器的,当然还有一些小工具,后面将一一讲来。
在ubuntu安装arm-elf-tools-20040427.sh
./arm-elf-tools-20040427.sh 后出现
tail : cannot open `+43' for reading : No such file or directory
错误
解决方法:
su切换为root用户(必须切换,不然export是设在当前用户)
然后先 export _POSIX2_VERSION=199209
再运行 ./arm-elf-tools-20040427.sh
即可!
5、测试你的arm-elf-gcc编译器
先写一个小程序hello.c
PHP 代码:
#include <stdio.h>
int main(void)
{
int i;
for(i = 0; i < 6; i++){
printf("i = %d ",i);
printf("Hello, embedded linux!\n");
}
return 0;
}
然后执行:
arm-elf-gcc -Wl,-elf2flt -o hello hello.c
-elf2flt参数是将elf文件格式转为flat文件格式,这个工具是在你安装交叉编译器产生的。
或者你可以写个Makefile文件,执行:
make
这里是我的Makefile文件,仅供参考:
PHP 代码:
# begin
CC = arm-elf-gcc
CFLAGS = -D__PIC__ -fpic -msingle-pic-base -O2 -pipe -Wall -g
LDFLAGS = -Wl,-elf2flt
LIBS =
OBJS = hello.o
all: hello
hello: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o hello $(OBJS) $(LIBS)
clean:
rm -rf *.o *.elf *.gdb hello
# end
如果编译通过,就会产生hello可执行文件。用下面的命令:
file hello
你会发现,它是BFLT(binary FLAT),你目标平台所支持的文件格式。
6、执行你的hello程序
这里,我们将借助genromfs这个小工具来完成测试,这个工具就是你在安装交叉编译器时产生的,你可以直接使用它。
下skyeye-testsuite-1.3.0_rc1.tar.bz2包:
tar jxvf skyeye-testsuite-1.3.0_rc1.tar.bz2
cd skyeye-testsuite-1.3.0_rc1/uClinux/at91/uclinux_cs8900a#
mkdir romfs.img(建一个目录,后面用)
mount -o loop romfs.img /mnt/xxx
cp -r /mnt/xxx/* romfs
另外,把你编译好的可执行程序拷贝到./romfs/bin目录里,这里就是hello了!
genromfs -f romfs.img -d romfs/
注:可以用genromfs -h来获得帮助!
OK!执行下面的命令:
skyeye -e linux
cd /bin
hello
可以看到结果了吗?
其实到了这一步,你就可以开发自己的程序了!
7.编译我们的uClinux内核
wget http://www.uClinux.org/pub/uClinux/dist/uClinux-dist-20040408.tar.gz
首先解压
代码:
tar -zxvf uClinux-dist-20040408.tar.gz //tar zxvf uClinux-dist-20090618.tar.gz这里不能用2009版,我编译时出现各种编译问题,只好换回04版
这是在你解压的目录里面会生成一个 uClinux-dist目录
shell 中进 uClinux-dist目录,执行make menuconfig进行配置:
代码:
phil@ubuntu-embedded:~/skyeye-tools/uClinux-dist$ make menuconfig
然后再进行配置:在下面这个选项里面选择GDB ARMulator
代码:
--- Select the Vendor you wish to target
(GDB) Vendor
--- Select the Product you wish to target
(ARMulator) GDB Products
Kernel选择2.4内核,Libc Version选择uClibc //不能选择2.6内核,编译器版本太低,不支持
代码:
(linux-2.4.x) Kernel Version
(uClibc) Libc Version
[ ] Default all settings (lose changes)
[ ] Customize Kernel Settings
[ ] Customize Vendor/User Settings
[ ] Update Default Vendor Settings
退出它会提示:
代码:
Do you wish to save your new kernel configuration?
< Yes > < No >
选择Yes
编译:
make clean
make dep
make
编译uClinux时提示arm-linux-gcc:command not found
解决方法:
uClinux是针对无MMU设备的Linux因此编译时要用arm-elf-gcc交叉编译器
先安装上arm-elf-tools交叉编译工具包
然后修改uClinux的配置文件使用arm-elf-XXX工具编译
vi uClinux-dist/vendors/config/armnommu/config.arch
找到以下代码段:
CROSS_COMPILE=arm-linux-
修改为
CROSS_COMPILE=arm-elf-
:wq
保存退出
重新编译应该没有问题
这个编译过程比较长,耐心等待。
编译成功后会在uClinux-dist目录里面生成一个images目录,这个目录里面有四个文件:
image.bin:这是包含内核映像和 romfs文件系统映像,可以写到Flash中的文件,
linux.data:包括内核所有的数据段
linux.text:包括内核所有的代码段
romfs.img:文件系统
另外在uClinux-dist/linux-2.4.x目录里面生成了两个文件:linux和system.map
linux:linux内核文件
system.map:内核符号表
然后在uClinux-dist目录里面建一个skyeye.conf文件,并键入以下配置文件
代码:
#skyeye config file sample
cpu: arm7tdmi
mach: at91
mem_bank: map=M, type=RW, addr=0x00000000, size=0x00004000
mem_bank: map=M, type=RW, addr=0x01000000, size=0x00400000
mem_bank: map=M, type=R, addr=0x01400000, size=0x00400000, file=./boot.rom
mem_bank: map=M, type=RW, addr=0x02000000, size=0x00400000
mem_bank: map=M, type=RW, addr=0x02400000, size=0x00008000
mem_bank: map=M, type=RW, addr=0x04000000, size=0x00400000
mem_bank: map=I, type=RW, addr=0xf0000000, size=0x10000000
注意这个配置文件中需要boot.rom 文件系统,但是我们并没有生成boot.rom文件系统,怎么办?
ln -s images/romfs.img boot.rom
代码:
wenwu@wenwu-desktop:/source/uClinux-dist$ ln -s images/romfs.img boot.rom
这是就可以在uClinux-dist 目录里面看到boot.rom这个文件
下面就可以用skyeye运行我们自己编译出来的内核了。
代码:
wenwu@wenwu-desktop:/source/uClinux-dist$ skyeye -e linux-2.4.x/linux
target sim
...
load
...
run
8.模拟运行自己的应用程序
找到前面曾编译的程序Hello.c,将编译生成的BFLT格式的Hello移动到/uClinux-dist/romfs/bin中(注意在shell中用root)
然后重新编译内核
#make
运行
#skyeye -e linux-2.4.x/linux
```
```
```
(省略)
Sash command shell(version 1.1.1)
/>cd bin
/bin>./Hello
Hello!This is Embedded Linux!
附录:skyeye.conf中的选项
SkyEye模拟的硬件配置和模拟执行行为由配置文件skyeye.conf中的选项确定。根据选项的功能,skyeye.conf的选项分为硬件配置选项和模拟执行选项。根据参数的个数,
skyeye.conf的选项主要由两种组成:
单参数选项行
格式为:
symbol: value
symbol可以是硬件定义,如cpu、mach等,也可以是执行控制定义,如log等。
value是symbol对应的值,可能是数字也可能是字符串。
多参数选项行
格式为:
symbol:opt1=value1,opt2=value2,......
opt1是参数名,value1是opt1对应的值,可能是数字也可能是字符串。
目前skyeye.conf的配置定义如下:
基本CPU核配置选项
目前存在的选项有:arm710、arm7tdmi、arm720t、arm920t、sa1100、sa1110、xscale
格式为
cpu: cpuname
注:cpuname表示一个代表cpu名字的字符串。
例如:
cpu: arm7tdmi
具体的开发板(包括CPU扩展)配置选项
目前存在的选项有:at91、ep7312、adsbitsy,pxa_Lubbock、lpc、s3c4510b、s3c44b0、cs89712、sa1100、at91rm92、sharp_lh7a400
格式为:
mach: machinename
注:cpuname表示一个代表基于特定CPU的开发板名字的字符串。
例如:
mach: at91
内存组配置选项
一个内存组内的地址是连续的,类型分为RAM SPACE, ROM SPACE, mapped IO SPACE
格式为:
mem_bank: map=M|I, type=RW|R, addr=0xXXXXXXXX, size=0xXXXXXXXX,file=imagefilename,boot=yes|no
map=M 表示 RAM/ROM SPACE, map=I 表示 mapped IO SPACE。
type=RW ,且如果map=M则表示RAM SPACE, type=R,且如果map=M则表示ROM SPACE。
addr=0xXXXXXX 表示内存组的起始物理地址(32bit,16进制)。
size =0xXXXXXX 表示内存组的大小(32bit,16进制) 。
file =imagefilename
file的值imagefilename是一个字符串,实际上表示了一个文件,一般是一个可以执行的binary image格式的可执行程序或OS内核文件或是一个binary image格式的根文件系统。如
果存在这个文件,SkyEye会把文件的内容直接写到对应的模拟内存组地址空间中。
boot=yes/no,如果boot=yes,则SkyEye会把模拟硬件启动后的第一条指令的地址定位到对应的内存组的起始地址。
例如:
mem_bank: map=M, type=RW, addr=0x00000000, size=0x00004000
mem_bank: map=M, type=R, addr=0x01400000, size=0x00400000, file=./boot.rom
mem_bank: map=M, type=RW, addr=0x10000000, size=0x00000800, file=./loader.bin,boot=yes
网络芯片8019AS的配置
格式为 nic: state=on/off mac=xx:xx:xx:xx:xx:xx ethmod=tuntap/vnet hostip=dd.dd.dd.dd
注:xx表示两位16进制数,dd表示两位10进制数
state表示模拟开始后,网络芯片是否开始工作
mac表示模拟的nic的mac地址
ethmod表示skyeye所处主机上的网络模拟方式, 目前有tuptap和vnet两种模式。tuntap是linux kernel支持的一个点到点虚拟网络实现,vnet是skyeye实现的一个功能更多的一个
基于虚拟HUB的网络。
hostip表示主机方与skyeye交互用的ip地址
例如:
net: state=on, mac=0:4:3:2:1:f, ethmod=tuntap, hostip=10.0.0.1
LCD的配置
格式为 lcd: state=on/off
state=on表示LCD处于接通状态; state=off 表示LCD处于关闭状态。
例如:
lcd: state=on
skyeye的UART控制选项
uart选项可以控制skyeye在另一个与某个串口连接的终端上输入/输出字符
格式:
uart: fd_in=indevname, fd_out=outdevname
fd_in=indevname indevname表示用于输入的设备文件名,其值为实际的串口设备文件/dev/ttySx
fd_out=outdevname outdevname表示用于输出的设备文件名,其值为实际的串口设备文件/dev/ttySx
例如:
uart: fd_in=/dev/ttyS0, fd_out=/dev/ttyS0
skyeye的log控制选项
log选项用于控制skyeye输出硬件系统的执行状态信息,包括每次执行指令时的执行指令值、寄存器值、各种硬件状态等。
格式:
log: logon=0|1, logfile=filename, start=number1, end=number2, length=number3
logon=0|1|2|3,如果值等于0表示不进行记录,如果值等于1表示记录指令和指令地址流,如果值等于2表示记录指令和指令地址和主要寄存器内容,如果值等于3表示记录指令和指
令地址和所有的寄存器内容。
logfile=filename 其值是一个字符串,表示用于记录信息的文件名
start=number1 其值是一个>=0的十进制整数,表示系统执行到第number1条指令时开始进行记录
end =number2其值是一个>=0的十进制整数,表示系统执行到第number2条指令时停止记录
length =number3其值是一个>=0的十进制整数,表示只记录系统最近执行的number3条指令时的信息
格式:
log: logon=0, logfile=/tmp/sk1.log, start=100000, end=200000, length=100
参考文献:
自己动手打造嵌入式Linux软硬件开发环境 http://linux.chinaunix.net/doc/embedded/2005-01-13/764.shtml
在ubuntu7.10上搭建uClinux编译开发环境并用Skyeye进行仿真http://forum.ubuntu.com.cn/viewtopic.php?t=88369&sid=9948fa118f9d824457625463193d77e2
uClinux+Skyeye open source simulator http://sourceforge.net/apps/trac/skyeye/wiki/uClinux
Getting Familiar with uClinux/ARM 2.6 http://opensrc.sec.samsung.com/Getting_Familiar_with_uClinuxARM2_6.html
联系客服