第二章 首次安装SDK
1、Hi3531 SDK包位置如果您需要通过WINDOWS操作系统中转拷贝SDK包,请先运行./sdk.cleanup,收起SDK包的内容,拷贝到新的目录后再展开。
遇到以下问题:
a@ubuntu:~/product$ tar -zxf Hi3531_SDK_V1.0.8.0.tgz
a@ubuntu:~/product$ ls
a8_orig c300.tar.bz2 Hi3531_SDK_V1.0.8.0 netconfig~
a8_orig.tar.bz2 c318 Hi3531_SDK_V1.0.8.0.tgz pingloop~
app_init gis mysql_hotbackup pings
app_init~ gislinux.tar mysql-setup.sh pings~
app_init2 gis.tar.gz netcfg record
c300 gis_udblip netconfig record.tar.bz2
a@ubuntu:~/product$ cd Hi3531_SDK_V1.0.8.0
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0$ ls
package scripts sdk.cleanup sdk.unpack
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0$ sudo ./sdk.unpack
[sudo] password for a:
./sdk.unpack: 2: ./sdk.unpack: source: not found
./sdk.unpack: 4: ./sdk.unpack: ECHO: not found
./sdk.unpack: 6: ./sdk.unpack: WARN: not found
./sdk.unpack: 7: ./sdk.unpack: WARN: not found
./sdk.unpack: 8: ./sdk.unpack: ECHO: not found
./sdk.unpack: 20: ./sdk.unpack: ECHO: not found
./sdk.unpack: 22: ./sdk.unpack: run_command_progress_float: not found
./sdk.unpack: 24: ./sdk.unpack: ECHO: not found
mkdir: created directory ‘mpp’
./sdk.unpack: 26: ./sdk.unpack: run_command_progress_float: not found
./sdk.unpack: 28: ./sdk.unpack: ECHO: not found
mkdir: created directory ‘drv’
./sdk.unpack: 30: ./sdk.unpack: run_command_progress_float: not found
解决方案
1)Ubuntu下修改默认Shell:dash为bash
输入 dpkg-reconfigure dash 后选 no 选项
2)解压SDK到当前目录后 进入目录如: ./Hi3515_V100R001C01SPC050/software/board
解压 tar zxvf Hi3515_SDK_V1.0.5.0.c1.tgz
进入目录,找到 scripts/common.sh
vi scripts/common.sh
找到 run_command_progress_float() 函数
将其中的:
prog_bar_base="[ ]"
while [ $rcp_tmp -lt $RCP_RANGE ]
do
prog_bar_base="$prog_bar_base-"
((rcp_tmp++))
done
替换为
prog_bar_base="[ ]"
while [ $rcp_tmp -lt $RCP_RANGE ]
do
prog_bar_base="$prog_bar_base-"
((rcp_tmp=rcp_tmp+1))
done
主要就是将第159行的((rcp_tmp++))替换为((rcp_tmp=rcp_tmp+1))
保存退出
3)如果用一般用户编译,需在用户的主目录的./baserc文件中最后增加编译器路径:
vi ~/.bashrc
文件末尾位置加入:
export PATH="$PATH:/opt/hisi-linux/x86-arm/gcc-3.4.3-uClibc-0.9.28/usr/bin/:/opt/hisi-linux/x86-arm/gcc-3.4.3-uClibc-0.9.28/bin/"
保存退出
然后:
sudo vi /root/.bashrc
仍在文件末尾位置加入:
export PATH="$PATH:/opt/hisi-linux/x86-arm/gcc-3.4.3-uClibc-0.9.28/usr/bin/:/opt/hisi-linux/x86-arm/gcc-3.4.3-uClibc-0.9.28/bin/"
保存退出
如用root编译可不做上述工作
4)普通用户编译执行
sudo ./sdk.unpack
SDK编译成功!
修改后输出结果
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0$ sudo ./sdk.unpack
Unpacking SDK
WARN: Be sure you have installed the cross-compiler. if not, install it first!
WARN: ALL THE SOUCE FILES WILL BE OVERWRITED, FILES YOU MOTIFIED WILL BE LOST !!!
unpacking osdrv
run_command_progress_float: 'tar -xvzf package/osdrv.tgz'
[100%]##################################################|
unpacking mpp
run_command_progress_float: 'tar -xvzf package/mpp.tgz'
[100%]##################################################|
unpacking drv
run_command_progress_float: 'tar -xvzf package/drv.tgz'
[100%]##################################################|
进入Hi3531_SDK_Vx.x.x.x/osdrv/toolchain/arm-hisiv200-linux目录,运行chmod +x cross.install,然后运行./cross.install即可。
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/toolchain/arm-hisiv200-linux$ sudo chmod +x cross.install
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/toolchain/arm-hisiv200-linux$ sudo ./cross.install
CROSS_COMPILER_PATH=/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin
Do not have version file
mkdir: created directory ‘/opt/hisi-linux’
mkdir: created directory ‘/opt/hisi-linux/x86-arm’
mkdir: created directory ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux’
Extract cross tools ...
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-addr2line’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-addr2line’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-ar’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-ar’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-as’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-as’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-c++’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-c++’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-c++filt’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-c++filt’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-cpp’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-cpp’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-g++’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-g++’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-gcc’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-gcc’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-gcc-4.4.1’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-gcc-4.4.1’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-gccbug’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-gccbug’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-gcov’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-gcov’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-gdb’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-gdb’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-gdbtui’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-gdbtui’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-gprof’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-gprof’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-ld’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-ld’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-nm’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-nm’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-objcopy’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-objcopy’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-objdump’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-objdump’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-ranlib’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-ranlib’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-readelf’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-readelf’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-size’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-size’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-strings’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-strings’
‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin/arm-hisiv200-linux-strip’ -> ‘/opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/arm-hisiv200-linux-gnueabi-strip’
export path /opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/toolchain/arm-hisiv200-linux$ source /etc/profile
export PATH="$PATH:/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/usr/bin/:/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin"
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/kernel/linux-3.0.y$ sudo make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux- uImage
make: arm-hisiv200-linux-gcc: Command not found
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
CC kernel/bounds.s
/bin/sh: arm-hisiv200-linux-gcc: command not found
make[1]: *** [kernel/bounds.s] Error 127
make: *** [prepare0] Error 2
a@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/kernel/linux-3.0.y$ arm-hisiv200-linux-gcc
arm-hisiv200-linux-gcc: no input files
make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux- godnet_config
make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux-
UNDEF_SYM=`arm-hisiv200-linux-objdump -x board/godnet/libgodnet.a lib/libgeneric.a lib/lzma/liblzma.a lib/lzo/liblzo.a arch/arm/cpu/godnet/libgodnet.a
arch/arm/cpu/godnet/godnet/libgodnet.a arch/arm/lib/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a
fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a fs/ubifs/libubifs.a net/libnet.a disk/libdisk.a drivers/bios_emulator/libatibiosemu.a
drivers/block/libblock.a drivers/dma/libdma.a drivers/fpga/libfpga.a drivers/gpio/libgpio.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a
drivers/input/libinput.a drivers/misc/libmisc.a drivers/mmc/libmmc.a drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/onenand/libonenand.a
drivers/mtd/ubi/libubi.a drivers/mtd/spi/libspi_flash.a drivers/mtd/spi/hisfc350/libhisfcv350.a drivers/mtd/spi/hisfc300new/libhisfcv300new.a
drivers/net/libnet.a drivers/net/phy/libphy.a drivers/net/hisfv300/libhisfv300.a drivers/net/higmac/libhigmac.a drivers/net/stmmac/libstmmac.a
drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/power/libpower.a drivers/spi/libspi.a drivers/vo/libvo.a drivers/hdmi/libhdmi.a
drivers/dec/libjpegd.a drivers/rtc/librtc.a drivers/serial/libserial.a drivers/twserial/libtws.a drivers/usb/gadget/libusb_gadget.a
drivers/usb/host/libusb_host.a drivers/usb/host/hiusb/libhiusb.a drivers/usb/musb/libusb_musb.a drivers/usb/phy/libusb_phy.a
drivers/video/libvideo.a drivers/watchdog/libwatchdog.a common/libcommon.a lib/libfdt/libfdt.a api/libapi.a post/libpost.a product/libproduct.a
product/hiupdate/libhiupdate.a | sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;
cd /home/a/product/Hi3531_SDK_V1.0.8.0/osdrv/uboot/u-boot-2010.06 && arm-hisiv200-linux-ld -Bstatic -T u-boot.lds
-Ttext 0x80800000 $UNDEF_SYM arch/arm/cpu/godnet/start.o --start-group lib/libgeneric.a lib/lzma/liblzma.a lib/lzo/liblzo.a
arch/arm/cpu/godnet/libgodnet.a arch/arm/cpu/godnet/godnet/libgodnet.a arch/arm/lib/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a
fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a fs/ubifs/libubifs.a net/libnet.a disk/libdisk.a
drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/dma/libdma.a drivers/fpga/libfpga.a drivers/gpio/libgpio.a
drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a drivers/mmc/libmmc.a drivers/mtd/libmtd.a
drivers/mtd/nand/libnand.a drivers/mtd/onenand/libonenand.a drivers/mtd/ubi/libubi.a drivers/mtd/spi/libspi_flash.a
drivers/mtd/spi/hisfc350/libhisfcv350.a drivers/mtd/spi/hisfc300new/libhisfcv300new.a drivers/net/libnet.a drivers/net/phy/libphy.a
drivers/net/hisfv300/libhisfv300.a drivers/net/higmac/libhigmac.a drivers/net/stmmac/libstmmac.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a
drivers/power/libpower.a drivers/spi/libspi.a drivers/vo/libvo.a drivers/hdmi/libhdmi.a drivers/dec/libjpegd.a drivers/rtc/librtc.a
drivers/serial/libserial.a drivers/twserial/libtws.a drivers/usb/gadget/libusb_gadget.a drivers/usb/host/libusb_host.a drivers/usb/host/hiusb/libhiusb.a
drivers/usb/musb/libusb_musb.a drivers/usb/phy/libusb_phy.a drivers/video/libvideo.a drivers/watchdog/libwatchdog.a common/libcommon.a
lib/libfdt/libfdt.a api/libapi.a post/libpost.a product/libproduct.a product/hiupdate/libhiupdate.a board/godnet/libgodnet.a --end-group
/home/a/product/Hi3531_SDK_V1.0.8.0/osdrv/uboot/u-boot-2010.06/arch/arm/lib/eabi_compat.o
-L /opt/hisi-linux/x86-arm/arm-hisiv200-linux/bin/../lib/gcc/arm-hisiv200-linux-gnueabi/4.4.1 -lgcc -Map u-boot.map -o u-boot
arm-hisiv200-linux-objcopy -O srec u-boot u-boot.srec
arm-hisiv200-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
export PATH="$PATH:/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/usr/bin/:/opt/hisi-linux/x86-arm/arm-hisiv200-linux/target/bin:/home/a/product/Hi3531_SDK_V1.0.8.0/osdrv/uboot/u-boot-2010.06/tools"
Kernel: arch/arm/boot/zImage is ready
UIMAGE arch/arm/boot/uImage
Image Name: Linux-3.0.8
Created: Mon May 23 02:31:49 2016
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3496792 Bytes = 3414.84 kB = 3.33 MB
Load Address: 80008000
Entry Point: 80008000
Image arch/arm/boot/uImage is ready
a. 修改一下源码
sun@:/work/busybox/busybox-1.20.2$ vi include/libbb.h
添加一行 #include
要不会出现如下错误:
loginutils/passwd.c: In function ‘passwd_main’:
loginutils/passwd.c:104:16: error: storage size of ‘rlimit_fsize’ isn’t known
loginutils/passwd.c:188:12: error: ‘RLIMIT_FSIZE’ undeclared (first use in this function)
loginutils/passwd.c:188:12: note: each undeclared identifier is reported> each function it appears in
loginutils/passwd.c:104:16: warning: unused variable ‘rlimit_fsize’ [-Wunused-variable]
配置busybox
sun@ubuntu:/work/busybox/busybox-1.20.2$ make menuconfig
Busybox Setting -> Build Options
[*]Build BusyBox as a static binary(no shared libs) //一定要选上这个,这样busybox才不依赖于其它的东东,独立运行的
Build Options --->
(/work/busybox/arm-2012.09/bin/arm-none-linux-gnueabi-) Cross Compiler prefix //配置工具链
c. make //只make,不用 make install
这会在当前目录下生成 busybox
AR util-linux/volume_id/lib.a
LINK busybox_unstripped
Trying libraries: crypt m
Library crypt is not needed, excluding it
Library m is needed, can't exclude it (yet)
Final link with: m
DOC busybox.pod
DOC BusyBox.txt
DOC BusyBox.1
DOC BusyBox.html
d make install
./_install/usr/sbin/setlogcons -> ../../bin/busybox
./_install/usr/sbin/svlogd -> ../../bin/busybox
./_install/usr/sbin/telnetd -> ../../bin/busybox
./_install/usr/sbin/udhcpd -> ../../bin/busybox
--------------------------------------------------
You will probably need to make your busybox binary
setuid root to ensure all configured applets will
work properly.
--------------------------------------------------
===========================================================================
启动时用到initrd来mount根文件系统。注意理解ramdisk和initrd这两个概念,其实ramdisk只是在ram上实现的块设备,类似与硬盘操作,但有更快的读写速度,它可以在
系统运行的任何时候使用,而不仅仅是用于启动;initrd(boot loader initialized RAM disk)可以说是启动过程中用到的一种机制,具体的实现过程也使用ramdisk技术。
就是在装载linux之前,bootloader可以把一个比较小的根文件系统的映象装载在内存的某个指定位置,姑且把这段内存称为initrd(这里是initrd所占的内存,不是ramdisk,
注意区别),然后bootloader通过传递参数的方式告诉内核initrd的起始地址和大小(也可以把这些参数编译在内核中),在启动阶段就可以暂时的用initrd来mount根文件
系统。initrd的最初的目的是为了把kernel的启动分成两个阶段:在kernel中保留最少最基本的启动代码,然后把对各种各样硬件设备的支持以模块的方式放在initrd中,
这样就在启动过程中可以从initrd所mount的根文件系统中装载需要的模块。这样的一个好处就是在保持kernel不变的情况下,通过修改initrd中的内容就可以灵活的支持
不同的硬件。在启动完成的最后阶段,根文件系统可以重新mount到其他设备上,但是也可以不再 重新mount(很多嵌入式系统就是这样)。 initrd的具体实现过程是这样的:
bootloader把根文件系统映象装载到内存指定位置,把相关参数传递给内核,内核启动时把initrd中的内容复制到ramdisk中(ram0),把initrd占用的内存释放掉,
在ram0上mount根文件系统。从这个过程可以看出,内核需要对同时对ramdisk和initrd的支持(这种需要都编入内核,不能作为模块)。
这四种给rootfs提供内容的方式都有一个共同点:在kernel启动时,一系列的文件被解压到rootfs,如果kernel能在其中找到可执行的文件“/init”,kernel就会运行它;
这意味着,kernel不会再去理会“root=”是指向哪里的。此外,一旦initramfs里面的init 进程运行起来,kernel就会认为启动已经完成
使用initramfs最简单的方式,莫过于用已经做好的cpio.gz把kernel里面那个空的给换掉。这是2.6 kernel天生支持的,所以,你不用做什么特殊的设置。
kernel的config option里面有一项CONFIG_INITRAMFS_SOURCE(I.E. General setup--->Initramfs source file(s) in menuconfig)。
这个选项指向放着内核打包initramfs需要的所有文件。默认情况下,这个选项是留空的,所以内核编译出来之后initramfs也就是空的,
也就是前面提到的rootfs什么都不做的情形。
CONFIG_INITRAMFS_SOURCE 可以是一个绝对路径,也可以是一个从kernel’s top build dir
(你敲入build或者是make的地方)开始的相对路径。而指向的目标可以有以下三种:一个已经做好的cpio.gz,或者一个已经为制作cpio.gz准备好所有内容的文件夹,
或者是一个text的配置文件。
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/kernel/linux-3.0.y# cat .config |grep CONFIG_INITRAMFS_SOURCE
CONFIG_INITRAMFS_SOURCE=""
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/kernel/linux-3.0.y# cat .config |grep CONFIG_INITRAMFS_SOURCE
CONFIG_INITRAMFS_SOURCE="/home/a/product/Hi3531_SDK_V1.0.8.0/rootfs"
BusyBox的配置程序和Linux内核菜单配置方式简直一模一样,十分方便易用。使用make menuconfig命令就可以进行配置
因为我们要将BusyBox交叉编译成ARM可执行程序放在开发板上执行,所以需要使用交叉编译器arm-linux-gcc
来编译BusyBox。所以需要修改BusyBox根目录下的Makefile,找到
ARCH ?= $(SUBARCH)
CROSS-COMPILE ?=
修改成ARM的配置,如下:
ARM ?= arm
CROSS-COMPILE ?= arm-linux-
Busybox Settings --->
Build Options
Build BusyBox as a static binary (no shared libs)
这个选项是一定要选择的,这样才能把BusyBox编译成静态链接的可执行文件,运行时才独立于其他函数库,
否则必须要其他库文件才能运行
Busybox Settings --->
Installation Options
Don’t use /usr
这个选项也是要选上的,否则make install 后BusyBox将安装在原系统的/usr下,这将覆盖系统原有的命令。
选择这个选项后,make install后会在BusyBox目录下生成一个叫_install的目录,里面有BusyBox和指向他
的链接。
Init Utilities --->
init
这个选项最好选上,这样BusyBox就可以初始化脚本inittab,可以用来初始化Linux系统。
Shells --->
这里可选的shell有多种,包括ash,hush,lash,msh。最好使用ash,因为它是功能最全也最类似于一般
Linux系统中的BASH的。同时注意第一行的:
Choose your default shell (none) --->
这里需要回车进去选择默认的Shell,例如选择了ash后,第一行的内容就会变成:
Choose your default shell (ash) --->
这样BusyBox才会生成sh的链接并且将这个sh指向对应的shell(ash)。
其他选项都是一些Linux基本命令选项,可以根据自己的需要选择配置,第一次的话用默认的设置即可
如果配置好了BusyBox,就可以使用make命令编译了。
#make
#make install
默认情况下,make install完成后会在BusyBox目录下创建一个新的本地子目录 _install,其中包含了基本的 Linux 环境。在这个目录中,会有一个链接到 BusyBox 的 linuxrc 程序。这个 linuxrc 程序在构建安装盘或急救盘(允许提前进行模块化的引导)时非常有用。同样在这个目录中,还有一个包含操作系统二进制文件的 /sbin 子目录。还有一个包含用户二进制文件的 /bin 目录。在构建软盘发行版或嵌入式初始 RAM 磁盘时,可以将这个 _install 目录迁移到目标环境的根目录中root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/busybox/busybox-1.16.1/_install# ls
bin linuxrc sbin usr
BusyBox虽然为我们创建了Linux根系统中最基本的shell和一些常用命令,但是一个根文件系统还不只包含这些,还需要其它的一些内容。
本章第一节已经介绍了根文件系统中的一些目录,这些目录是Linux正常运行时所必需的。我们可以在BusyBox的_install基础上创建完整的根文件系统目录,一般步骤如下:
1 在PC上创建一个目标根文件系统的目录,例如/rootfs,将BusyBox里的_install目录里所有内容复制到这个文件夹里:cp –r _install /rootfs
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/busybox/busybox-1.16.1/_install#
cp -r bin ../../../../rootfs
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/busybox/busybox-1.16.1/_install#
cp -r sbin ../../../../rootfs
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/busybox/busybox-1.16.1/_install#
cp -r usr ../../../../rootfs
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/busybox/busybox-1.16.1/_install#
cp -d linuxrc ../../../../rootfs
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/osdrv/busybox/busybox-1.16.1/_install#
ls -l ../../../../rootfs
total 12
drwxr-xr-x 2 root root 4096 May 26 01:28 bin
lrwxrwxrwx 1 root root 11 May 26 01:30 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 4096 May 26 01:29 sbin
drwxr-xr-x 4 root root 4096 May 26 01:29 usr
语法: cp [选项] 源文件或目录 目标文件或目录
说明:该命令把指定的源文件复制到目标文件或把多个源文件复制到目标目录中。
该命令的各选项含义如下:
- a 该选项通常在拷贝目录时使用。它保留链接、文件属性,并递归地拷贝目录,其作用等于dpR选项的组合。
- d 拷贝时保留链接。
- f 删除已经存在的目标文件而不提示。
- i 和f选项相反,在覆盖目标文件之前将给出提示要求用户确认。回答y时目标文件将被覆盖,是交互式拷贝。
- p 此时cp除复制源文件的内容外,还将把其修改时间和访问权限也复制到新文件中。
- r 若给出的源文件是一目录文件,此时cp将递归复制该目录下所有的子目录和文件。此时目标文件必须为一个目录名。
- l 不作拷贝,只是链接文件。
复制指定目录下的全部文件到另一个目录中
假设复制源目录 为 dir1 ,目标目录为dir2。怎样才能将dir1下所有文件复制到dir2下了
如果dir2目录不存在,则可以直接使用
cp -r dir1 dir2
即可。
如果dir2目录已存在,则需要使用
cp -r dir1/. dir2
如果这时使用cp -r dir1 dir2,则也会将dir1目录复制到dir2中,明显不符合要求。
2 在/rootfs下创建目录etc/,dev/,lib/,tmp/,usr/,var/目录,同时var/目录里还需要创建var/run和var/log等目录。
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# mkdir etc
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# mkdir dev
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# mkdir lib
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# mkdir tmp
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# mkdir usr
mkdir: cannot create directory ‘usr’: File exists
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# mkdir var
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# cd var
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/var# ls
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/var# mkdir run
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/var# mkdir log
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/var# cd ..
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# ls
bin dev etc lib linuxrc sbin tmp usr var
[root@localhost c300]# ls -R rootfs
rootfs:
bin dev etc init lib linuxrc mnt proc sbin sys tmp usr var
rootfs/bin:
[ basename chmod cp dirname env fgrep grep id killall5 logname mkfifo netstat printenv realpath sh telnet top umount usleep
[[ busybox chown cut dmesg expand free hexdump install ln ls mknod nice ps rm sleep test touch uname vi
arping cat cksum date echo expr ftpget hostid kill logger mesg mount ping pwd rmdir strings tftp true uniq who
ash chgrp cmp df egrep false ftpput hostname killall login mkdir mv ping6 readlink setsid tar time tty uptime yes
rootfs/dev:
console null ptmx pts ttyS0
rootfs/dev/pts:
rootfs/etc:
fstab group hostname init.d inittab localtime mtab passwd profile resolv.conf shadow shells sysctl.conf
rootfs/etc/init.d:
rcS reboot
rootfs/lib:
ld-2.9.so libc-2.9.so libdl-2.9.so libm-2.9.so libnss_dns-2.9.so libpthread-2.9.so librt-2.9.so libutil-2.9.so
ld-linux.so.2 libcrypt-2.9.so libdl.so.2 libm.so.6 libnss_dns.so.2 libpthread.so.0 librt.so.1 libutil.so.1
libanl-2.9.so libcrypt.so.1 libgcc_s.so libnsl-2.9.so libnss_files-2.9.so libresolv-2.9.so libthread_db-1.0.so modules
libanl.so.1 libc.so.6 libgcc_s.so.1 libnsl.so.1 libnss_files.so.2 libresolv.so.2 libthread_db.so.1
rootfs/lib/modules:
rootfs/mnt:
rootfs/proc:
rootfs/sbin:
arp chpasswd getty halt hwclock ifconfig init insmod klogd logread lsmod mdev poweroff reboot rmmod route sysctl syslogd telnetd udhcpc
rootfs/sys:
rootfs/tmp:
rootfs/usr:
bin lib local sbin share
rootfs/usr/bin:
msp-control
rootfs/usr/lib:
libmsp.so libmsp.so.0 libmsp.so.0.1.0
rootfs/usr/local:
rootfs/usr/sbin:
init reboot
rootfs/usr/share:
udhcpc
rootfs/usr/share/udhcpc:
default.script
rootfs/var:
[root@localhost c300]#
[root@localhost rootfs]# cd dev
[root@localhost dev]# ls
console null ptmx pts ttyS0
[root@localhost dev]# ls -l
鎬昏 24
crwxr-xr-x 1 root root 5, 1 2015-10-26 console
crw-r--r-- 1 root root 1, 3 2015-10-26 null
crw-r--r-- 1 root root 5, 2 2015-10-26 ptmx
drwxr-xr-x 2 root root 4096 2015-10-26 pts
crwxr-xr-x 1 root root 4, 64 2015-10-26 ttyS0
mknod 的标准形式为: mknod DEVNAME {b | c} MAJOR MINOR
1,DEVNAME是要创建的设备文件名,如果想将设备文件放在一个特定的文件夹下,就需要先用mkdir在dev目录下新建一个目录;
2, b和c 分别表示块设备和字符设备:
b表示系统从块设备中读取数据的时候,直接从内存的buffer中读取数据,而不经过磁盘;
c表示字符设备文件与设备传送数据的时候是以字符的形式传送,一次传送一个字符,比如打印机、终端都是以字符的形式传送数据;
3,MAJOR和MINOR分别表示主设备号和次设备号:
为了管理设备,系统为每个设备分配一个编号,一个设备号由主设备号和次设备号组成。主设备号标示某一种类的设备,次设备号用来区分同一类型的设备。linux操作系统中为设备文件编号分配了32位无符号整数,其中前12位是主设备号,后20位为次设备号,所以在向系统申请设备文件时主设备号不好超过4095,次设备号不好超过2^20 -1。
.
下面,我们就可以用mknod命令来申请设备文件了。
mkdir -p /dev/cobing
mknod /dev/cobing/mydev1 c 128 512
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/dev# mknod console c 5 1root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/dev# mknod null c 1 3
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/dev# mknod ptmx c 5 2
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/dev# mknod ttyS0 c 4 64 root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/dev# mkdir pts
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/dev# ls
console null ptmx pts ttyS0
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs/dev# ls -l
total 4
crw-r--r-- 1 root root 5, 1 May 26 03:04 console
crw-r--r-- 1 root root 1, 3 May 26 03:04 null
crw-r--r-- 1 root root 5, 2 May 26 03:06 ptmx
drwxr-xr-x 2 root root 4096 May 26 03:07 pts
crw-r--r-- 1 root root 4, 64 May 26 03:07 ttyS0
318 rootfs的init
[root@localhost rootfs]# cat init
#!/bin/busybox ash
# Copyright (C) 2006 OpenWrt.org
/bin/busybox mount -t sysfs sysfs /sys
/bin/busybox mount -t proc proc /proc
exec /sbin/init "$@" /dev/console 2>&1
拷贝过来
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# gedit init
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs# chmod 777 init
root@ubuntu:~/product/Hi3531_SDK_V1.0.8.0/rootfs#
3 生成etc/里的设备文件,例如tty,console,fb(FrameBuffer),mtdblock(Memory Technology Device)等,这些设备文件是Linux很多驱动程序及就用程序正常的工作的基础。这些设备文件都是与相应的硬件相联系的,主要包含几种信息:设备类型,主设备号,次设备号。
其中设备类型主要包括字符设备(Character Device)和块设备(Block Device),字符设备主要字符的输入输出设备如键盘、鼠标等,块设备主要指整块数据的输入输出设备,如FLASH、硬盘等存储设备,一般包含缓冲区机制。
主设备号用来区分不同种类的设备,而次设备号用来区分同一类型的多个设备。对于常用设备,Linux有约定俗成的编号,如硬盘的主设备号是3,而次设备对应到每个具体的设备上,一般在/proc/devices文件里可以找到相关信息。
对于一个已存在的设备文件可以通过ls –l 命令来获取它的设备相关信息。
ls –l /dev/console
crw-rw---- 1 root root 5,1 Apr 14 23:08 /dev/console
可以看出第一个字母为c,这代表/dev/console是字符设备,若第一个字母为b,则为块设备。而root之后的 5,1就分别为相应设备的主次设备号了。
这里需要强调一点,设备文件类似于配置文件,存储的是一些设备信息,里面不包含特定平台下的指令,所以设备文件本身是平台无关的,也就是说在I386上创建的设备文件可以放在ARM的根文件系统,而可以被Linux正确识别的。
基本了解设备后,还需要如何创建它们,一般情况下可以使用mknod生成相应设备文件。mknod是Linux中用来创建设备文件的命令,格式如下:
mknode [–m MODE] NAME TYPE [MAJOR MINOR]
其中MODE用于指定设备文件的访问权限。NAME为设备文件的文件名,TYPE为相应的设备类型(字符设备c,块设备b等),MAJOR和MINOR分别为主次设备号。
例如要创建刚才的那个console命令可用如下的命令:
mknode –m 660 console c 5 1
设备文件的创建除了使用mknod命令,还可以使用MAKEDEV命令,MAKEDEV可以较方便的创建一系统的设备文件,一般的Linux发行版都有自带,其基本格式如下:
MAKEDEV –d directory -m maxdevices device
其中directory为设备文件的目标存放文件夹,若不指定则为当前系统下的/dev里。maxdevices为最大的设备数,因为MAKEDEV一般会创建一种设备的一系列设备文件,一般从0开始编号,直到maxdevices,所以一般这个需要指定,要不会生成较多的相关设备文件,而一般我们是不需要这么多的。最后一个参数device为对应的设备文件名,包括tty,vt,mem,null,zero,fd,hd,audio,sound等。这些参数的详细内容以及更多的参数选项,可以参考man手册。
可以这样创建硬盘的设备文件hd
MAKEDEV –d /rootfs/dev -m 2 hda
这条命令就会在/rootfs/dev目录中创建hda和hda1两个设备文件,指向第一块硬盘和第一块硬盘的第一个分区。
对于目标根文件系统中的设备文件,一般都应放在etc/目录中,可以用如下几种方法来获取相应的设备文件:
ü 可以手动用mknod命令一个个的创建设备文件;
ü 可以使用MAKEDEV来创建设备文件;
ü 甚至可以直接拷贝PC系统中部分设备文件至目标根文件系统中。
lib/目录放的是Linux就用程序所需的库文件,其实也是目标平台的指令代码,所以这里的文件与etc/里不一样,必须与相应的硬件平台相对应,例如i386里的库文件放到ARM系统中就不能使用的,这点与Linux的可执行文件一样。在PC机上使用ls /lib命令就可以看到很多.so结尾的库文件,这些.so文件就是Linux的动态链接库(类似于Windows下的DLL文件)。要注意的是.so文件名后缀还可能加上一些版本号标志例如.so.1,.so.1.2等都是动态链接库。
ü 目标根文件系统中的库文件从哪里来?
一般这些库都是事先编译好的,而且跟编译器相关的(glibc等),例如我们使用arm-linux-gcc进行编译则需要相应版本的一些库文件,这些库文件可以从编译器所在的目录里直接拷贝。对于ELDK开发包,可以从ELDK目录下的arm/lib/目录里复制相应文件。
ü 目标根文件系统需要哪些基本库文件?
库文件实际上是由其它可执行文件来调用的,所以库文件的取舍是由根文件系统中所包含的可执行文件来决定的。但是要运行可执行文件,一般有几个是系统必须的。它们是ld(ld-linux),libc,几乎所有的可执行文件都需要调用到这两个库文件。
ld(ld-linux):ld-linux.so 实际上就是一个可执行程序。这是负责执行动态装载的代码。它从可执行程序读取头信息(ELF格式的),然后通过这些信息判断必要的库和需要装载的库。之后,执行动态链接,修改可执行程序和装载的库中的所有地址指针,使程序能够运行。一般的文件名可能为ld-2.3.2.so,ld-linux.so.2,这点与编译器和系统版本有关。
libc:libc.so.6 是以 ld-linux.so.2 为基础架构而完成的动态链接库,它几乎负责了所有常用的标准 C 函数库,例如 Linux 下写的 Socket 程序,其中的connect()、bind()、send() .....之类的函数,都是由 libc.so.6 所提供的。
所以一个最基本的lib/目录应该至少包含这ld-linux.so.2和libc.so.6这两个文件。
ü 应用程序需要哪些库文件?
前面已经说过动态链接库是由应用程序(可执行文件)调用的,那对于一个特定的可执行文件是如何判断它需要哪些库文件的?一般可以编译器的ldd命令来查看,例如arm-linux-gcc包含了arm-linux-ldd命令用来查看ARM可执行文件调用的动态链接库。arm-linux-ldd的功能就是列出可执行文件及动态链接库运行时需要的库文件,例如,对于刚才所指的libc.so.6可以查找出其需要的动态链接库。这里我们假设为ELDK里的libc。
# file /eldk/arm/libc.so.6
libc.so.6:symbolic link to `libc-2.3.5.so`
通过file命令看出这里的libc.so.6实际上是个符号连接,链接到libc-2.3.5.so,所以我们继续追查libc-2.3.5.so:
#file libc-2.3.5.so
libc-2.3.5.so: ELF 32-bit LSB shared object, ARM, version 1(ARM), stripped
从这里可以明显的看出这个是ARM的Shared Object,也就是ARM格式的动态链接库。到这里可以判断出libc.so.6是ARM指令的。下来看libc.so.6到底需要哪些库文件:
#arm-linux-ldd libc.so.6
ld-linux.so.2 => not found
可以看出libc.so.6库文件需要ld-linux.so.2这个动态链接库(not found 说明在当前系统中未找到相应的库,因为系统是i386而需要的是ARM格式,所以找不到)。
这样通过arm-linux-ldd命令就可以确定各个程序所需的动态链接库,然后根据需要放到lib/目录里,就组成目标根文件系统的动态链接库集合了。
因为Linux系统加载根文件系统后需要执行一些配置以初始化整个Linux的工作环境及init程序和Shell等。这个文件就是etc/inittab。关于此文件的详细内容可以查看man inittab。但是BusyBox的inittab格式与一般Linux下的inittab的格式是不同,所以直接拷贝PC机上/etc/inittab文件到BusyBox制作的根文件系统中是不能用的,那怎么办呢?
BusyBox自带了符合它的格式的inittab样本文件,放在examples目录下,主要内容包括:
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
tty2::askfirst:-bin/sh
tty3::askfirst:-bin/sh
tty4::askfirst:-bin/sh
#Stuff to do when restarting the init process
::restart:/sbin/reboot
#Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff –a
BusyBox的inittab的每一行格式如下:
总共包含四项,每项间以”:”隔开。
第一二项
第三项
第四项
知道了格式,下面简单的分析一下inittab样本文件:
第一行::sysinit:/etc/init/rcS实际上指定了系统初始化(sysinit)时脚本为/etc/init/rcS,这个可以根据自己的需要更改的。
但是对于不同的终端设备的不同配置区别在于开头的标志,例如对于tty2终端,则有对应的操作 tty2::askfirst:-bin/sh。此行的意思指对于tty2使用shell为/bin/sh,同时对askfirst(有提示信息再要求登陆)。 若对于某个特定的终端设备可以直接将前面的设备标志去掉,例如ttyS0, ttyS1等。
第二行::askfirst:-/bin/sh指定了系统第一个终端在加载shell为/bin/sh,而且在进入shell前会提示用户。其它行请读者自行分析。
例如fstab、passwd、group、inputrc等,由于篇幅所限,不可能一一详解,读者可以参考其它书籍或者man手册,对于一些文件读者也可借用别的嵌入式根文件系统里的内容,然后在此基础上进行修改以符合自己的系统。这里简单介绍etc/里的几个文件:
ü fstab:这个文件描述系统中各种文件系统的信息。在这个文件中,每个文件系统用一行来描述,在每一行中,用空格或TAB符号来分隔各个字段,文件中以*开头的行是注释信息。一般内容可能如下:
/dev/mtdblock2 / jffs2 defaults 0 0
none /tmp ramfs defaults 0 0
none /proc proc defaults 0 0
第一列(字段):设备名或者设备卷标名(一般为/dev里的对应的设备文件)
第二列(字段):设备挂载目录 (例如上面的“/”或者“/tmp”)
第三列(字段):设备文件系统 (例如上面的“ext3”或者“vfat”)
第四列(字段):挂载参数 (具体可以查看帮助man mount)
对于已经挂载好的设备,例如上面的/dev/sda2,现在要改变挂载参数,这时可以不用卸载该设备,而可以使用下面的命令(没有挂载的设备,remount 这个参数无效)
#mount /mnt -o remount,ro (改defaults为ro)
关于其它参数请参考man手册。
第五列(字段):指明是否要备份。(0为不备份,1为要备份)
第六列(字段):指明自检顺序。 (0为不自检,1或者2为要自检,如果是根分区要设为1,其他分区只能是2)
ü passwd和group保存着Linux系统的用户组和用户名等,与硬件平台无关,为方便起见,可以从现有的Linux系统中拷贝过去即可。
etc/目录里的配置文件较多,不可能一一解释,请读者在创建时多参考已有的系统。
上面已经介绍一个根文件系统的创建过程,如果完整的按照上面的步骤做下来,应该就会在/rootfs下得到了一个相对完整的根文件系统,这个根文件系统主要BusyBox的bin/、sbin/目录,etc/系统配置文件目录以及lib/动态链接库所在目录等,这样一个Linux应用程序可执行的最小环境基本已经搭成了。之后可以在这个根文件系统中添加所需的应用程序等等。
但是这个根文件系统又是怎么放到目标开发板里的呢?
通常的做法是将整个根文件系统打包成某种文件系统格式的映像,然后下载到目标开发板的存储设备里(如FLASH等)。
用什么程序可以打包?支持几种格式呢?
通常使用mkfs系统命令。mkfs命令可以生成指定文件系统类型的映像文件。对于不同的文件系统类型需要不同的mkfs命令,例如EXT2,EXT3类型的文件可以使用mkfs.ext2和mkfs.ext3等。而通常嵌入式开发板使用FLASH作为存储设备,所以对应的文件系统类型一般为JFFS2,所以使用命令mkfs.jffs2命令,这个命令一般在开发板提供的工具有,也可以从网上搜索下载,这个命令一般是运行在PC系统上的,所以一般为I386可执行文件。
mkfs.jffs2的基本命令格式如下:
mkfs.jffs2 -r DIR -o FILE -e SIZE --pad=PADSIZE
其中DIR为要打包的文件夹,FILE为输出的文件路径,SIZE为每次擦除的块大小(默认为64KB)。PADSIZE为填充大小,这个参数强制使目标文件大小至少为PADSIZE字节,若实际数据没有这么大,则使用0xFF填充,这个参数很重要,在将映像写入目标开发板时一般应与实际根文件系统大小相符(类似于总磁盘容量),这样具有初始化的作用,若不相符合,在挂载这个JFFS2根文件系统时可能会出现一些问题。
下面给个简单的例子,这个例子将/rootfs的这个根文件系统打包成文件rootfs.img,且总大小为1M(0x100000字节)。
mkfs.jffs2 -r /rootfs -o rootfs.img -e 0x40000 --pad=0x100000
做好映像文件后就可以将这个映像文件写入目标板中,通常使用U-BOOT等BootLoader通过网卡下载到开发板内存中,然后再写入开发板的FLASH里。在U-BOOT里若网卡驱动可用,通常用tftp下载,再使用相关的FLASH操作命令写数据。
#!/bin/sh
mkfs.jffs2 --pad=2228224 -e 64KiB -d app -o app.img
cp app.img /tftpboot -f
cp app.img ../src -f
msp=../src/Default_EA_10_25_03_04-m823.axf
kernel=../src/zImage
uboot=../src/u-boot.bin
PACKET=c318.bin
dd if=$uboot of=uboot.out conv=sync ibs=384k count=1
dd if=$msp of=msp.out conv=sync ibs=2560k count=1
dd if=$kernel of=kernel.out conv=sync ibs=3072k count=1
cat uboot.out > $PACKET
cat msp.out >> $PACKET
cat kernel.out >> $PACKET
cat app.img >> $PACKET
cp $PACKET ../src/ -f
rm -f uboot.out msp.out kernel.out
root@user:image# cat build_fs
mkfs.ubifs -r $1 -m 2048 -e 126KiB -c $3 -o ubifs.img
ubinize -o $4 -m 2048 -p 128KiB -O 512 $2
rm -f ubifs.img
root@user:image# cat makeall
./build_fs ./app app.cfg 760 app.img
./build_fs ./dummy data.cfg 760 data.img
./build_fs ./dummy log.cfg 360 log.img
root@user:image# ls
app app.img build_lib data.img log.cfg makeall ubinize.cfg
app.cfg build_fs data.cfg dummy log.img ubi.img
root@user:image# cat app.cfg
[ubifs]
mode=ubi
image=ubifs.img
vol_id=0
vol_size=95MiB
vol_type=dynamic
vol_name=apps
vol_flags=autoresize
root@user:image# cat log.cfg
[ubifs]
mode=ubi
vol_id=0
vol_size=40MiB
vol_type=dynamic
vol_name=logs
vol_flags=autoresize
root@user:image# cat data.cfg
[ubifs]
mode=ubi
vol_id=0
vol_size=95MiB
vol_type=dynamic
vol_name=data
vol_flags=autoresize
root@user:image# cat ubinize.cfg
[ubifs]
mode=ubi
image=ubifs.img
vol_id=0
vol_size=35MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize
do_copy()
{
if [ -e "$1/lib/$2" ]; then
cp $1/lib/$2 .
ln -s $2 $3
fi
}
do_copy $1 ld-2.8.so ld-linux.so.3
do_copy $1 libanl-2.8.so libanl.so.1
do_copy $1 libc-2.8.so libc.so.6
do_copy $1 libcidn-2.8.so libcidn.so.1
do_copy $1 libcrypt-2.8.so libcrypt.so.1
do_copy $1 libdl-2.8.so libdl.so.2
do_copy $1 libgcc_s.so.1 libgcc_s.so
do_copy $1 libm-2.8.so libm.so.6
do_copy $1 libnsl-2.8.so libnsl.so.1
do_copy $1 libnss_compat-2.8.so libnss_compat.so.2
do_copy $1 libnss_dns-2.8.so libnss_dns.so.2
do_copy $1 libnss_files-2.8.so libnss_files.so.2
do_copy $1 libnss_hesiod-2.8.so libnss_hesiod.so.2
do_copy $1 libnss_nis-2.8.so libnss_nis.so.2
do_copy $1 libnss_nisplus-2.8.so libnss_nisplus.so.2
do_copy $1 libpthread-2.8.so libpthread.so.0
do_copy $1 libresolv-2.8.so libresolv.so.2
do_copy $1 librt-2.8.so librt.so.1
do_copy $1 libthread_db-1.0.so libthread_db.so.1
do_copy $1 libutil-2.8.so libutil.so.1
if [ -e "$1/usr/lib/libstdc++.so.6.0.10" ] ; then
cp $1/usr/lib/libstdc++.so.6.0.10 .
ln -s libstdc++.so.6.0.10 libstdc++.so
ln -s libstdc++.so.6.0.10 libstdc++.so.6
fi
root@user:image# cd app
root@user:app# ls
bin cfg lib modules
root@user:app# ls -r
modules lib cfg bin
root@user:app# ls modules
app_timer.ko
root@user:app# ls lib
root@user:app# ls cfg
netconfig udhcpd.conf
root@user:app# ls bin
app_init tcpdump
root@user:app#
root@user:image# ls dummy
root@user:image#
先打开一个超级用户权限的shell:
sudo –s
在当前shell下,设置环境变量:
export PATH=$PATH:/usr/local/arm/2.95.3/bin
再进入到kernel目录,make zImage,就可以找到arm-linux-gcc了
SYSMAP System.map
SYSMAP .tmp_System.map
OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
AS arch/arm/boot/compressed/head.o
GZIP arch/arm/boot/compressed/piggy.gzip
AS arch/arm/boot/compressed/piggy.gzip.o
CC arch/arm/boot/compressed/misc.o
CC arch/arm/boot/compressed/decompress.o
SHIPPED arch/arm/boot/compressed/lib1funcs.S
AS arch/arm/boot/compressed/lib1funcs.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
UIMAGE arch/arm/boot/uImage
"mkimage" command not found - U-Boot images will not be built
make[1]: *** [arch/arm/boot/uImage] Error 1
make: *** [uImage] Error 2
参见osdrv目录下readme
1.osdrv使用说明
本目录设计思路为一套源代码支持两种工具链编译,因此需要通过编译参数指定不同的工具链。其中arm-hisiv100nptl-linux是uclibc工具链,arm-hisiv200-linux是glibc工具链。具体命令如下
(1)编译整个osdrv目录:
make OSDRV_CROSS=arm-hisiv100nptl-linux all
或者
make OSDRV_CROSS=arm-hisiv200-linux all
(2)清除整个osdrv目录的编译文件:
make OSDRV_CROSS=arm-hisiv100nptl-linux clean
或者
make OSDRV_CROSS=arm-hisiv200-linux clean
(3)彻底清除整个osdrv目录的编译文件,除清除编译文件外,还删除已编译好的镜像:
make OSDRV_CROSS=arm-hisiv100nptl-linux distclean
或者
make OSDRV_CROSS=arm-hisiv200-linux distclean
(4)=================================================单独编译kernel==================================================:
待进入内核源代码目录后,执行以下操作
cp arch/arm/configs/godnet_defconfig .config
make ARCH=arm CROSS_COMPILE=arm-hisiv100nptl-linux- menuconfig
make ARCH=arm CROSS_COMPILE=arm-hisiv100nptl-linux- uImage
或者
cp arch/arm/configs/godnet_defconfig .config
make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux- menuconfig
make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux- uImage
(5)====================================================单独编译uboot========================================================
待进入boot源代码目录后,执行以下操作
make ARCH=arm CROSS_COMPILE=arm-hisiv100nptl-linux- godnet_config
make ARCH=arm CROSS_COMPILE=arm-hisiv100nptl-linux-
或者
make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux- godnet_config
make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux-
(6)=================================================制作文件系统镜像========================================:
在osdrv/pub/中有已经编译好的文件系统,因此无需再重复编译文件系统,只需要根据单板上flash的规格型号制作文件系统镜像即可。
spi flash使用jffs2格式的镜像,制作jffs2镜像时,需要用到spi flash的块大小。这些信息会在uboot启动时会打印出来。建议使用时先直接运行mkfs.jffs2工具,根据打印信息填写相关参数。下面以块大小为64KB为例:
osdrv/pub/bin/pc/mkfs.jffs2 -d osdrv/pub/rootfs_uclibc -l -e 0x40000 -o osdrv/pub/rootfs_uclibc_256k.jffs2
或者
osdrv/pub/bin/pc/mkfs.jffs2 -d osdrv/pub/rootfs_glibc -l -e 0x40000 -o osdrv/pub/rootfs_glibc_256k.jffs2
nand flash使用yaffs2格式的镜像,制作yaffs2镜像时,需要用到nand flash的pagesize和ecc。这些信息会在uboot启动时会打印出来。建议使用时先直接运行mkyaffs2image工具,根据打印信息填写相关参数。下面以2KB pagesize、1bit ecc为例:
osdrv/pub/bin/pc/mkyaffs2image osdrv/pub/rootfs_uclibc osdrv/pub/rootfs_uclibc_2k_1bit.yaffs2 1 1
或者
osdrv/pub/bin/pc/mkyaffs2image osdrv/pub/rootfs_glibc osdrv/pub/rootfs_glibc_2k_1bit.yaffs2 1 1
2. 镜像存放目录说明
编译完的image,rootfs等存放在osdrv/pub目录下
pub
│ rootfs_uclibc.tgz ------------------------------------------ hisiv100nptl编译出的rootfs文件系统
│ rootfs_glibc.tgz ------------------------------------------- hisiv200编译出的rootfs文件系统
│
├─image_glibc ------------------------------------------------ hisiv200编译出的镜像文件
│ uImage ------------------------------------------------- kernel镜像
│ u-boot-hi3531_930MHz.bin ------------------------------- u-boot镜像
│ rootfs_256k.jffs2 -------------------------------------- jffs2 rootfs镜像(对应spi-flash blocksize=256K)
│ rootfs_2k_1bit.yaffs2 ---------------------------------- yaffs2 rootfs镜像(对应nand-flash pagesize=2K ecc=1bit)
│
├─image_uclibc ----------------------------------------------- hisiv100nptl编译出的镜像文件
│ uImage ------------------------------------------------- kernel镜像
│ u-boot-hi3531_930MHz.bin ------------------------------- u-boot镜像
│ rootfs_256k.jffs2 -------------------------------------- jffs2 rootfs镜像(对应spi-flash blocksize=256K)
│ rootfs_2k_1bit.yaffs2 ---------------------------------- yaffs2 rootfs镜像(对应nand-flash pagesize=2K ecc=1bit)
│
└─bin
├─pc
│ mkfs.jffs2
│ mkimage
│ mkfs.cramfs
│ mkyaffs2image
│
├─board_glibc -------------------------------------------- hisiv200编译出的单板用工具以及pcie消息通讯层ko
│ flash_eraseall
│ mcc_usrdev_host.ko
│ flash_erase
│ mcc_usrdev_slv.ko
│ hi35xx_dev_slv.ko
│ nandwrite
│ hi35xx_dev_host.ko
│ mcc_drv_slv.ko
│ mtd_debug
│ flash_info
│ mcc_drv_host.ko
│ boot_device.ko
│ pcit_dma_slv.ko
│ sumtool
│ mtdinfo
│ flashcp
│ nandtest
│ nanddump
│ parted_glibc
│ pcit_dma_host.ko
│ gdb-arm-hisiv200-linux
│
└─board_uclibc ------------------------------------------- hisiv100nptl编译出的单板用工具以及pcie消息通讯层ko
flash_eraseall
mcc_usrdev_host.ko
flash_erase
mcc_usrdev_slv.ko
hi35xx_dev_slv.ko
nandwrite
hi35xx_dev_host.ko
mcc_drv_slv.ko
mtd_debug
flash_info
parted_uclibc
mcc_drv_host.ko
boot_device.ko
pcit_dma_slv.ko
sumtool
mtdinfo
flashcp
nandtest
gdb-arm-hisiv100nptl-linux
nanddump
pcit_dma_host.ko
3.osdrv目录结构说明:
osdrv
├─Makefile ------------------------------ osdrv目录编译脚本
├─busybox ------------------------------- 存放busybox源代码的目录
├─tools --------------------------------- 存放各种工具的目录
│ ├─board_tools ----------------------- 各种单板上使用工具
│ │ ├─reg-tools-1.0.0 --------------- 寄存器读写工具
│ │ ├─mtd-utils --------------------- flash裸读写工具
│ │ ├─udev-100 ---------------------- udev工具集
│ │ ├─gdb --------------------------- gdb工具
│ │ ├─parted ------------------------ 大容量硬盘分区工具
│ │ └─e2fsprogs --------------------- mkfs工具集
│ └─pc_tools -------------------------- 各种pc上使用工具
│ ├─mkfs.cramfs ------------------- cramfs文件系统制作工具
│ ├─mkfs.jffs2 -------------------- jffs2文件系统制作工具
│ ├─mkimage ----------------------- uImage制作工具
│ ├─mkyaffs2image301 -------------- yaffs2文件系统制作工具
│ ├─nand_production --------------- nand flash烧写文件制作工具
│ └─uboot_tools ------------------- uboot镜像制作工具、xls文件及ddr初始化脚本、bootrom工具
├─toolchain ----------------------------- 存放工具链的目录
│ ├─arm-hisiv100nptl-linux ---------------- hisiv100nptl交叉工具链
│ └─arm-hisiv200-linux ---------------- hisiv200交叉工具链
├─pub ----------------------------------- 存放各种镜像的目录
│ ├─image_glibc ----------------------- 基于hisiv100nptl工具链编译,可供FLASH烧写的映像文件,包括uboot、内核、文件系统
│ ├─image_uclibc ---------------------- 基于hisiv200工具链编译,可供FLASH烧写的映像文件,包括uboot、内核、文件系统
│ ├─bin ------------------------------- 各种未放入根文件系统的工具
│ │ ├─pc ---------------------------- 在pc上执行的工具
│ │ ├─board_glibc ------------------- 基于hisiv100nptl工具链编译,在单板上执行的工具
│ │ └─board_uclibc ------------------ 基于hisiv200工具链编译,在单板上执行的工具
│ ├─rootfs_uclibc.tgz ----------------- 基于hisiv100nptl工具链编译的根文件系统
│ └─rootfs_glibc.tgz ------------------ 基于hisiv200工具链编译的根文件系统
├─drv ----------------------------------- 存放外设驱动的目录
│ └─pcie_mcc -------------------------- pcie消息通讯层驱动
├─rootfs_scripts ------------------------ 存放根文件系统制作脚本的目录
├─uboot --------------------------------- 存放uboot源代码的目录
└─kernel -------------------------------- 存放kernel源代码的目录
4.注意事项
(1)使用某一工具链编译后,如果需要更换工具链,请先将原工具链编译文件清除,然后再更换工具链编译。
(2)在windows下复制源码包时,linux下的可执行文件可能变为非可执行文件,导致无法编译使用;u-boot或内核下编译后,会有很多符号链接文件,在windows下复制这些源码包, 会使源码包变的巨大,因为linux下的符号链接文件变为windows下实实在在的文件,因此源码包膨胀。因此使用时请注意不要在windows下复制源代码包。
(3)目前网络为自适应模式,如果要修改为固定某种速率模式,需要修改文件kernel/linux-3.0.y/drivers/net/stmmac/stmmac_mdio.c:
关掉宏定义TNK_HW_PLATFORM_ADJUST,注释掉33行;
选择需要固定配置的速率,例如固定配置为百兆全双工的话,打开46行宏定义PHY_SPEED_100即可。
(4)Hi3531支持硬浮点,文件系统中发布的库都是硬浮点库。因此请用户注意,所有Hi3531板端代码编译时需要在Makefile里面添加以下命令:
CFLAGS += -march=armv7-a -mcpu=cortex-a9 –mfloat-abi=softfp -mfpu=vfpv3-d16
CXXFlAGS +=-march=armv7-a -mcpu=cortex-a9 –mfloat-abi=softfp -mfpu=vfpv3-d16
其中CXXFlAGS中的XX根据用户Makefile中所使用宏的具体名称来确定,e.g:CPPFLAGS。
(2)系统启动后,配置load3531的脚本中mmz的管理内存为208M(DDR0)和256M(DDR1),“insmod mmz.ko mmz=anonymous,0,0x83000000,208M:ddr1,0,0xC0000000,256M anony=1 || report_error”。
linux操作系统下双网卡绑定有七种模式。现在一般的企业都会使用双网卡接入,这样既能添加网络带宽,同时又能做相应的冗余,可以说是好处多多。而一般企业都会使用linux操作系统下自带的网卡绑定模式,当然现在网卡产商也会出一些针对windows操作系统网卡管理软件来做网卡绑定(windows操作系统没有网卡绑定功能 需要第三方支持)。进入正题,linux有七种网卡绑定模式:0. round robin,1.active-backup,2.load balancing (xor), 3.fault-tolerance (broadcast), 4.lacp, 5.transmit load balancing, 6.adaptive load balancing。
一个网卡处于活动状态 ,一个处于备份状态,所有流量都在主链路上处理。当活动网卡down掉时,启用备份的网卡。
1:[root@lyt ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0 #编辑该设备eth0如图:
[root@lyt ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth1 #编辑该设备eth1 如图:
2:[root@lyt ~]# cd /etc/sysconfig/network-scripts/
[root@lyt network-scripts]# cp ifcfg-eth0 ifcfg-bond0 #生成一个bond0的虚拟网卡
[root@lyt network-scripts]# vim ifcfg-bond0 #编辑该网卡内容
3:[root@lyt network-scripts]# vim /etc/modprobe.conf #编辑该配置文件
下图中1表示系统在启动时加载bonding模块,对外虚拟网络接口设备为 bond0;miimon=100表示系统每100ms监测一次链路连接状态,如果有一条线路不通就转入另一条线
路;mode=1表示fault-tolerance (active-backup)提供冗余功能,工作方式是主备的工作方式,也就是说默认情况下只有一块网卡工作,另一块做备份。
4:[root@lyt network-scripts]# vim /etc/rc.local #编辑该开机脚本,将eth0和eth1网卡进行绑定
5:[root@lyt network-scripts]# init 6 #重启,bond0启动成功
[root@lyt ~]# ifconfig #查看网卡信息,在此处三块网卡的mac地址是一样的
[root@lyt ~]#vim /proc/net/bonding/bond0 #查看模式及网卡信息。实际mac地址是不一样的
测试:
6:Xshell:\> ping 192.168.101.50 –t #一直测试网络的连通性查看结果
断掉eth0网卡后显示结果
将网卡eth0断掉后,系统使用备份网卡eth1,此时eth1处于活动状态
所有链路处于负载均衡状态,这模式的特点增加了带宽,同时支持容错能力。
1:在案例一的基础上,只需要修改/etc/modprobe.conf 配置文件:如图:
2:vim /proc/net/bonding/bond0 #查看使用的模式及网卡信息,如图:
测试:mode=0:
3:Xshell:\> ping 192.168.101.50 –t #一直测试网络的连通性查看结果
将网卡eth1断掉后,系统依然可以ping通