此文档是基于at91sam9261这款CPU来进行记录的
对于移植一个自己的linux内核来说,需要下面的几个步骤:
一:首先要让系统跑起来需要一个一级启动代码,这个可以从atmel官方去下载.
# ls
AT91Bootstrap1.14.zip
二:下载纯净的linux内核,和该内核所对应的该系列CPU的补丁.
# ls -l
-rw-rw-rw- 1 root root 29127 2008-10-13 12:54 2.6.24.at91.2-exp.patch.gz
-rw-rw-rw- 1 root root 145164 2008-10-13 13:04 2.6.24-at91.patch.gz
-rw-rw-rw- 1 root root 46737783 2009-06-15 10:32 linux-2.6.24.tar.bz2
三:下载适合的交叉编译工具:
# ls -l
-rw-rw-rw- 1 root root 67481346 2009-12-15 20:25 arm-2008q1-126-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
四:下载u-boot,同时可以在atmel官方去下载u-boot的补丁
# ls -l
total 7668
-rw-rw-rw- 1 root root 111418 2009-10-23 10:08 u-boot-1.3.4-exp.3.diff
-rw-rw-rw- 1 root root 7714456 2009-05-11 09:51 u-boot-1.3.4.tar.bz2
五:下载busybox用来制作根文件系统:
# ls -l
total 1888
-rw-rw-rw- 1 root root 1924980 2010-02-23 21:10 busybox-1.11.2.tar.bz2
注:以上的我只是说明我用的文件名,具体的下载路径我没写,因为有的链接可能失效.
这样的话,有以上的文件就可以使这个linux的最小系统在这个板子上跑起来了.
接下来就是进行解压配置了:
先可以根据自己的需要建立文件夹,最好是每个文件用单独的文件夹做出来,这样利于自己看的清楚,下面是我的文件夹目录:
# ls -l
total 24
drwxr-xr-x 3 root root 4096 2010-04-09 10:53 AT91Bootstrap
drwxr-xr-x 3 root root 4096 2010-04-05 09:32 crosstool
drwxr-xr-x 3 root root 4096 2010-04-05 13:32 filesyetem
drwxr-xr-x 3 root root 4096 2010-04-05 09:41 kernel
-rw-r--r-- 1 root root 214 2010-04-05 11:59 setenv-9261
drwxr-xr-x 3 root root 4096 2010-04-05 10:32 u-boot
注意上面绿色的文件是一个脚本文件,是用来配置环境变量的.这个会在后面有所说明.
第一步:当然是配置交叉编译工具了,这个不做,你后面的东西根本就没办法在你的板子上跑起来.
# cd crosstool/
# tar -xjvf arm-2008q1-126-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
# ls
arm-2008q1
arm-2008q1-126-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
# cd arm-2008q1
# ls
arm-none-linux-gnueabi bin include lib libexec share
# cd arm-2008q1
# ls
arm-none-linux-gnueabi bin include lib libexec share
# cd bin/
# ls
arm-none-linux-gnueabi-addr2line arm-none-linux-gnueabi-g++ arm-none-linux-gnueabi-gprof arm-none-linux-gnueabi-readelf
arm-none-linux-gnueabi-ar arm-none-linux-gnueabi-gcc arm-none-linux-gnueabi-ld arm-none-linux-gnueabi-size
arm-none-linux-gnueabi-as arm-none-linux-gnueabi-gcc-4.2.3 arm-none-linux-gnueabi-nm arm-none-linux-gnueabi-sprite
arm-none-linux-gnueabi-c++ arm-none-linux-gnueabi-gcov arm-none-linux-gnueabi-objcopy arm-none-linux-gnueabi-strings
arm-none-linux-gnueabi-c++filt arm-none-linux-gnueabi-gdb arm-none-linux-gnueabi-objdump arm-none-linux-gnueabi-strip
arm-none-linux-gnueabi-cpp arm-none-linux-gnueabi-gdbtui arm-none-linux-gnueabi-ranlib
# pwd
/workdir/at91sam9261/crosstool/arm-2008q1/bin
可见进入bin目录就可以看到我们所需要的交叉编译工具.
# cd ../../..
# ls
AT91Bootstrap crosstool filesyetem kernel setenv-9261 u-boot
# vim setenv-9261
建立一个脚本文件用来配置环境变量.
#!/bin/sbin/
echo "set the at91sam9261....."
export PATH=$PATH:/workdir/at91sam9261/crosstool/arm-2008q1/bin/
rm *~
然后保存退出,这样只要运行这个脚本就可以设置好环境变量,但是只是针对于本终端,这样做有个好处就是不污染你的系统.麻烦的就是每次打开这个终端都要去执行这个脚本来配置.
# chmod +x setenv-9261
# . setenv-9261
set the at91sam9261.....
rm: cannot remove `*~': No such file or directory
# arm-none-linux-gnueabi-gcc -v
Using built-in specs.
Target: arm-none-linux-gnueabi
Configured with: /scratch/sandra/lite/src/gcc-4.2/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libgomp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --with-pkgversion=Sourcery G++ Lite 2008q1-126 --with-bugurl= --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc --with-build-sysroot=/scratch/sandra/lite/linux/install/arm-none-linux-gnueabi/libc --enable-poison-system-directories --with-build-time-tools=/scratch/sandra/lite/linux/install/arm-none-linux-gnueabi/bin --with-build-time-tools=/scratch/sandra/lite/linux/install/arm-none-linux-gnueabi/bin
Thread model: posix
gcc version 4.2.3 (Sourcery G++ Lite 2008q1-126)
这样就说明交叉编译工具的环境变量已经设置好了,可以进行下面的步骤了.
第二步:解压编译一级启动代码:
# ls
AT91Bootstrap1.14.zip
# unzip AT91Bootstrap1.14.zip
这样就在当前目录下解压了文件:
# ls
AT91Bootstrap1.14.zip Bootstrap-v1.14
现在我们可以进入解压后文件的目录进行针对自己的修改了,不过一般没必要做太大的修改,那么多代码看起来也比较头疼的!对整体架构不清楚很难做出正确的修改.
说明:因为我这个板子上面没有网卡,所以不能进行NFS文件系统这样的开发,我为了我方便,我把不用去修改的放在dataflash里面,需要修改的内核和文件系统我放在nandflash里面,这样我每次烧写就不用去重复了.
首先我对我的内存存储分配:
以下是我的存储空间的安排:
dataflash 0x8000 u-boot
nandflash 0x00000000 kernel
nandflash 0x00400000 ramdisk.gz
因为默认的地址和我这个有点冲突,所以就要对有的文件进行修改:
进入下面目录:
# pwd
/workdir/at91sam9261/AT91Bootstrap/Bootstrap-v1.14/board/at91sam9261ek/dataflash
# ls
at91sam9261ek.h dataflash_at91sam9261ek.bin dataflash_at91sam9261ek.elf dataflash_at91sam9261ek.map Makefile
修改at91sam9261ek.h
找到修改位置:
/* ******************************************************************* */
/* BootStrap Settings */
/* */
/* ******************************************************************* */
#define AT91C_SPI_PCS_DATAFLASH AT91C_SPI_PCS0_DATAFLASH /* Boot on SPI NCS0 */
#define IMG_ADDRESS 0x8400 /* Image Address in DataFlash */
#define IMG_SIZE 0x33900 /* Image Size in DataFlash */
#define MACH_TYPE 0x350 /* AT91SAM9261-EK */
#define JUMP_ADDR 0x23F00000 /* Final Jump Address */
修改为:
/* ******************************************************************* */
/* BootStrap Settings */
/* */
/* ******************************************************************* */
#define AT91C_SPI_PCS_DATAFLASH AT91C_SPI_PCS0_DATAFLASH /* Boot on SPI NCS0 */
//#define IMG_ADDRESS 0x8400 /* Image Address in DataFlash */
//#define IMG_SIZE 0x33900 /* Image Size in DataFlash */
/* ******************************************************************* */
/* Date: 20100409 */
/* Author: microcreat */
/* Modification: changed the Image Address in DataFlash */
/* and the Image Size in DataFlash */
/* ******************************************************************* */
#define IMG_ADDRESS 0x8000 /* Image Address in DataFlash */
#define IMG_SIZE 0x80000 /* Image Size in DataFlash */
#define MACH_TYPE 0x350 /* AT91SAM9261-EK */
#define JUMP_ADDR 0x23F00000 /* Final Jump Address */
然后进行编译:
修改Makefile文件:
# vim Makefile
# TODO: set this appropriately for your local toolchain
ifndef ERASE_FCT
ERASE_FCT=rm -f
endif
ifndef CROSS_COMPILE
CROSS_COMPILE=arm-none-linux-gnueabi-
endif
修改使用的交叉编译工具.
保存退出,make
# make
# ls
at91sam9261ek.h crt0_gnu.o dataflash_at91sam9261ek.elf dataflash.o div0.o main.o pmc.o string.o _udivsi3.o
at91sam9261ek.o dataflash_at91sam9261ek.bin dataflash_at91sam9261ek.map debug.o gpio.o Makefile sdramc.o udiv.o _umodsi3.o
这样就看到编译成功,然后将编译生成的"dataflash_at91sam9261ek.bin"烧人板子的dataflash里面,这样就完成了一级启动代码的烧录.
*****烧写使用samba软件,用法在后面一个单独的文章来说明.
这样就完成了基于dataflash的一级启动代码的编译工作.(烧写一级启动代码可以见另外一篇文章<
>)
第三步:解压并编译u-boot
上面进行了一级启动代码的移植,现在开始做u-boot的移植,一级启动代码里面设置了u-boot在dataflash里面的烧写地址.
打开u-boot目录,解压u-boot源代码并且打入补丁.
# ls -l
total 7668
-rw-rw-rw- 1 root root 111418 2009-10-23 10:08 u-boot-1.3.4-exp.3.diff
-rw-rw-rw- 1 root root 7714456 2009-05-11 09:51 u-boot-1.3.4.tar.bz2
# tar -xjvf u-boot-1.3.4.tar.bz2
# ls
u-boot-1.3.4 u-boot-1.3.4-exp.3.diff u-boot-1.3.4.tar.bz2
进入u-boot目录:
# cd u-boot-1.3.4
将补丁复制到u-boot目录里:
# cp ../u-boot-1.3.4-exp.3.diff .
打入atmel的补丁:
# cat u-boot-1.3.4-exp.3.diff | patch -p1
现在为止,u-boot已经打入了atmel的补丁,现在可以进行下面的编译过程了.
可以删除这个补丁文件.
# rm u-boot-1.3.4-exp.3.diff
可以看到一级启动代码中的
# ls
at91sam9261ek.h crt0_gnu.o dataflash_at91sam9261ek.elf dataflash.o div0.o main.o pmc.o string.o _udivsi3.o
at91sam9261ek.o dataflash_at91sam9261ek.bin dataflash_at91sam9261ek.map debug.o gpio.o Makefile sdramc.o udiv.o _umodsi3.o
中的at91sam9261ek.h 文件
#define JUMP_ADDR 0x23F00000 /* Final Jump Address */
和u-boot文件中的"config.mk"的地址一致.
# ls
at91sam9261ek.c at91sam9261ek.o config.mk led.c led.o libat91sam9261ek.a Makefile nand.c nand.o partition.c partition.o
# cat config.mk
TEXT_BASE = 0x23f00000
到此为止,也可以直接去编译,可以用at91am9261的默认配置,但是你可以对nandflash分为几个区,分别用来存储内核和文件系统等.
这个地址分配可以修改u-boot源码文件下的"at91sam9261ek.h"这个文件!
这个文件的目录是:
# pwd
/workdir/at91sam9261/u-boot/u-boot-1.3.4/include/configs
这个目录前面的不是绝对的,根据你自己所建立的目录为准,后面的目录才是这个文件所在的位置.
#ifdef CFG_USE_DATAFLASH_CS0
/* bootstrap + u-boot + env + linux in dataflash on CS0 */
#define CFG_ENV_IS_IN_DATAFLASH 1
#define CFG_MONITOR_BASE (CFG_DATAFLASH_LOGIC_ADDR_CS0 + 0x8400)
#define CFG_ENV_OFFSET 0x4200
#define CFG_ENV_ADDR (CFG_DATAFLASH_LOGIC_ADDR_CS0 + CFG_ENV_OFFSET)
#define CFG_ENV_SIZE 0x4200
#define CONFIG_BOOTCOMMAND "cp.b 0xC0042000 0x22000000 0x210000; bootm"
#define CONFIG_BOOTARGS "console=ttyS0,115200 " \
"root=/dev/mtdblock0 " \
"mtdparts=at91_nand:-(root) " \
"rw rootfstype=jffs2"
#elif CFG_USE_DATAFLASH_CS3
/* bootstrap + u-boot + env + linux in dataflash on CS3 */
#define CFG_ENV_IS_IN_DATAFLASH 1
#define CFG_MONITOR_BASE (CFG_DATAFLASH_LOGIC_ADDR_CS3 + 0x8400)
#define CFG_ENV_OFFSET 0x4200
#define CFG_ENV_ADDR (CFG_DATAFLASH_LOGIC_ADDR_CS3 + CFG_ENV_OFFSET)
#define CFG_ENV_SIZE 0x4200
#define CONFIG_BOOTCOMMAND "cp.b 0xD0042000 0x22000000 0x210000; bootm"
#define CONFIG_BOOTARGS "console=ttyS0,115200 " \
"root=/dev/mtdblock0 " \
"mtdparts=at91_nand:-(root) " \
"rw rootfstype=jffs2"
#else /* CFG_USE_NANDFLASH */
/* bootstrap + u-boot + env + linux in nandflash */
#define CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_OFFSET 0x60000
#define CFG_ENV_OFFSET_REDUND 0x80000
#define CFG_ENV_SIZE 0x20000 /* 1 sector = 128 kB */
#define CONFIG_BOOTCOMMAND "nand read 0x22000000 0xA0000 0x200000; bootm"
#define CONFIG_BOOTARGS "console=ttyS0,115200 " \
"root=/dev/mtdblock5 " \
"mtdparts=at91_nand:128k(bootstrap)ro," \
"256k(uboot)ro,128k(env1)ro," \
"128k(env2)ro,2M(linux),-(root) " \
"rw rootfstype=jffs2"
#endif
以上的部分可以看出每个flash里面的默认分区,应为我想把u-boot放在dataflash,我板子上的片选是cs0,所以我就可以按照我的想法去修改上面CS0的dataflash的分区信息.
修改如下:
#ifdef CFG_USE_DATAFLASH_CS0
/* bootstrap + u-boot + env + linux in dataflash on CS0 */
#define CFG_ENV_IS_IN_DATAFLASH 1
/* ******************************************************************* */
/* Date: 20100409 */
/* Author: microcreat */
/* Modification: changed the adress, */
/* keep the same of Bootstrap-v1.14/board/at91sam9261ek/*/
/* dataflash/at91sam9261ek.h! */
/* ******************************************************************* */
//#define CFG_MONITOR_BASE (CFG_DATAFLASH_LOGIC_ADDR_CS0 + 0x8400)
#define CFG_MONITOR_BASE (CFG_DATAFLASH_LOGIC_ADDR_CS0 + 0x8000)
#define CFG_ENV_OFFSET 0x4000
#define CFG_ENV_ADDR (CFG_DATAFLASH_LOGIC_ADDR_CS0 + CFG_ENV_OFFSET)
#define CFG_ENV_SIZE 0x4000
#define CONFIG_BOOTCOMMAND "cp.b 0xC0042000 0x22000000 0x210000; bootm"
#define CONFIG_BOOTARGS "console=ttyS0,115200 " \
"root=/dev/mtdblock0 " \
"mtdparts=at91_nand:-(root) " \
"rw rootfstype=jffs2"
修改这个入口地址后,然后修改分区信息:
进入下面的目录:
# pwd
/workdir/at91sam9261/u-boot/u-boot-1.3.4/board/atmel/at91sam9261ek
# ls
at91sam9261ek.c at91sam9261ek.o config.mk led.c led.o libat91sam9261ek.a Makefile nand.c nand.o partition.c partition.o
修改"partition.c"这个文件.
/*define the area offsets*/
dataflash_protect_t area_list[NB_DATAFLASH_AREA] = {
{0x00000000, 0x000041FF, FLAG_PROTECT_SET, 0, "Bootstrap"},
{0x00004200, 0x000083FF, FLAG_PROTECT_CLEAR, 0, "Environment"},
{0x00008400, 0x00041FFF, FLAG_PROTECT_SET, 0, "U-Boot"},
{0x00042000, 0x00251FFF, FLAG_PROTECT_CLEAR, 0, "Kernel"},
{0x00252000, 0xFFFFFFFF, FLAG_PROTECT_CLEAR, 0, "FS"},
};
这个是原始文件,我们可以根据自己的需要去修改:
我的修改如下:
/* ******************************************************************* */
/* Date: 20100409 */
/* Author: microcreat */
/* Modification: changed the adress, */
/* keep the same of Bootstrap-v1.14/board/at91sam9261ek/*/
/* dataflash/at91sam9261ek.h! */
/* ******************************************************************* */
/*define the area offsets*/
dataflash_protect_t area_list[NB_DATAFLASH_AREA] = {
{0x00000000, 0x00003FFF, FLAG_PROTECT_SET, 0, "Bootstrap"},
{0x00004000, 0x00007FFF, FLAG_PROTECT_CLEAR, 0, "Environment"},
{0x00008000, 0x00088000, FLAG_PROTECT_SET, 0, "U-Boot"},
{0x00088001, 0x0041FFFF, FLAG_PROTECT_CLEAR, 0, "NULL"},
};
以上修改的分区要和上面的基地址配合.
#define CFG_MONITOR_BASE (CFG_DATAFLASH_LOGIC_ADDR_CS0 + 0x8000)
#define CFG_ENV_OFFSET 0x4000
#define CFG_ENV_ADDR (CFG_DATAFLASH_LOGIC_ADDR_CS0 + CFG_ENV_OFFSET)
#define CFG_ENV_SIZE 0x4000
可以在原来的基础上修改,也可以把原来的屏蔽掉,然后自己写!
然后退回到u-boot的根目录.执行配置文件.
# make distclean
# make at91sam9261ek_config
... with environment variable in SPI DATAFLASH CS0
Configuring for at91sam9261ek board...
# make
.......好长的英文.....
arm-none-linux-gnueabi-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
arm-none-linux-gnueabi-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
# ls
api common examples lib_generic lib_sh mkconfig README u-boot.map
api_examples config.mk fs lib_i386 lib_sparc nand_spl rules.mk u-boot.srec
arm_config.mk COPYING i386_config.mk lib_m68k m68k_config.mk net sh_config.mk
avr32_config.mk cpu include lib_microblaze MAINTAINERS nios2_config.mk sparc_config.mk
blackfin_config.mk CREDITS lib_arm lib_mips MAKEALL nios_config.mk System.map
board disk lib_avr32 lib_nios Makefile onenand_ipl tools
CHANGELOG doc lib_blackfin lib_nios2 microblaze_config.mk post u-boot
CHANGELOG-before-U-Boot-1.1.5 drivers libfdt lib_ppc mips_config.mk ppc_config.mk u-boot.bin
这样就会生成上面的文件,特别是用红色标记的,u-boot.bin是可以写入到dataflash里面的文件,tools是在编译内核的时候"uImage"的工具.
我们把u-boot.bin烧入自己定义的dataflash位置,我的位置是0x8000.
烧入一级启动代码和u-boot后,打开串口终端,也就是debug口输出信息
可以看到u-boot启动了.
RomBOOT
U-Boot 1.3.4 (Apr 9 2010 - 15:58:24)
DRAM: 64 MB
NAND: 128 MiB
DataFlash:AT45DB321
Nb pages: 8192
Page Size: 528
Size= 4325376 bytes
Logical address: 0xC0000000
Area 0: C0000000 to C0003FFF (RO) Bootstrap
Area 1: C0004000 to C0007FFF Environment
Area 2: C0008000 to C0088000 (RO) U-Boot
Area 3: C0088001 to C041FFFF NULL
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
ERROR: resetting DM9000 -> not responding
dm9000 not found at 0x30000000 id: 0x2b2a2928
DM9000: Undefined IO-mode:0x3
MAC: 00:00:00:00:00:00
could not establish link
Hit any key to stop autoboot: 0
Wrong Image Format for bootm command
ERROR: can't get kernel image!
U-Boot>
到此为止,u-boot移植成功,下面开始移植linux内核了.
第四步:解压,编译linux内核
解压缩linux-2.6.24 压缩文件:
为了生成uImage 我们可以把先前设置的一个脚本文件修改为这样
# ls
AT91Bootstrap crosstool filesyetem kernel setenv-9261 u-boot
# vim setenv-9261
#!/bin/sbin/
echo "set the at91sam9261....."
export PATH=$PATH:/workdir/at91sam9261/crosstool/arm-2008q1/bin/
export PATH=$PATH:/workdir/at91sam9261/u-boot/u-boot-1.3.4/tools/
rm *~
也就是把u-boot生成的tools工具,用来编译内核.
# ls
2.6.24-at91.patch.gz COPYING Documentation MAINTAINERS README arch crypto fs init kernel mm samples security usr
2.6.24.at91.2-exp.patch.gz CREDITS Kbuild Makefile REPORTING-BUGS block drivers include ipc lib net scripts sound
# zcat 2.6.24.at91.2-exp.patch.gz | patch -p1
# zcat
2.6.24-at91.patch.gz | patch -p1
这样就打入了at91的补丁.
现在可以配置linux内核了.
# ls
2.6.24.at91.2-exp.patch.gz 2.6.24-at91.patch.gz linux-2.6.24 linux-2.6.24.tar.bz2 yaffs2.tar.gz
# cd linux-2.6.24
# ls
arch CREDITS drivers init kernel Makefile net samples sound vmlinux
block crypto fs ipc lib mm README scripts System.map vmlinux.o
COPYING Documentation include Kbuild MAINTAINERS Module.symvers REPORTING-BUGS security usr
进入linux内核目录:
# vim Makefile
linux-2.6.24 主目录下有个Makefile 文件,打开,找到185 行左右,修改
ARCH ?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi-
保存退出。
# make distclean
# make at91sam9261ek_defconfig
# make menuconfig
进入上面的选项配置:
将上图中的这2个选项要选中:
这样可以用EABI的交叉编译工具编译了.保存退出.
# make uImage
等待英文飘完,编译ok后,就可以得到内核image了.
....................
Image Name: Linux-2.6.24
Created: Fri Apr 9 16:28:41 2010
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1167608 Bytes = 1140.24 kB = 1.11 MB
Load Address: 20008000
Entry Point: 20008000
Image arch/arm/boot/uImage is ready
# cd arch/arm/boot/
# ls -l
total 4652
drwxr-xr-x 2 root root 4096 2008-01-25 06:58 bootp
drwxr-xr-x 2 root root 4096 2010-04-09 16:28 compressed
-rwxr-xr-x 1 root root 2394488 2010-04-09 16:28 Image
-rw-r--r-- 1 root root 1326 2008-01-25 06:58 install.sh
-rw-r--r-- 1 root root 2775 2008-01-25 06:58 Makefile
-rw-r--r-- 1 root root 1167672 2010-04-09 16:28 uImage
-rwxr-xr-x 1 root root 1167608 2010-04-09 16:28 zImage
这样就可以把生成的uImage烧进nandflash的对应的位置了.
这里需要注意了,因为u-boot里面没有修改环境变量,也就是说,当u-boot启动后,输入printenv,看到的信息是基于jffs2的,所以在uboot启动后需要手动的去修改环境变量.
RomBOOT
U-Boot 1.3.4 (Apr 9 2010 - 15:58:24)
DRAM: 64 MB
NAND: 128 MiB
DataFlash:AT45DB321
Nb pages: 8192
Page Size: 528
Size= 4325376 bytes
Logical address: 0xC0000000
Area 0: C0000000 to C0003FFF (RO) Bootstrap
Area 1: C0004000 to C0007FFF Environment
Area 2: C0008000 to C0088000 (RO) U-Boot
Area 3: C0088001 to C041FFFF NULL
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
ERROR: resetting DM9000 -> not responding
dm9000 not found at 0x30000000 id: 0x2b2a2928
DM9000: Undefined IO-mode:0x3
MAC: 00:00:00:00:00:00
could not establish link
Hit any key to stop autoboot: 0
U-Boot>
U-Boot>
U-Boot>
U-Boot>
U-Boot>
U-Boot>
U-Boot> printenv
bootargs=console=ttyS0,115200 root=/dev/mtdblock0 mtdparts=at91_nand:-(root) rw rootfstype=jffs2
bootcmd=cp.b 0xC0042000 0x22000000 0x210000; bootm
bootdelay=3
baudrate=115200
Environment size: 176/16892 bytes
这个我们可以手动设置,具体命令可以去看下uboot的命令:
我的设置是这样的,这个只是来验证编译的内核是不是可以启动的.
U-Boot> setenv bootcmd nand read 0x21500000 0x00000000 0x20000000\; bootm 0x21500000
U-Boot> setenv bootargs mem=64M console=ttyS0,115200 root=/dev/mtdblock0
U-Boot> saveenv
Saving Environment to dataflash...
然后重起板子,nandflash可能会有坏块,不成功的话,多重起几次.
以下是我的启动信息:
RomBOOT
U-Boot 1.3.4 (Apr 9 2010 - 17:36:14)
DRAM: 64 MB
NAND: 128 MiB
DataFlash:AT45DB321
Nb pages: 8192
Page Size: 528
Size= 4325376 bytes
Logical address: 0xC0000000
Area 0: C0000000 to C0003FFF (RO) Bootstrap
Area 1: C0004000 to C0007FFF Environment
Area 2: C0008000 to C0088000 (RO) U-Boot
Area 3: C0088001 to C041FFFF NULL
In: serial
Out: serial
Err: serial
ERROR: resetting DM9000 -> not responding
dm9000 not found at 0x30000000 id: 0x2b2a2928
DM9000: Undefined IO-mode:0x3
MAC: 00:00:00:00:00:00
could not establish link
Hit any key to stop autoboot: 0
NAND read: device 0 offset 0x0, size 0x20000000
0 bytes read: ERROR
## Booting kernel from Legacy Image at 21500000 ...
Image Name: Linux-2.6.24
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1167608 Bytes = 1.1 MB
Load Address: 20008000
Entry Point: 20008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux............................................................................. done, booting the kernel.
Linux version 2.6.24 () (gcc version 4.2.3 (Sourcery G++ Lite 2008q1-126)) #1 Fri Apr 9 16:28:34 HKT 2010
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
Machine: Atmel AT91SAM9261-EK
Ignoring unrecognised tag 0x54410008
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 198 MHz, master 99 MHz, main 18.432 MHz
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: mem=64M console=ttyS0,115200 root=/dev/mtdblock0
AT91: 96 gpio irqs in 3 banks
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
console [ttyS0] enabled
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 62464KB available (2112K code, 206K data, 108K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 64 bytes
NET: Registered protocol family 16
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
Time: pit clocksource has been installed.
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NetWinder Floating Point Emulator V0.97 (double precision)
io scheduler noop registered
io scheduler anticipatory registered (default)
atmel_lcdfb atmel_lcdfb.0: backlight control is not available
atmel_lcdfb atmel_lcdfb.0: 150KiB frame buffer at 23cc0000 (mapped at ffc00000)
atmel_lcdfb atmel_lcdfb.0: fb0: Atmel LCDC at 0x00600000 (mapped at c480c000), irq 21
atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
ssc ssc.1: Atmel SSC device at 0xc4810000 (irq 15)
dm9000 Ethernet Driver
dm9000: read wrong id 0x2b2a2928
dm9000: read wrong id 0x2b2a2928
dm9000: wrong id: 0x2b2a2928
dm9000: not found (-19).
Driver 'sd' needs updating - please use bus_type methods
NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit)
AT91 NAND: 8-bit, Software ECC
Scanning device for bad blocks
Creating 3 MTD partitions on "at91_nand":
0x00000000-0x00400000 : "Bootstrap"
0x00400000-0x04000000 : "Partition 1"
0x04000000-0x08000000 : "Partition 2"
atmel_spi atmel_spi.0: Atmel SPI Controller at 0xfffc8000 (irq 12)
usbmon: debugfs is not available
at91_ohci at91_ohci: AT91 OHCI
at91_ohci at91_ohci: new USB bus registered, assigned bus number 1
at91_ohci at91_ohci: irq 20, io mem 0x00500000
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
udc: at91_udc version 3 May 2006
mice: PS/2 mouse device common for all mice
input: gpio-keys as /class/input/input0
ads7846 spi0.2: touchscreen, irq 29
input: ADS784x Touchscreen as /class/input/input1
rtc-at91sam9 at91_rtt.0: rtc core: registered at91_rtt as rtc0
rtc-at91sam9 at91_rtt.0: rtc0: SET TIME!
i2c /dev entries driver
i2c-gpio i2c-gpio: using pins 39 (SDA) and 40 (SCL)
at91sam9_wdt: invalid timeout (must be between 1 and 16)
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
rtc-at91sam9 at91_rtt.0: hctosys: unable to read the hardware clock
List of all partitions:
1f00 4096 mtdblock0 (driver?)
1f01 61440 mtdblock1 (driver?)
1f02 65536 mtdblock2 (driver?)
No filesystem could mount root, tried: ext2 cramfs vfat
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,0)
停在这里是因为没有文件系统,所以下一步就是制作根文件系统,也是最后一步!不过以上信息表明内核是启动起来了!内核的移植基本成功!
第五步:根文件系统的建立
一般采用busybox来制作根文件系统,这个busybox根据我的实验,和交叉编译工具的版本要配合好,不然制作出来的文件系统可能要有问题.
我的busybox版本和交叉编译工具的版本如下:
# ls
busybox-1.11.2.tar.bz2
# ls
arm-2008q1-126-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
我的这个例子是这个配置.
因为在上面的步骤已经设置好交叉编译工具了,所以剩下的工作就是来对busybox进行配置了.
# tar -xjvf busybox-1.11.2.tar.bz2
# ls
busybox-1.11.2 busybox-1.11.2.tar.bz2
# ls
applets Config.in docs findutils libbb Makefile miscutils procps selinux TODO
arch console-tools e2fsprogs include libpwdgrp Makefile.custom modutils README shell TODO_config_nommu
archival coreutils editors init LICENSE Makefile.flags networking runit sysklogd util-linux
AUTHORS debianutils examples INSTALL loginutils Makefile.help printutils scripts testsuite
# # vim Makefile
...................................................................................
ROSS_COMPILE specify the prefix used for all executables used
# during compilation. Only gcc and related bin-utils executables
# are prefixed with $(CROSS_COMPILE).
# CROSS_COMPILE can be set on the command line
# make CROSS_COMPILE=ia64-linux-
# Alternatively CROSS_COMPILE can be set in the environment.
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
CROSS_COMPILE ?= arm-none-linux-gnueabi-
# bbox: we may have CONFIG_CROSS_COMPILER_PREFIX in .config,
# and it has not been included yet... thus using an awkward syntax.
ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE := $(shell grep ^CONFIG_CROSS_COMPILER_PREFIX .config 2>/dev/null)
CROSS_COMPILE := $(subst CONFIG_CROSS_COMPILER_PREFIX=,,$(CROSS_COMPILE))
CROSS_COMPILE := $(subst ",,$(CROSS_COMPILE))
endif
# SUBARCH tells the usermode build what the underlying arch is. That is set
# first, and if a usermode build is happening, the "ARCH=um" on the command
# line overrides the setting of ARCH below. If a native build is happening,
# then ARCH is assigned, getting whatever value it gets normally, and
# SUBARCH is subsequently ignored.
ifneq ($(CROSS_COMPILE),)
SUBARCH := $(shell echo $(CROSS_COMPILE) | cut -d- -f1)
else
SUBARCH := $(shell uname -m)
endif
SUBARCH := $(shell echo $(SUBARCH) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
ARCH ?= arm
...................................................................................
如果不想怎么麻烦,可以直接在命令行加上参数;
# make
CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm menuconfig
# make CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm
# make CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm install
设置交叉编译工具.
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs)
先就配置这个,先把最小系统跑起来!
现在可以直接编译了.
# make
# make install
# ls _install/
bin linuxrc sbin usr
可以看到生成了常用的命令等.
现在自己建立一个目录树,按照文件系统的要求:
为了方便,我把步骤都写成一个脚本了,如果对脚本不熟悉的话,可以按照脚本里面的步骤一步一步来.
进入你所要建立文件目录树的目录,下面是我的目录:
# ls
busybox-1.11.2 busybox-1.11.2.tar.bz2
# vim mk_roofs
#!/bin/bash
mkdir rootfs
cd rootfs
mkdir boot etc home proc tmp var dev mnt root sys
cd etc
mkdir init.d
cd ..
cd dev
mknod console c 5 1
mknod null c 1 3
cd ../..
ls
上面的基本的文件夹,还需要对etc下面进行修改!
# . mk_rootfs
运行这个脚本
# ls
busybox-1.11.2 busybox-1.11.2.tar.bz2 mk_roofs rootfs
建立lib文件,然后将交叉编译工具的lib文件复制过来
# mkdir lib
# cp -a ../../crosstool/arm-2008q1/arm-none-linux-gnueabi/libc/armv4t/lib/* lib/
# cd lib/
# ls
ld-2.5.so libcrypt-2.5.so libm.so.6 libnss_hesiod-2.5.so libresolv-2.5.so
ld-linux.so.3 libcrypt.so.1 libnsl-2.5.so libnss_hesiod.so.2 libresolv.so.2
libanl-2.5.so libc.so.6 libnsl.so.1 libnss_nis-2.5.so librt-2.5.so
libanl.so.1 libdl-2.5.so libnss_compat-2.5.so libnss_nisplus-2.5.so librt.so.1
libBrokenLocale-2.5.so libdl.so.2 libnss_compat.so.2 libnss_nisplus.so.2 libSegFault.so
libBrokenLocale.so.1 libgcc_s.so libnss_dns-2.5.so libnss_nis.so.2 libthread_db-1.0.so
libc-2.5.so libgcc_s.so.1 libnss_dns.so.2 libpcprofile.so libthread_db.so.1
libcidn-2.5.so libm-2.5.so libnss_files-2.5.so libpthread-2.5.so libutil-2.5.so
libcidn.so.1 libmemusage.so libnss_files.so.2 libpthread.so.0 libutil.so.1
然后将busybox制作的文件复制过来.
# cd ..
# ls
boot dev etc home lib mnt proc root sys sysconfig tmp var
# cp -a ../busybox-1.11.2/_install/* .
# ls
bin boot dev etc home lib linuxrc mnt proc root sbin sys tmp usr var
# cd usr/
# ls
bin sbin
可见文件已经复制过来了!
然后进入etc目录
# vim inittab
下面是内容:
::sysinit:/etc/init.d/rcS
::respawn:/bin/ash
保存退出.
然后进入init.d
# cd init.d/
# vim rcS
下面是内容:
#!/bin/sh
echo "#-----Start /etc/init.d/rcS "
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
echo "***********************************************"
echo " Start ARM..... "
echo " 2010 04 10 "
echo " microcreat "
echo "***********************************************"
然后保存,退出.
# cd ../../..
# rm rootfs.cramfs
# mkcramfs rootfs rootfs.cramfs
Directory data: 7164 bytes
Everything: 2096 kilobytes
Super block: 76 bytes
CRC: 85fce0bb
# ls
busybox-1.11.2 busybox-1.11.2.tar.bz2 mk_roofs rootfs rootfs.cramfs
这样就生成了cramfs"rootfs.cramfs"文件!
按照分配地址写入nandflash,重起板子,从终端就可以看到信息:
RomBOOT
U-Boot 1.3.4 (Apr 9 2010 - 17:36:14)
DRAM: 64 MB
NAND: 128 MiB
DataFlash:AT45DB321
Nb pages: 8192
Page Size: 528
Size= 4325376 bytes
Logical address: 0xC0000000
Area 0: C0000000 to C0003FFF (RO) Bootstrap
Area 1: C0004000 to C0007FFF Environment
Area 2: C0008000 to C0088000 (RO) U-Boot
Area 3: C0088001 to C041FFFF NULL
In: serial
Out: serial
Err: serial
ERROR: resetting DM9000 -> not responding
dm9000 not found at 0x30000000 id: 0x2b2a2928
DM9000: Undefined IO-mode:0x3
MAC: 00:00:00:00:00:00
could not establish link
Hit any key to stop autoboot: 0
NAND read: device 0 offset 0x0, size 0x20000000
0 bytes read: ERROR
## Booting kernel from Legacy Image at 21500000 ...
Image Name: Linux-2.6.24
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1165092 Bytes = 1.1 MB
Load Address: 20008000
Entry Point: 20008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux............................................................................. done, booting the kernel.
Linux version 2.6.24 () (gcc version 4.2.3 (Sourcery G++ Lite 2008q1-126)) #1 Sat Apr 10 09:46:40 HKT 2010
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
Machine: Atmel AT91SAM9261-EK
Ignoring unrecognised tag 0x54410008
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 198 MHz, master 99 MHz, main 18.432 MHz
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: mem=64M noinitrd console=ttyS0,115200 init= nuxrc root=/dev/mtdblock2 rootfstype=cramfs
AT91: 96 gpio irqs in 3 banks
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
console [ttyS0] enabled
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 62464KB available (2112K code, 206K data, 108K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 64 bytes
NET: Registered protocol family 16
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
Time: pit clocksource has been installed.
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NetWinder Floating Point Emulator V0.97 (double precision)
io scheduler noop registered
io scheduler anticipatory registered (default)
atmel_lcdfb atmel_lcdfb.0: backlight control is not available
atmel_lcdfb atmel_lcdfb.0: 150KiB frame buffer at 23cc0000 (mapped at ffc00000)
atmel_lcdfb atmel_lcdfb.0: fb0: Atmel LCDC at 0x00600000 (mapped at c480c000), irq 21
atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
ssc ssc.1: Atmel SSC device at 0xc4810000 (irq 15)
dm9000 Ethernet Driver
dm9000: read wrong id 0x2b2a2928
dm9000: read wrong id 0x2b2a2928
dm9000: wrong id: 0x2b2a2928
dm9000: not found (-19).
Driver 'sd' needs updating - please use bus_type methods
NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit)
AT91 NAND: 8-bit, Software ECC
Scanning device for bad blocks
Creating 4 MTD partitions on "at91_nand":
0x00000000-0x00800000 : "Bootstrap"
0x00800000-0x01c00000 : "ramdisk"
0x01400000-0x03200000 : "cramfs"
0x04000000-0x08000000 : "file"
atmel_spi atmel_spi.0: Atmel SPI Controller at 0xfffc8000 (irq 12)
usbmon: debugfs is not available
at91_ohci at91_ohci: AT91 OHCI
at91_ohci at91_ohci: new USB bus registered, assigned bus number 1
at91_ohci at91_ohci: irq 20, io mem 0x00500000
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
udc: at91_udc version 3 May 2006
mice: PS/2 mouse device common for all mice
input: gpio-keys as /class/input/input0
ads7846 spi0.2: touchscreen, irq 29
input: ADS784x Touchscreen as /class/input/input1
rtc-at91sam9 at91_rtt.0: rtc core: registered at91_rtt as rtc0
rtc-at91sam9 at91_rtt.0: rtc0: SET TIME!
i2c /dev entries driver
i2c-gpio i2c-gpio: using pins 39 (SDA) and 40 (SCL)
at91sam9_wdt: invalid timeout (must be between 1 and 16)
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
rtc-at91sam9 at91_rtt.0: hctosys: unable to read the hardware clock
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 108K
init started: BusyBox v1.11.2 (2010-04-10 10:18:23 HKT)
starting pid 735, tty '': '/etc/init.d/rcS'
#-----Start /etc/init.d/rcS
***********************************************
Start ARM.....
2010 04 10
microcreat
***********************************************
starting pid 736, tty '': '/bin/ash'
/bin/ash: can't access tty; job control turned off
# ls
bin dev home linuxrc proc sbin tmp var
boot etc lib mnt root sys usr
# cd /
# ls
bin dev home linuxrc proc sbin tmp var
boot etc lib mnt root sys usr
# cd etc/
# ls
init.d inittab
可以看到内核基本已经启动起来!但是这个只是最基本的!还需要进一步完善!不过这样可以给一个大致的认识!至少liunx已经跑起来了!以后的工作就是在这个上面去进行了!