本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接。内容可任意使用,但对因使用该内容引起的后果不做任何保证。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net
这里使用的单板是通过Qemu模拟的一块smdkc210单板,CPU类型为Samsung的Exynos4(cortex-A9的核)。开发环境是Ubuntu 12.04。
2.1Memory map
u-boot用于加载linux系统,因此需要提前规划好内存布局。下图中是目标smdkc210的的内存布局(可以在Qemu上使用info mtree命令查看)。内存占据了4G到8G这段空间。ARM系统默认的启动地址为0。smdkc210的这个位置上有一块ROM,通过x命令可以发现它会跳转到地址0x40010000,而u-boot.bin也会被加载到这个位置。通过info roms命令,可以查看Qemu加载ROM的位置。从这时起,内存如何使用就取决于我们如何设置u-boot了。
此时u-boot已经被放到RAM中了,但这只是Qemu为了执行后续操作。在真是的单板中,u-boot通常会被放到ROM中,而不是内存中。因此u-boot启动后会尽快把自己拷贝到RAM中(一般是RAM的最后)。这里我们也保留这一拷贝操作。同时为uImage与uRamDisk设定加载位置。加载位置选择的原则是不要与u-boot互相覆盖。
图1:内存布局
2.2设置Qemu虚拟机
a)$ apt-get install
qemu.
该命令用于在ubuntu上安装Qemu。也可以下载Qemu源码,自己编译。
b)$ qemu-system-ARM
-M ?
查看Qemu支持的单板类型:
Supported
machines are:
noneempty machine
smdkc210Samsung
SMDKC210 board (Exynos4210)
realview-pbx-a9ARM
RealView Platform Baseboard Explore for Cortex-A9
可以看到Qemu支持smdkc210单板。
2.3注册板类型
a)设置编译器.
由于是交叉编译,需要设置要使用的编译器。编译器由变量CROSS_COMPILE指定,同时通过变量BUILD_DIR设置临时文件与目标文件的保存路径。默认的保存路径是与源文件根目录,这样会与源文件混在一起,不利于管理。
这两个变量可以通过make命令传入,但每次都要输入它们。更好的方式是直接把它们在Makefile中设置好:
export CROSS_COMPILE=arm-qhao-Linux-gnueabi-
export BUILD_DIR=../obj/u-boot/tmp$(ARCH)
$(shell mkdir -p $(BUILD_DIR))
b)注册板类型
u-boot支持的板类型保存在boards.cfg中。其格式如下:
# Status, Arch, CPU:SPLCPU, SoC, Vendor, Board
name, Target, Options, Maintainers
ActiveARMARMv7exynossamsungsmdkc210smdkc210-Marco Hao
Target名是该单板的唯一标示,不能重复。注册板类型命令如下:
$
make smdkc210_config
如果boards.cfg中找不到对应的单板,则需要自己增加新的板类型。
如果注册成功,则显示如下信息:
Configuring
for smdkc210 board...
板信息会被存储到“obj/u-boot/tmpARM/include/config.mk”中:
ARCH= ARM
CPU= ARMv7
BOARD=
smdkc210
VENDOR = samsung
SOC=
exynos
2.4编译u-boot
$ make
如果u-boot已经支持该单板,执行这个命令就可以完成编译,生成u-boot与u-boot.bin。但如果不支持,则需要一些额外操作。
如果要加入新的单板类型,千万不要试着从头写。选择一个类似的单板类型,照着它进行改造。这里选择smdkv310,因为它与smdkc210都是三星的开发板,同样都是使用exynos4。相信他们的结构会非常类似。
对于新的板类型smdkc210,需要增加下面的几个文件:
1)include/configs/smdkc210.h
单板的配置文件,记录了单板的硬件信息。(拷贝自smdkv310.h).
2)board/samsung/smdkc210/smdkc210.c’
单板的一些独有的配置函数。(拷贝自smdkv310.c).
有时,新单板与参考单板的某些期间不一样,所以需要的驱动也不一样。比如,smkdc210与smkdv310使用的串口设备不一样,所以需要改变串口驱动类型。
所有的串口驱动都在“drivers/serial”目录中。通过查看smdkv310.h得知smdkv310设置了宏CONFIG_S5P。打开“drivers/serial/Makefile”,信息如下:
COBJS-$(CONFIG_S5P)
+=serial_s5p.o
COBJS-$(CONFIG_SYS_NS16550_SERIAL) +=
serial_ns16550.o
COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o
COBJS-$(CONFIG_IXP_SERIAL) += serial_ixp.o
COBJS-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o
因此我们知道smdkv210选择的串口驱动是serial_s5p.c。假设smdkc210使用的是serial_ns16550.c,则需要在smdkc210.h中把CONFIG_S5P替换成CONFIG_SYS_NS16550_SERIAL。
2.5在Qemu上加载u-boot
如下命令用于启动Qemu,指定的单板类型为smdkc210,加载的image为u-boot.bin:
$ my_tap=$(sudo /usr/sbin/tunctl -b)
$ sudo ifconfig $my_tap 192.168.2.100 netmask
255.255.255.0
$ sudo qemu-system-ARM -machine smdkc210 -m 1024m
-kernel u-boot.bin \
-monitor
stdio -serial vc-net nic,vlan=0 -net
tap,vlan=0,ifname=$my_tap,script=no
$ sudo /usr/sbin/tunctl -d $my_tap
2.6设置tftp服务器
u-boot启动后,通常会通过tftp的方式加载linux影响与文件系统,下面的命令用于在Ubuntu上安装与启动tftp
a)安装tftp
sudo
apt-get install xinetd tftpd tftp
b)创建并加入下面的信息,sserver_args指定了tftp的根路径。
service tftp
{
protocol= udp
port= 69
socket_type= dgram
wait= yes
user= nobody
server= /usr/sbin/in.tftpd
server_args= /tftpboot
disable= no
}
a)设置根路径
从上面的配置中可以看到根路径的user是nobody,所以需要把根路径的所有者改成nobody,并且好设置根路径的读写权限:
$ sudo mkdir /tftpboot
$ sudo chmod -R 777 /tftpboot
$ sudo chown -R nobody /tftpboot
b)Restart the
xinetd service.
$ sudo
/etc/init.d/xinetd restart
c)Additional
command of tftp:
$ sudo
/etc/init.d/xinetd start
$
sudo /etc/init.d/xinetd stop
2.7下载Linux kernel与uRamDisk
加载命令如下
$ Tftp 0x7c000000 uImage
$ Tftp 0x7d000000 uRamDisk
$ Bootm 0x7d000000 0x7c000000
u-boot要加载linux kernel,需要配置网卡、设置启动参数、下载与启动kernel等多个步骤,可以在启动u-boot后通过控制台命令进行设置,也可以在配置文件中写死,好处是启动后可以自动完成上述步骤。单板配置文件在include/configs目录下,与单板同名,我们这里的板子配置文件是smdkc210.h。
#define CONIFG_ETHADDR 00:e0:0c:bc:e5:61
#define CONFIG_IPADDR 192.168.2.102
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 192.168.2.100
#define CONFIG_GATEWAYIP 192.168.2.100
#define CONFIG_RAMBOOT_COMMAND \
"setenv
bootargs root=/dev/ram rw init=/linuxrc console=ttyAMA0;" \
"tftp
7f000000 uRamDisk;" \
"tftp
7e000000 uImage;" \
"bootm
7e000000 7f000000"
#define CONFIG_EXTRA_ENV_SETTINGS \
"bootargs=root=/dev/ram
rw init=/linuxrc console=ttyAMA0\0" \
"netdev=eth0\0"
\
"consoledev=ttyAMA0\0"
\
"loadaddr=7e000000\0"
\
"bootfile=uImage\0"
\
"ramdiskaddr=7f000000\0"
\
"ramdiskfile=uRamDisk\0"
\
""
#define CONFIG_BOOTCOMMAND CONFIG_RAMBOOT_COMMAND
本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接。内容可任意使用,但对因使用该内容引起的后果不做任何保证。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net