两周来的学习小结

 

构建自己的交叉编译环境

嵌入式设备由于不具备一定的处理器能力和存储空间,程序开发一般用PC来完成,然后将可执行文件下载到嵌入式系统中运行。这是目前嵌入式程序开发的 不二选择——Host/target模式。但这引发了一个问题:由于Host和target的处理器体系结构不同,我们不能直接用PC上既有的程序开发工 具,必须使用跨平台开发工具,即在Host上生成能在Target上运行格式的目标文件。以下我会简单的说一下怎么构建交叉编译环境,当然如果不想麻烦也 可以到网上去下载。先下载binutils、gcc、glibc、linux-kernel等包和几个插件,先解压glibc-2.3.5,打开 INSTALL文件,看其中对 gcc、awk、sed等软件的要求。

[ 编辑]

设置环境变量

TARGET=arm-linux

PREFIX=/usr/arm

SYSROOT=${PREFIX}/sysroot

export ARCH=arm

export CROSS_COMPILE=${TARGET}-

export PATH=$PATH:${PREFIX}/bin

[ 编辑]

建立二进制工具

mkdir -p ${PREFIX}/src

cd ${PREFIX}/src

tar zxvf binutils-2.16.tar.gz

mkdir -p BUILD/binutils-2.16

cd BUILD/binutils-2.16

../../binutils-2.16/configure --prefix=${PREFIX} --target=${TARGET} --with-sysroot=${SYSROOT} && make && make install && echo ok

(如果最后一行显示ok则表示安装成功)

[ 编辑]

建立内核头文件

cd ${PREFIX}/src

tar zxvf linux-2.6.10.tar.gz

ln -s linux-2.6.10 linux

zcat 2.6.10-at91.patch.gz | patch -d linux -p1

cd linux

make at91rm9200dk_defconfig

make include/linux/version.h

mkdir -p ${SYSROOT}/usr/include

cp -a ${PREFIX}/src/linux/include/linux ${SYSROOT}/usr/include/linux

cp -a ${PREFIX}/src/linux/include/asm-arm ${SYSROOT}/usr/include/asm

cp -a ${PREFIX}/src/linux/include/asm-generic ${SYSROOT}/usr/include/asm-generic

[ 编辑]

安装glibc头文件

cd ${PREFIX}/src

tar zxvf glibc-2.3.5.tar.gz

patch -d glibc-2.3.5 -p1 < ioperm.c.diff

cd glibc-2.3.5

tar xvfz ../glibc-linuxthreads-2.3.5.tar.gz

cd ..

mkdir -p BUILD/glibc-2.3.5-headers

cd BUILD/glibc-2.3.5-headers

../../glibc-2.3.5/configure --prefix=/usr --host=${TARGET} --enable-add-ons=linuxthreads --with-headers=${SYSROOT}/usr/include &&

make cross-compiling=yes install_root=${SYSROOT} install-headers && echo ok

touch ${SYSROOT}/usr/include/gnu/stubs.h

touch ${SYSROOT}/usr/include/bits/stdio_lim.h

[ 编辑]

建立初始编译器

cd ${PREFIX}/src

tar jxvf gcc-3.4.4.tar.bz2

patch -d gcc-3.4.4 -p1 < flow.c.diff

patch -d gcc-3.4.4 -p1 < t-linux.diff

mkdir -p BUILD/gcc-3.4.4-stage1

cd BUILD/gcc-3.4.4-stage1

../../gcc-3.4.4/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c --with-sysroot=${SYSROOT} && make && make install

&& echo ok

[ 编辑]

建立c库

cd ${PREFIX}/src

mkdir -p BUILD/glibc-2.3.5

cd BUILD/glibc-2.3.5

BUILD_CC=gcc CC=${CROSS_COMPILE}gcc AR=${CROSS_COMPILE}ar RANLIB=${CROSS_COMPILE}ranlib AS=${CROSS_COMPILE}as LD=${CROSS_COMPILE}ld ..

/../glibc-2.3.5/configure --prefix=/usr --build=i386-redhat-linux --host=arm-linux --target=arm-linux --without-__thread --enable-add

-ons=linuxthreads --with-headers=${SYSROOT}/usr/include && make && make install_root=${SYSROOT} install && echo ok

[ 编辑]

建立全套编译器

cd ${PREFIX}/src

mkdir -p BUILD/gcc-3.4.4

cd BUILD/gcc-3.4.4

../../gcc-3.4.4/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c,c++ --with-sysroot=${SYSROOT} && make && make

install && echo ok

[ 编辑]

测试

1)编写一个HelloWorld程序,然后arm-linux-gcc helloworld.c -o helloworld
2)file helloworld
aa: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped
如果显示出上面的输出,说明你编译了一个能在arm体系结构下运行的helloworld,证明你的编译工具做成功了。


[ 编辑]

u-boot移植

BootLoader就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的 软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。BootLoader是严重地依赖于硬件而实现的,特别是在嵌入式世界。
由于BootLoader的实现依赖于CPU的体系结构,因此大多数BootLoader都分为stage1和stage2 两大部分。依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而 stage2则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。

BootLoader的stage1通常包括以下步骤(以执行的先后顺序):

1、硬件设备初始化。
2、为加载BootLoader的stage2准备RAM空间。
3、拷贝BootLoader的stage2到RAM空间中。(注:由于stage2通常是C语言执行代码,因此在考虑空间大小时,除了stage2可执行映象的大小外,
还必须把堆栈空间也考虑进来。一般情况下都是分出1M的RAM给它们,我的习惯是把RAM顶层的1M空间空出来分给它们,即 0x21f00000到0x21
ffffff,当然也可以把RAM起始位置的1M空间分给他们)
4、设置好堆栈。
5、跳转到stage2的C入口点。

BootLoader的stage2通常包括以下步骤(以执行的先后顺序):

1、初始化本阶段要使用到的硬件设备。
2、检测系统内存映射(memory map)。
3、将kernel映像和根文件系统映像从flash上读到RAM空间中。
4、为内核设置启动参数。
5、调用内核。

如今能支持RAM cpu的BootLoader有好多个,其中支持类型最多,且最出名的是blob和u-boot,本篇就介绍一下我用u-boot往at91rm9200开发板上移植的过程:

[ 编辑]

修改myboard目录下的文件内容

cp -R at91rm9200dk myboard
1)cp at91rm9200dk.c myboard.c
2)vi Makefle

将COBJS   := at91rm9200dk.o at45.o flash.o 改为 COBJS   := myboard.o at45.o flash.o

3)添加Nor Flash驱动,芯片型号是MBM29LV320BE(FUJITSU)
vi flash.c
1>由于这个型号的Nor Flash有71个扇区,且前9个是8K,后62个是64K,因此加入

OrgDef OrgMBM29LV320BE[] =
{
{ 8, 8*1024 }, /* 8 * 8 kBytes sectors */
{ 63, 64*1024 }, /* 63 * 64 kBytes sectors */
};

2>加入

#define RESET           0xF0

3>
在函数void flash_identification (flash_info_t * info)中加入:

/* Read Reset  */
MEM_FLASH_ADDR1 = FLASH_CODE1;
MEM_FLASH_ADDR2 = FLASH_CODE2;
MEM_FLASH_ADDR1 = RESET;
/* Go to Autoselect mode */
MEM_FLASH_ADDR1 = FLASH_CODE1;
MEM_FLASH_ADDR2 = FLASH_CODE2;
MEM_FLASH_ADDR1 = ID_IN_CODE;
/* Vendor type */
info->flash_id = FUJ_MANUFACT & FLASH_VENDMASK;
printf("FUJ and AMD/n");
/* AMD Flash */
info->flash_id |= AMD_ID_LV320B & FLASH_TYPEMASK;
printf("MBM29LV320B (32Mbit)/n");

4>
在函数ulong flash_init (void)中加入:

/* MBM29LV320BE Flash */
pOrgDef = OrgMBM29LV320BE;
flash_nb_blocks = sizeof (OrgMBM29LV320BE) / sizeof (OrgDef);

5>
在函数void flash_print_info (flash_info_t * info)中加入:

case (FUJ_MANUFACT & FLASH_VENDMASK):
printf("FUJ");
break;
case (AMD_ID_LV320B & FLASH_TYPEMASK):
printf("MBM29LV320BE (32Mbit/n)");
break;

6>
在函数int flash_erase (flash_info_t * info, int s_first, int s_last)中加入:

if ((info->flash_id & FLASH_VENDMASK) != (FUJ_MANUFACT & FLASH_VENDMASK)) 
{
return ERR_UNKNOWN_FLASH_VENDOR;
}
[ 编辑]

修改u-boot目录下的Makefile文件

回到u-boot目录下,打开Makefile文件,加入(为了能make myboard_config):

myboard_config  :   unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t myboard NULL at91rm9200
[ 编辑]

修改u-boot目录下的MAKEALL文件

在u-boot目录下,打开MAKEALL文件,在

LIST_ARM9=" /
at91rm9200dk cmc_pu2 /
ap920t ap922_XA10 ap926ejs ap946es /
ap966 cp920t cp922_XA10 cp926ejs /
cp946es cp966 lpd7a400 mp2usb /
mx1ads mx1fs2 netstar omap1510inn /
omap1610h2 omap1610inn omap730p2 sbc2410x /
scb9328 smdk2400 smdk2410 trab /
VCMA9 versatile versatileab versatilepb /
voiceblue /
"

加入 myboard,即:

LIST_ARM9=" /
at91rm9200dk cmc_pu2 /
ap920t ap922_XA10 ap926ejs ap946es /
ap966 cp920t cp922_XA10 cp926ejs /
cp946es cp966 lpd7a400 mp2usb /
mx1ads mx1fs2 netstar omap1510inn /
omap1610h2 omap1610inn omap730p2 sbc2410x /
scb9328 smdk2400 smdk2410 trab /
VCMA9 versatile versatileab versatilepb /
voiceblue myboard /
"
[ 编辑]

修改myboard的头文件

cd include/configs,cp at91rm9200dk.h myboard.h,打开myboard.h文件
1)加入#define CONFIG_SKIP_LOWLEVEL_INIT (由于板子会自动进行初始化,所以此处要跳过去,否则会成为死循环)
2)由于我的板子上的Nor Flash是4M,所以把

#define PHYS_FLASH_SIZE  0x200000

改为

#define PHYS_FLASH_SIZE  0x400000

3)由于我的板子上的Nor Flash共71个扇区,所以把

#define CFG_MAX_FLASH_SECT      256

改为

#define CFG_MAX_FLASH_SECT      71
[ 编辑]

编译

export BUILD_DIR=/home/lb/abc
make distclean
make myboard_config
make all

在/home/lb/abc中会生成三个可执行文件u-boot.bin、u-boot和u-boot.srec,通常是用u-boot.bin文件。


[ 编辑]

编译内核

Bootloader将内核加载到内存中,设定一些寄存器,然后将控制权交由内核,该过程中,关闭MMU功能。通常,内核都是以压缩的方式存放,如zImage,这里有两种解压方法:

1、使用内核自解压程序。
2、在Bootloader中增加解压功能。

使用该方法时内核不需要带有自解压功能,而使用Bootloader中的解压程序代替内核自解压程序。其工作过程与内核自解压过程相似:Bootloader把压缩方式的内核解压到内存中,然后跳转到内核入口处开始执行。

内核有多种启动方式,如下:
XIP(EXECUTE IN PLACE)是指直接从存放代码的位置上启动运行。

1、非压缩,非XIP

非XIP方式是指在运行之前需对代码进行重定位。该类型的内核以非压缩方式存放在Flash中,启动时由Bootloader加载到内存后运行。

2、非压缩,XIP

该类型的内核以非压缩格式存放在ROM/Flash中,不需要加载到内存就能运行,Bootloader直接跳转到其存放地址执行。Data段复制 和BSS 段清零的工作由内核自己完成。这种启动方式常用于内存空间有限的系统中,另外,程序在ROM/Flash中运行的速度相对较慢。

3、RAM自解压

压缩格式的内核由开头一段自解压代码和压缩内核数据组成,由于以压缩格式存放,内核只能以非XIP方式运行。RAM自解压过程如下:压缩内核存放于 ROM/Flash中,Bootloader启动后加载到内存中的临时空间,然后跳转到压缩内核入口地址执行自解压代码,内核被解压到最终的目的地址然后 运行。压缩内核所占据的临时空间随后被Linux回收利用。这种方式的内核在嵌入式产品中较为常见。

4、ROM自解压

解压缩代码也能够以 XIP的方式在ROM/Flash中运行。ROM自解压过程如下:压缩内核存放在ROM/Flash中,不需要加载到内存就能运行,Bootloader 直接跳转到其存放地址执行其自解压代码,将压缩内核解压到最终的目的地址并运行。ROM自解压方式存放的内核解压缩速度慢,而且也不能节省内存空间。

先下载一个内核原文件和相对应的ARM内核补丁。通常情况下ARM内核不要超过1M,所以对自己没有用的选项都可以不选。

[ 编辑]

安装插件

cd linux-2.6.*
zcat ../2.6.*-at91.patch.gz |patch -p1
[ 编辑]

修改linux-2.6.*目录下的Makefile文件

vi Makefile

ARCH     ?= $(SUBARCH)
CROSS_COMPILE ?=

改为

ARCH            ?= arm
CROSS_COMPILE  ?= 相应交叉编译环境 (我的是arm-linux-)
[ 编辑]

编译

make at91rm9200dk_defconfig
make menuconfig
make

(注:配置ARMlinux的方法和配置官方Linux内核差不多,以下是我对内核的配置,可供大家参考:
[Gernel setup]通用配置

  选择 Sysctl support
选择 System V IPC
这两个选项我也没有深入研究,不知不选是不是也可以?其它的都不要选了。

[Memory Technology Devices(MTD)] MTD 配置

  选择 <*>Memory Technology Device(MTD) support 记着选择为“built-in”而不是“module”(前面的选项为“*”而不是“M”)
选择 <*>Mtd partitioning support MTD 分区支持
选择 <*>Caching block device access to MTD devices 支持 MTD作为BLOCK设备访问
进入【RAM/ROM/FLASH chip drivers- 】选项选择加载 FLASH 的驱动
选择 <*> Detect flash chips by Common Flash Interface (CFI) probe自动探测 CFI 接口的 FLASH 设备
选择 <*> Support for AMD/Fujistu flash chips 选择对 AMD/Fujistu FLASH 设备的支持
选择 <*> Support for ROM chips in bus mapping 支持 ROM 设备总线 MAP
其它选项不选,退回到上一级。
进入【Mapping drivers for chip access- 】选项
选择 <*> CFI Flash device mapped on ARM Integrator/P720T 支持 ARM 的 FLASH 分区
其它选项都不用选中。

[Networking Options] 网络选项

  本选项全部为 built-in 方式。
选择<*> Packet socket
选择<*> Kernel/User netlink socket
选择<*> Unix domain sockets
选择<*> TCP/IP networking
选择<*> IP: multicasting 支持组播
选择<*> IP: kernel level autoconfiguration
选择<*> IP: DHCP support
选择<*> IP: BOOTP support
选择<*> IP: RARP support
其它的都可以不选。

[File systems] 文件系统

  该目录下包含内核对各种文件系统的支持,可以根据需要选择想要的文件系统。
选择<*> Second extended fs support
选择<*> JFS filesystem support
进入[Miscellaneous filesystems]选项
选择<*> Jouralling Flash File System V2 (JFFS2) support内核支持 JFFS 和 JFFS2 文件系统
进入【Network File Systems- 】 网络文件系统子选项
选择<*> NFS file system support NFS 网络文件系统支持
选择<*> Provide NFSv3 client support 支持 NFS 版本 3 客户端
选择<*> Root file system on NFS 根文件系统采用 NFS
退回上级菜单,其它的都没有选中。
其它的配置可以根据目标系统的不同灵活配置,像IDE、Sound等和目标系统没关系的选项都可以去掉,因“板”而异吗。

)

4、生成内核映像文件

cp linux2.6.*/vmlinux /home/lb/kernel
cp linux2.6.*/arch/arm/boot/zImage /home/lb/kernel
cd /home/lb/kernel
1)arm-linux-objcopy -O binary -S vmlinux linux.bin
2)gzip -v9 linux.bin
3)/home/lb/abc/tools/mkimage -A arm -O linux -T kernel -C gzip -a 0x20008000 -e 0x20008000 -d linux.bin.gz uImage

( 注:uboot源代码的tools/目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。 mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头,记录参数所指定的信息,这样uboot才能识别这个映象是针对哪个CPU体系结构的,哪个OS的,哪种类型,加载内存中的哪个位置,入口点在内存的那个位置以及映象名是什么。

参数说明:
-A 指定CPU的体系结构:
alpha Alpha
arm ARM
x86 Intel x86
ia64 IA64
mips MIPS
mips64 MIPS 64Bit
ppc PowerPC
s390 IBM S390
sh SuperH
sparc SPARC
sparc64 SPARC 64Bit
m68k MC68000

-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 指定制作映象的源文件
)
得到了内核映射文件uImage

[ 编辑]

构建文件系统

在嵌入式Linux开发中, 往往需要为目标系统设置根文件系统, 这包括: 准备好根文件系统所需的内容, 选择目标系统的文件系统类型, 将根文件系统的内容转换为所用文件系统的格式, 将根文件系统安装到目标系统上。 常用的文件系统有:
1、ramdisk

ramdisk的优点: 读写速度非常快, 适合用来制作initrd。
ramdisk的缺点: 不具有永久性, 断电后无法保存. 且ramdisk大小不可更改, 浪费ram。

2、tmpfs

tmpfs是一个以虚拟内存为基础的文件系统,它的大小不是固定的, 这都是它区别于ramdisk的优点。
tmpfs以虚拟内存为基础, 所以它不同于ramdisk,ramdisk只能位于ram中, 而tmpfs可能位于交换分区中(Linux内核的虚拟内存资源同时来源于
RAM和交换分区)。
tmpfs是个文件系统, 而不是块设备,同样和ramdisk比较: ramdisk是个块设备, 需要一个mkfs之类的命令将个做成某个格式的文件系统才能使
用,而tmpfs是一个文件系统不是块设备,mount它即可使用。

3、cramfs

1)采用实时解压缩方式,但解压缩的时侯有延迟。
2)cramfs的数据都是经过处理、打包的,对其进行写操作有一定困难。所以cramfs不支持写操作,这个特性刚好适合嵌入式应用中使用Flash存
储文件系统的场合。
3)在cramfs中,文件最大不能超过16MB。
4)支持组标识(gid),但是mkcramfs只将gid的低8位保存下来,因此只有这8位是有效的。
5)支持硬链接。但是cramfs并没有完全处理好,硬链接的文件属性中,链接数仍然为1.
6)cramfs的目录中,没有“.”和“..”这两项。因此,cramfs中的目录的链接数通常也仅有一个。
7) cramfs中,不会保存文件的时间戳(timestamps)信息。当然,正在使用的文件由于inode保存在内存中,因此其时间可以暂时地变更为最新时
间,但是不会保存到cramfs文件系统中去。
8)当前版本的cramfs只支持PAGE_CACHE_SIZE为4096的内核。因此,如果发现cramfs不能正常读写的时侯,可以检查一下内核的参数设置。

在嵌入式的环境之下,内存和外存资源都需要节约使用。如果使用ramdisk方式来使用文件系统,那么在系统运行之后,首先要把外存(Flash) 上的映像文件解压缩到内存中,构造起ramdisk环境,才可以开始运行程序。但是它也有很致命的弱点。在正常情况下,同样的代码不仅在外存中占据了空间 (以压缩后的形式存在),而且还在内存中占用了更大的空间(以解压缩之后的形式存在),这违背了嵌入式环境下尽量节省资源的要求。
使用cramfs就是一种解决这个问题的方式。cramfs是一个压缩式的文件系统,它并不需要一次性地将文件系统中的所有内容都解压缩到内存之中,而只 是在系统需要访问某个位置的数据的时侯,马上计算出该数据在cramfs中的位置,将其实时地解压缩到内存之中,然后通过对内存的访问来获取文件系统中需 要读取的数据。 cramfs中的解压缩以及解压缩之后的内存中数据存放位置都是由cramfs文件系统本身进行维护的,用户并不需要了解具体的实现过程,因此这种方式增 强了透明度,对开发人员来说,既方便,又节省了存储空间。

我选择的文件系统是ramdsik:
要先安装mtd(memory technology device),debian中安装mtd-tools,gentoo中安装mtd-utils。

[ 编辑]

建立内存映像文件ramdisk

1)mkdir -p /mnt/loop
2)dd if=/dev/zero of=/tmp/loop_tmp bs=1k count=3072
3)/sbin/losetup /dev/loop0 /tmp/loop_tmp
将设备与临时文件联系起来。如果出现“ioctl: LOOP_SET_FD: 设备或资源忙”的提示,说明设备还和一文件联系,可以用/sbin/losetup /de
v/loop0来看,并可用-d来删除。
4)mkfs.ext2 –m0 /dev/loop0
mkfs.ext2将会自动判断设备容量的大小并相应地配置自身,-m0参数防止它给root保留空,这样会腾出更多地有用空间。
5)mount -t ext2 /dev/loop0 /mnt/loop
6)mkdir {bin,sbin,usr,dev,etc,lib,home,opt,root,src,tmp,var,mnt,proc,sys,initrd}
7)umount /mnt/loop
卸载此文件系统,得到的/tmp/loop_tmp就是ramdisk,可以将其改名为ramdisk
8)gzip - v9 /tmp/ramdisk
在/tmp中生成一个ramdisk.gz,这样一个内存映像文件就生成了。
[ 编辑]

编译busybox

1)
make defconfig
make menuconfig
2)busybox设置
1>在Build Options中的Build BusyBox as a static binary (no shared libs)是问是否将busybox静态链接,如果是glibc的话不选,如果是uclib
c的话要选。
2>在Installation Options选项中,默认地, 运行 make install之后, BusyBox将被安装到./_install目录。
3>NFS是肯定要选的, 使用NFS将宿主机的文件系统mount到目标板上, 这是嵌入式Linux程序开发的一个重要方面。
4>由于可使用NFS, 能在宿主机上实现的功能就都不需要在目标板上实现了。
5>Debian Utilities 全不选, Editors全不选, System Logging Utilities全不选。
6>解压缩工具只安装解压工具,gzip、bzip2、tar工具(要求目标板能解压缩tar.bz2和tar.gz文件)。
7>shell使用ash。
3)编译及安装
make TARGET_ARCH=arm CROSS=arm-linux- -j2
make install
[ 编辑]

用busybox给ramdisk增加命令

1)
gunzip ramdisk.gz
mount -o loop ramdisk /mnt/ramdisk
2)
cd busybox1.4.1/_install
cp -rfv * /mnt/ramdisk
umount /mnt/ramdisk
gzip -v9 ramdisk

生成最后带有busybox命令的内存映像文件ramdisk.gz,不过此时的ramdisk文件系统内仍缺少一些必需的东西,如/lib下的库 文件、 /etc下的一些配置文件、/dev下的一些块设备和文件系统等,这都需要自己添加,如果觉得麻烦,可以下载一个现成的,然后在它的基础上作一些修改。

(注:
BusyBox 将数以百计的常用Unix/Linux命令集成到一个可执行文件中(名为busybox)。它体积小巧, 功能却不失强大,常用Linux命令实现的功能它都能提供,它甚至还提供了tftp, http服务程序,尽管少数的Linux命令的某些选项BusyBox没能提供, 但这并不影响它在嵌入式Linux系统中的流行。
BusyBox 可以与glibc或uClibc库进行链接编译, 可以采用动态链接或静态链接,即便采用与glibc的静态链接, 最终生成的busybox文件大小也能轻易控制在1MB之内,而采用uClibc动态链接的可执行文件就更小了,这非常适于存储空间紧张的嵌入式 Linux系统。由此, 有人将BusyBox称为嵌入式系统中的瑞士军刀,更为形象的比喻是: Linux系统中的单个命令是电路中的分立式元件, 而BusyBox是将它们集成在一起的IC: 功能不变, 体积却大为减小。
)


[ 编辑]

向Nor Flash烧写u-boot和linux操作系统

[ 编辑]

片内启动

[ 编辑]
用Xmodem协议下载loader.bin和uboot-bin

用Xmodem协议,发送loader.bin和uboot.bin文件,此时uboot.bin被发送到系统的SDRAM中,发送完后uboot开始运行,如果这时断电或退出,则一切将从头开始,因为SDRAM内存储的数据会在断电或退出后消失。

[ 编辑]
擦除Flash

在对Flash进行烧写之前,需要将其擦除:

Uboot>protect off all           去掉Flash的扇区写保护
Uboot>erase all 擦除Flash的所有扇区

(注:
如果只是要擦除某块区域的Flash,比如0x10000000到0x10060000之间的区域,则可用命令:

1)protect off 10000000 1006ffff
2)erase 10000000 1006ffff

如果是要对某块区域加上写保护,比如0x10000000到0x10060000之间的区域,则可用命令:

1)protect on 10000000 1006ffff

可用flinfo命令来查看那些区域是受保护的,那些区域不是受保护的。
)

[ 编辑]
烧写boot.bin到Flash

在Uboot提示符下键入命令:
Uboot>loadb 21000000 (下完之后会显示boot.bin的大小,然后在后面用命令cp.b烧写时将其后4位变成f,假如文件大小为5e33a,则在烧写时将其变为5ffff) 将文件发送到系统的SDRAM中
然后在超级终端使用Kermit协议,发送文件boot.bin,发送完毕后,键入以下命令:

Uboot>cp.b 21000000 10000000 5ffff      将发送到SDRAM中的数据写入Flash
Uboot>protect on 10000000 10005ffff 对写入Flash的内容进行写保护

(注:
此处还可以用tftp或bootp协议来完成,不过要先设置网络变量,即设置本机和目标机的IP地址,还有目标机的Mac地址。
网络环境变量:

Uboot>setenv bootargs root=/dev/ram rw initrd=0x21100000,6000000 ramdisk_size=15360
console=ttyS0,115200,mem=32M 启动系统环境变量
Uboot>setenv ethaddr 12:34:56:78:99:aa mac 地址
Uboot>setenv ipaddr [目标板 ip 地址] 目标板 ip 地址
Uboot>setenv serverip [主机 ip 地址] 主机 ip 地址

tftp协议:

1)tftp 21000000 lb/boot.bin
2)cp.b 21000000 10000000 5ffff
3)protect on 10000000 10005fff

bootp协议:

1)bootp 21000000 lb/boot.bin
2)cp.b 21000000 10000000 5ffff
3)protect on 10000000 10005fff

)

[ 编辑]
烧写 Uboot.gz 到 Flash

在Uboot提示符下键入命令:装入Uboot.gz

Uboot>loadb 20000000                   将文件发送到系统的SDRAM中

然后在超级终端使用Kermit协议,发送文件Uboot.gz,发送完毕后,键入以下命令:

Uboot>cp.b 20000000 10010000 ffff      将发送到SDRAM中的数据写入Flash
Uboot>protect on 10000000 1001ffff 对写入Flash的内容进行写保护

(注:此处也可以用tftp或bootp协议)

[ 编辑]

片外启动

[ 编辑]
如何在uboot内运行自己的程序

1)手动运行(只是将程序下载到SDRAM中运行,仅做测试之用,断电或退出后就会消失)
1>loadb 20000000 下载用户程序(*.bin) <注:必须是.bin文件,可用arm-linux-objcopy命令生成>
2>go 20000000 程序就会运行
2)自动运行(将程序写入Flash,uboot启动之后程序自动运行)
1>设置环境变量

Uboot>setenv usr_prg cp.b 10300000 20000000 ffff(程序的大小)
Uboot>setenv run_prg go 20000000
Uboot>setenv bootcmd run usr_prg/;run run_prg
Uboot>saveenv

2>写入程序,即将其烧入Flash

protect off all
erase 10300000 103fffff
loadb 20000000 下载*.bin
cp.b 20000000 10300000 ffff(用户程序的大小)

3>reset之后程序就会自动运行

[ 编辑]
烧写linux到Flash

1)下载linux到系统的SDRAM运行(仅做测试之用,断电或退出后就会消失)
1>运行Uboot,设置环境变量

Uboot>setenv bootargs root=/dev/ram rw initrd=0x21100000,6000000 ramdisk_size=15360 
console=ttyS0,115200,mem=32M 启动系统环境变量
Uboot>setenv ethaddr 12:34:56:78:99:aa mac 地址
Uboot>setenv ipaddr [目标板 ip 地址] 目标板 ip 地址
Uboot>setenv serverip [主机 ip 地址] 主机 ip 地址

2>下载linux内核,文件系统
打开tftpserver应用程序,设置根目录路径,将内核、文件系统等拷贝到所设置的根目录下。

Uboot>tftp 21100000 ramdisk.gz                     下载文件系统
Uboot>tftp 21000000 uImage 下载 linux 内核
Uboot>bootm 21000000 启动 linux

然后linux操作系统就开始运行。
2)烧写 Linux 到系统的 Flash 运行
1>设置运行Linux的环境变量

Uboot> setenv bootargs root=/dev/ram rw initrd=0x21100000,6000000  ramdisk_size=15360 console=ttyS0,115200,mem=32M   启动系统环境变量
Uboot>setenv image cp.b 10020000 21000000 b0000 拷贝内核到sdram
Uboot>setenv ramdisk cp.b 100d0000 21100000 226000 拷贝文件系统到sdram
Uboot>setenv boot bootm 设置变量boot
Uboot>setenv bootcmd run ramdisk/;run image/;run boot 设置默认变量bootcmd
Uboot>setenv ethaddr 12:34:56:78:99:aa mac 地址
Uboot>setenv ipaddr 目标板 ip 地址 目标板 ip 地址,由你自己决定
Uboot>setenv serverip 主机ip地址 主机ip地址,就是你的PC的ip
Uboot>saveenv 保存环境变量

2>烧写Linux内核到Flash

Uboot>tftp 21100000 ramdisk.gz
Uboot>cp.b 21100000 100d0000 226000
Uboot>tftp 21000000 uImage
Uboot>cp.b 21000000 10020000 b0000

reset之linux操作系统就开始运行。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值