基于ATMEL AT91RM9200的嵌入式Linux移植笔记

2019-07-13 02:21发布

  2006-08-10   前面利用开发板带的现成的东西step by step让Linux 2.4.19在开发板上跑起来了,对于开发的流程也有了一定的认识。现在想对每一步进行详细深入的探讨,好好学习一下,把笔记记录下来,省得忘记了。有些内容是从看过的书中摘要过来的,大部分是自己实践后的心得。我想记得详细点,也好为后面总结打好基础。 先谈一下对于嵌入式开发流程和嵌入式开发环境拓扑结构的认识。 刚开始比较盲目,看得书也不多,现在才算是大体上有了些了解。从开发产品的角度简单的描述如下: 一、嵌入式开发流程简介
假设我们现在进行一项嵌入式开产品的开发,比如说智能电力系统终端,那么我想首先应该对完整的开发流程有一个大致的了解,才不致于在以后的工作中被动。下面对嵌入式linux开发简单的介绍一下。
1、系统的需求分析 
2、硬件平台的选择和设计
3、软件开发
(3-1)建立开发环境。
(3-2)引导装载程序。
(3-3)内核裁减与编译。
(3-4)建立文件系统。
(3-5)应用程序开发。 
060810123611.jpg 图1 因为我想要做的是软件开发,所以对前两步就不作深入探索了。只想要对软件开发的每一步熟悉起来,让我定制的系统跑得稳定,开发的程序能很好的完成其功能。这是个很艰巨的任务,万里长征刚刚走了第一步:) 二、嵌入式开发环境拓扑结构简介
嵌入式开发环境一般由:宿主机(Linux Server)、工作站、嵌入式目标系统(target board)和将它们连在一起的网络环境。
1、linux server:嵌入式linux内核编译、应用程序编译的公共平台,有单独的一台pc机充当,安装标准的linux操作系统,比如redhat,debian等等。
2、工作站:为普通局域网计算机,以支持小组项目开发。工作站一般安装windows,需要linux服务器时,可以从工作站远程登陆到linux server。
3、target board:这是需要开发的最终产品,可以根据需要与工作站连接(通常通过串口或者usb接口),或连至局域网。
4、工作站需要安装ftp客户端(cuteftp、flashfxp等)和telnet客户端程序(secureCRT等),linux服务器应该开通ftp和telnet服务,还有ssh。
综述过程:开发人员在一台工作站进行操作,通过远程登陆的方式操作linux server,并且使用ftp在linux server和工作站进行文件传输,同时target board需要与网络连接,其串口与工作站的RS232接口连接。使用工作站上的超级终端作为嵌入式目标系统输入/输出端。
060810130246.jpg 对于开发流程有了一定的了解后就有了目标,这样才能够不是太郁闷。 我的开发环境:Windows XP SP2+VMWARE+RedHat 9.0 首先规划一下,我先建立了一个用户armlinux,我的全部工作都是在这个用户根目录下完成。 $pwd /home/armlinux $mkdir bootloader debug images software source kernel rootfiles sysapps tmp tools program $ls bootloader  images  program    software  sysapps  tools
debug       kernel  rootfiles  source    tmp
然后建立环境变量,直接在.bash_profile中改就可以了。 # .bash_profile   # Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi
  # User specific environment and startup programs
export TARGET=arm-linux
export PRJROOT=/home/armlinux
export PREFIX=${PRJROOT}/tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=$PATH:$HOME/bin:$PREFIX/bin:/sbin:/usr/sbin:/usr/local/sbin
  unset USERNAME 这样在下一次进入此用户时,环境变量就生效了。如果想立刻生效,那么可以用下面的命令:$source .bash_profile。这种方法可以使这些环境变量在进入用户armlinux后就会成效,比较方便。   三、建立交叉编译环境 这一步工作我已经很顺利的完成了。刚开始时,手动建立交叉编译工具链,很困难,出现了很多问题,幸亏网上有不少的资料可以参考。关于手动建立交叉编译工具链的过程我已经做了总结,放到blog上了。现在可以获得已经编译好的工具链,这样比较方便些,毕竟几个小时的手动建立过程太繁琐,太容易出错了。 3.1 获取交叉编译工具链 网站:http://www.arm.linux.org.uk 在linux server上以ftp方式登陆: #ftp ftp.arm.linux.org.uk 这是系统提示输入用户名和密码,不要随便输,那样可能会连接失败。该ftp站点是允许匿名访问的,所以你可以用下面的用户名:anonymous登陆,密码无,直接回车就可以了。 进入后执行: ftp>cd pub/armlinux/toolchain/ ftp>bin ftp>get cross-2.95.3.tar.bz2 ftp>get cross-3.0.tar.bz2 ftp>get cross-3.2.tar.bz2 ftp>get README ftp>bye Linux 2.4.xx及其以下的内核源码用2.95.3的交叉编译器来编译就可以了;而2.6.xx的内核源码一般要用到cross-3.x以上的版本来编译。所以我全都下载下来了,备用。要想用更新的版本,则可以到网站ftp://ftp.handhelds.org/projects/toolchain下载,这里可以下在到cross-3.3.2和cross-3.4.1,默认路径是/usr/local/arm/<版本号>。 从手动编译就可以知道,根据环境变量PREFIX指定了安装目标文件夹,那么上面提供的编译好的工具链也必须安装到指定的文件夹才可以使用。可以在README中知道安装方法: This works for both gcc-2.95.3 and gcc-3.0.
How to install:   cd /usr/local
  mkdir arm
  cd arm
  tar Ixvf cross-.tar.bz2
Add /usr/local/arm//bin to your path to use the cross compiler. 在Linux下面要养成看README、INSTALL文件的习惯,虽然是英文,但是写得都比较具体,比较简洁,没有很困难的。 明确了方法就比较简单了。 #mkdir /usr/local/arm #cd /usr/local/arm #tar jxvf cross-2.95.3.tar.bz2 然后添加路径: $cd $ls -a $vi .bash_profile # .bash_profile # Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi
# User specific environment and startup programs
export TARGET=arm-linux
export PRJROOT=/home/armlinux
export PREFIX=${PRJROOT}/tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=$PATH:$HOME/bin:$PREFIX/bin:/usr/local/arm/2.95.3/bin:/sbin:/usr/sbin:/usr/local/sbin
unset USERNAME 看见红 {MOD}的行就是修改好的。只需要把你的路径添加到后面就可以了。 这样可以验证一下了。 验证: $cd $cd program $vi hello.c ------------------------------------------- #include int main()
{
        int i;
        for(i=1;i<9;i++)
                printf("Hello World %d times!/n",i);
}
-------------------------------------------- 保存后退出。 $arm-linux-gcc hello.c -o hello-arm $file hello-arm hello-arm: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped 这就说明生成的hello-arm是可以工作在ARM平台上的,也证明了你的交叉编译工具链是有效并且可用的。 在下载的2.95.3的工具链中没有包含调试工具gdb和目标板的gdbserver。在这里一起搭建好。 首先从ftp://ftp.gnu.org/gnu/gdb中获得gdb套件。解压缩关于路径就不多说了。 $cd $cd debug $mkdir build-gdb build-gdbserver $cd $cd software $../source/gdb-5.2.1/configure --target=$TARGET --prefix=$PREFIX $make $make install 这样就可以顺利的完成gdb-5.2.1的安装了。 要想对目标板进行交叉编译,gdb显得太大了些,所以需要gdbserver。下面建立gdbserver。 $cd $cd debug/build-gdbserver $chmod +x ../../software/gdb-5.2.1/gdb/gdbserver/configure $CC=arm-linux-gcc ../../software/gdb-5.2.1/gdb/gdbserver/configure --host=$TARGET --prefix=$TARGET_PREFIX $make $make install n=`echo gdbserver | sed 's,x,x,'`; /
if [ x$n = x ]; then n=gdbserver; else true; fi; /
/usr/bin/install -c gdbserver /home/armlinux/tools/arm-linux/bin/$n; /
/usr/bin/install -c -m 644 ../../software/gdb-5.2.1/gdb/gdbserver/gdbserver.1 /home/armlinux/tools/arm-linux/man/man1/$n.1
/usr/bin/install: 无法创建一般文件‘/home/armlinux/tools/arm-linux/bin/gdbserver’: 没有那个文件或目录
/usr/bin/install: 无法创建一般文件‘/home/armlinux/tools/arm-linux/man/man1/gdbserver.1’: 没有那个文件或目录
make: *** [install-only] Error 1
此处错误不难理解,主要是因为交叉编译工具放到/usr/local/arm里面了。前面的安装目录tools里面缺少几个文件夹,只需要建立就可以了。 $cd $PRJROOT/tools $mkdir arm-linux $cd arm-linux $mkdir bin man $cd man $mkdir man1 $cd $PRJROOT/debug/build-gdbserver $make install 这样就没有问题了,当然也可以修改makefile,但是自己还没有学好shell语言,所以采取上述方法解决了。这样首先用strip处理一下,目的是gdbserver不需要附带上调试的信息,把它们都剥离去就是了。 $arm-linux-strip $TARGET_PREFIX/bin/gdbserver $ls -l $TARGET_PREFIX/bin/ 总用量 24
-rwxr-xr-x    1 armlinux armlinux    23132  8月 10 11:33 gdbserver
也就是说,gdbserver经过strip处理之后还剩下23KB多一点,已经挺小了,适合目标板了。 附: 在CU论坛上看到tree工具可以查看目录树,觉得不错。也想要安装一个。 $cd $cd source $ftp mama.indstate.edu
Connected to mama.indstate.edu (139.102.70.201).
220 ProFTPD 1.3.0 Server (ProFTPD Default Installation) [139.102.70.201]
Name (mama.indstate.edu:armlinux): anonymous
331 Anonymous login ok, send your complete email address as your password.
Password:
230 Anonymous access granted, restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd linux/tree
250 CWD command successful
ftp> ls
227 Entering Passive Mode (139,102,70,201,149,53).
150 Opening ASCII mode data connection for file list
drwxr-xr-x   2 root     root         4096 Jun  4  2001 binary
drwxr-xr-x   2 root     root         4096 May 19  1999 slack
-rw-r--r--   1 root     root          406 Oct 11  1996 tree-1.1.lsm
-rw-r--r--   1 root     root        13135 Oct 11  1996 tree-1.1.tgz
-rw-r--r--   1 root     root          405 Jan  6  1997 tree-1.2.lsm
-rw-r--r--   1 root     root        16362 Jan  6  1997 tree-1.2.tgz
-rw-r--r--   1 root     root          436 Feb 21  2002 tree-1.3.lsm
-rw-r--r--   1 root     root        25060 Feb 21  2002 tree-1.3.tgz
-rw-r--r--   1 root     root          432 Feb 21  2002 tree-1.4b1.lsm
-rw-r--r--   1 root     root        27536 Feb 21  2002 tree-1.4b1.tgz
-rw-r--r--   1 root     root        27891 Mar 25  2002 tree-1.4b2.tgz
-rw-r--r--   1 root     root          432 Jun 18  2003 tree-1.4b3.lsm
-rw-r--r--   1 root     root        29366 Feb  6  2003 tree-1.4b3.tgz
-rw-r--r--   1 root     root          466 Aug 20  2004 tree-1.5.0.lsm
-rw-r--r--   1 root     root        26543 Aug 16  2004 tree-1.5.0.tgz
226 Transfer complete.
ftp> get tree-1.5.0.tgz
ftp> bye 221 Goodbye. $mv tree-1.5.0.tgz tree-1.5.0.tar.gz $cd ../software $tar xvzf ../source/tree-1.5.0.tar.gz $make $make install 然后就可以了,安装路径查看makefile文件知道在/usr/local/bin,也可以用which查看。现在可以用tree命令来查看一下自己的目录结构了。 示例: $cd $tree -L 1     //显示一级目录,当然也可以显示二级目录了。 .
|-- bootloader
|-- debug
|-- images
|-- kernel
|-- program
|-- rootfiles
|-- software
|-- source
|-- sysapps
|-- tmp
`-- tools
这样对自己的组织比较好。等用tree熟悉了,在补充它的用法。 四、引导装载程序bootloader 因为u-boot的功能比较强大,所以选择了u-boot。这几天想先研究研究它的代码,好好分析一下启动过程。原来做过一次,不过是利用原来开发板做好的,熟悉过程是可以,但是不明白原理仍然不行。这次要学习掌握原理部分。 待续。。。。 2006-08-14 一、了解一下存储器的基本分类情况。 存储器的物理实质是一组或多组具备数据输入输出和数据存储功能的集成电路,用于充当设备缓存或保存固定的程序及数据。存储器按存储信息的功能可分为只读存储器ROMRead Only Memory)和随机存储器RAMRandom Access Memory)。 1  常见存储器分类   060814110621.gif 1、  ROM ROM 中的信息一次写入后只能被读出,而不能被操作者修改或删除,一般由芯片制造商进行掩膜写入信息,价格便宜,适合于大量的应用。一般用于存放固定的程序,如监控程序、汇编程序等,以及存放各种表格。EPROMErasable Programmable ROM)和一般的ROM不同点在于它可以用特殊的装置擦除和重写它的内容,一般用于软件的开发过程。 特别介绍:闪存(Flash Memory 闪速存储器(Flash Memory)又称PEROMProgrammable and Erasable Read Only Memory,Intel 公司在80 年代末90 年代初推出的,由于它的众多优点而深受用户的青睐。Flash Memory 的两个主要特点是可以按整体/扇区擦除和按字节编程。它是完全非易失的,可以在线写入,并且可以按页连续字节写入,读出速度高。Flash 芯片划分成很多扇区,把一位从0 重置为1 不能通过对该位单独操作来实现,而必须擦除整个扇区。Flash芯片的寿命就用擦除周期来衡量。通常的寿命为每个扇区可擦除100000 次。为了避免任意一个扇区在其他扇区之前达到这个极限,大多数Flash 芯片用户会尽量保证擦除次数在各扇区之间均匀分布,这一过程称为“磨损均衡”(wear leveling 2、  RAM RAM 就是我们平常所说的内存,主要用来存放各种现场的输入、输出数据,中间计算结果,以及与外部存储器交换信息和作堆栈用。它的存储单元根据具体需要可以读出,也可以写入或改写。RAM 只能用于暂时存放程序和数据,一旦关闭电源或发生断电,其中的数据就会丢失。现在的RAM 多为MOS 型半导体电路,它分为静态和动态两种。静态RAM 是靠双稳态触发器来记忆信息的;动态RAM 是靠MOS 电路中的栅极电容来记忆信息的。由于电容上的电荷会泄漏,需要定时给与补充,所以动态RAM 需要设置刷新电路。但动态RAM 比静态RAM 集成度高、功耗低,从而成本也低,适于作大容量存储器。所以主内存通常采用动态RAM,而高速缓冲存储器(Cache)则使用静态RAM。动态RAM 按制造工艺的不同,又可分为动态随机存储器(Dynamic RAM)、扩展数据输出随机存储器(Extended Data Out RAM)和同步动态随机存储器(Synchromized DynamicRAM)。DRAM 需要恒电流以保存信息,一旦断电,信息即丢失。它的刷新频率每秒钟可达几百次,但由于DRAM 使用同一电路来存取数据,所以DRAM 的存取时间有一定的时间间隔,这导致了它的存取速度并不是很快。另外,在DRAM 中,由于存储地址空间是按页排列的,所以当访问某一页面时,切换到另一页面会占用CPU 额外的时钟周期。EDO-RAMDRAM 相似,但在把数据发送给CPU 的同时可以去访问下一个页面,故而速度要比普通DRAM 15~30%SDRAM DRAM 有很大区别,它使用同一个CPU 时钟周期即可完成数据的访问和刷新,即以同一个周期、相同的速度、同步的工作,因而可以同系统总线以同频率工作,可大大提高数据传输率,其速度要比DRAM EDO-RAM 快很多(比EDO-RAM提高近50%)。 二、AT91RM9200开发板的存储器情况 第一地址译码控制器行,有附加功能的高统总线(ASB) 译码将4G地址空16 256M域。1 8 对应EBI外部片NC0 NCS70为内部存地址,第二级译码提供1M节内部存15地址提供设总线(APB) 访问。其它区域未使用,使用它们进访问时将访问请的主机注意,地址的转换都是按照字节为单位的。 1、内部存储器映射 内部ROMAT91RM9200集成了一128-KROM任何ROM映射到地址0x10 0000。若BMS 高,后到重新映射命,可访问地址0x0ROM容量为128KB,即对应0x20000。所以范围为0x1000000x120000 RAMAT91RM9200集成了高速,16-K SRAM后到重新映射命访问SRAM 0x20 0000地址空。重新映射后SRAM 在地址0x0 效。SRAM容量为16KB,即对应0x4000,所以范围为0x2000000x204000 USB 主机端口AT91RM9200集成了一USB主机端口主机控制器接口(OHCI)ASB访问该接口存器,部存器一映射到地址0x30 0000 2 内部存储器映射   060814110637.gif 2、外部存储器映射 3 外部存储器映射060814110655.gif 嵌入式存储设备通常主要是RAM 和作为永久存储媒质的Flash 现在所用的AT91RM9200开发板所用的SDRAMHY57V281620HCTH,其容量为4banks×2Mbits×16,即128Mbits16MbytesSDRAM共有两片HY57V281620HCTH,所以SDRAM容量为32MB 现在所用的Flash芯片为Intel28F640J3,容量为8MB,地址映射从0x100000000x10800000。现在将Flash分为64个扇区,每个扇区为128KB0x20000,每个扇区分为两个擦除块,为64KB0x10000 ------------------------------------------------------------------- Chip Select 0――Flash0x1000 00000x1FFF FFFF 0x1000 0000(第0扇区)         boot.bin            Flash 0x1001 0000(第0扇区)         u-boot.bin.gz   Flash 0x1002 0000(第1扇区)         uImage          Flash . . . 0x1012 0000(第9扇区)         ramdisk         Flash . . . 0x107E 0000(第63扇区)         uboot环境变量 Flash ------------------------------------------------------------------- Chip Select 1――SDRAM0x2000 00000x2200 0000 0x2000 0000                     SDRAM . . 0x2100 0000         uImage      SDRAM 0x2110 0000         ramdisk     SDRAM . . ------------------------------------------------------------------- 2006-08-17  u-boot移植 1  首先,了解一下bootloader。bootloader是系统加电后运行的第一段代码。它要完成的工作就是初始化硬件设备,建立内存空间的映射图,这样为最终调用操作系统内核做好准备。 2  bootloader的操作模式 (1)启动加载模式(bootloading) (2)下载模式(downloading) 开发时要用(2),target board上的bootloader将通过串口或者网络等通信手段从host上下载内核映象和根文件系统映象等到ram中。 3  bootloader的启动方式:网络启动、磁盘启动、flash启动。 4  bootloader的种类 区分一下“bootloader”和“monitor”的概念。bootloader只是引导设备并且执行主程序的固件;而monitor还提供了更多的命令行接口,可以进行调试、读写内存、烧写flash、配置环境变量等。monitor在嵌入式系统开发过程中还可以提供很好的调试功能,开发完成后,就完全配置成了一个bootloader。所以,习惯上把它们统称为bootloader。我现在要使用的u-boot就是典型的monitor。 5  bootloader的启动流程 搜集了一些资料,写的比较精彩,放在这里。。。 资料一: 系统上电,检测BMS,选择系统的启动方式,如果BMS为高电平,则系统从片内ROM启动。AT91RM9200的ROM上电后被映射到了0x0和0x100000处,在这两个地址处都可以访问到ROM。由于9200的ROM中固化了一个BOOTLOAER程序。所以PC从0X0处开始执行这个BOOTLOAER(准确的说应该是一级BOOTLOADER)。这个BOOTLOER依次完成以下步骤:
1.              PLL SETUP
设置PLLB产生48M时钟频率提供给USB DEVICE。同时DEBUG USART也被初始化为48M的时钟频率。
2.              相应模式下的堆栈设置
3.              检测主时钟源(Main oscillator)
4.              中断控制器(AIC)的设置
5.              C 变量的初始化
6.              跳到主函数
完成以上步骤后,我们可以认为BOOT过程结束,接下来的就是LOADER的过程,或者也可以认为是装载二级BOOTLOER。
AT91RM9200按照DATAFLASH、EEPROM、连接在外部总线上的8位并行FLASH的顺序依次来找合法的BOOT程序。所谓合法的指的是在这些存储设备的开始地址处连续的存放的32个字节,也就是8条指令必须是跳转指令或者装载PC的指令,其实这样规定就是把这8条指令当作是异常向量表来处理。必须注意的是第6条指令要包含将要装载的映像的大小。关于如何计算和写这条指令可以参考用户手册。一旦合法的映像找到之后,则BOOT程序会把找到的映像搬到SRAM中去,所以映像的大小是非常有限的,不能超过16K的大小。当BOOT程序完成了把合法的映像搬到SRAM的任务以后,接下来就进行存储器的REMAP,经过REMAP之后,SRAM从映设前的0X200000地址处被映设到了0X0地址并且程序从0X0处开始执行。而ROM这时只能在0X100000这个地址处看到了。至此9200就算完成了一种形式的启动过程。如果BOOT程序在以上所列的几种存储设备中找到合法的映像,则自动初始化DEBUG USART口和USB DEVICE口以准备从外部载入映像。对DEBUG口的初始化包括设置参数115200 8 N 1以及运行XMODEM协议。对USB DEVICE进行初始化以及运行DFU协议。现在用户可以从外部(假定为PC平台)载入你的映像了。在PC平台下,以WIN2000为例,你可以用超级终端来完成这个功能,但是还是要注意你的映像的大小不能超过13K。一旦正确从外部装载了映像,接下来的过程就是和前面一样重映设然后执行映像了。我们上面讲了BMS为高电平,AT91RM9200选择从片内的ROM启动的一个过程。如果BMS为低电平,则AT91RM9200会从片外的FLASH启动,这时片外的FLASH的起始地址就是0X0了,接下来的过程和片内启动的过程是一样的,只不过这时就需要自己写启动代码了,至于怎么写,大致的内容和ROM的BOOT差不多,不同的硬件设计可能有不一样的地方,但基本的都是一样的。由于片外FLASH可以设计的大,所以这里编写的BOOTLOADER可以一步到位,也就是说不用像片内启动可能需要BOOT好几级了,目前AT91RM9200上使用较多的bootloer是u-boot,这是一个开放源代码的软件,用户可以自由下载并根据自己的应用配置。 资料2 loader.bin, boot.bin, u-boot.bin代码执行流分析.

以上三个文件时at91rm9200启动所需要的三个bin,他们的实现代码并不难。
如果是你是采用at91rm9200的评估版,应该能得到其源码。

loader.bin 执行流程,这个文件主要在片内启动从串口下载代码时会用到
loader/entry.S init cpu
b main ---> crt0.S
--> copydata --> clearbss --> b boot
main.c --> boot -->
/*Get internel rom service address*/
/* Init of ROM services structure */
pAT91 = AT91C_ROM_BOOT_ADDRESS;

/* Xmodem Initialization */
--> pAT91->OpenSBuffer
--> pAT91->OpenSvcXmodem
/* System Timer initialization */
---> AT91F_AIC_ConfigureIt
/* Enable ST interrupt */
AT91F_AIC_EnableIt
AT91F_DBGU_Printk("XMODEM: Download U-BOOT ");

Jump.S
// Jump to Uboot BaseAddr exec
Jump((unsigned int)AT91C_UBOOT_BASE_ADDRESS)

boot.bin执行流程 该文件会在从片内启动时被下载到板子上,以后还会被烧写到片外Flash中,以便在片外启动时
用它来引导并解压u-boot.bin.gz,并跳转到u-boot来执行。
boot/entry.S
b main --> crt0.S --> copydata --> clearbss --> b boot

AT91F_DBGU_Printk(" ");
AT91F_DBGU_Printk("************************************** ");
AT91F_DBGU_Printk("** Welcome to at91rm9200 ** ");
AT91F_DBGU_Printk("************************************** ");

boot/misc.s /* unzip uboot.bin.gz */
----> decompress_image(SRC,DST,LEN) --> gunzip

//jump to ubootBaseAddr exec 这里跳转到解压u-boot.bin.gz的地址处直接开始执行u-boot
asm("mov pc,%0" : : "r" (DST));

u-boot.bin执行流程
u-boot/cpu/at91rm9200/start.S
start --->reset
---> copyex ---> cpu_init_crit
---> /* set up the stack */ --> start_armboot
u-boot/lib_arm/board.c

init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup */
board_init, /* basic board dependent setup */
interrupt_init, /* set up exceptions */
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
dram_init, /* configure available RAM banks */
display_dram_config,
checkboard,
NULL,
};

---> start_armboot ---> call init_sequence
---> flash_init --> display_flash_config
---> nand_init ---> AT91F_DataflashInit
---> dataflash_print_info --> env_relocate
---> drv_vfd_init --> devices_init --> jumptable_init
---> console_init_r --> misc_init_r --> enable_interrupts
---> cs8900_get_enetaddr --> board_post_init -->

u-boot/common/main.c
for (;;)
{ /* shell parser */
main_loop () --> u_boot_hush_start --> readline
--> abortboot
-->printf("Hit any key to stop autoboot: %2d ", bootdelay);
}


以上是at91rm9200启动并进入u-boot的执行流分析。后面u-boot还会将uImage解压到特定的位置并开始执行内核代码。
6  u-boot-1.1.1的移植 自己先用u-boot-1.1.1,主要步骤如下: (1)下载u-boot-1.1.1 http://sourceforge.net/projects/u-boot (2)解压 用户:armlinux $mkdir bootloader $cd bootloader $tar jxvf ../source/u-boot-1.1.1.tar.bz2 $cd u-boot-1.1.1 (3)修改 首先看一下结构 $ tree -L 1 -d
.
|-- board  平台依赖,存放电路板相关的目录文件
|-- common  通用多功能函数的实现
|-- cpu  平台依赖,存放cpu相关的目录文件 |-- disk  通用。硬盘接口程序
|-- doc  文档
|-- drivers  通用的设备驱动程序,如以太网接口驱动
|-- dtt
|-- examples  应用例子
|-- fs  通用存放文件系统的程序
|-- include  头文件和开发板配置文件,所有开发板配置文件放在其configs里
|-- lib_arm  平台依赖,存放arm架构通用文件
|-- lib_generic  通用的库函数
|-- lib_i386  平台依赖,存放x86架构通用文件
|-- lib_m68k  平台依赖
|-- lib_microblaze  平台依赖
|-- lib_mips  平台依赖
|-- lib_nios   平台依赖
|-- lib_ppc平台依赖,存放ppc架构通用文件
|-- net  存放网络的程序
|-- post  存放上电自检程序
|-- rtc  rtc的驱动程序
`-- tools  工具
然后具体步骤为: (一)在board文件夹下面建立自己的开发板的文件夹。一般的,要选取与自己的开发板硬件设置最为接近的型号。在u-boot-1.1.1中,已经支持at91rm9200,所以可以选取at91rm9200dk作为模板进行修改。设置你的开发板的名字,随意即可,我的设置为:myboard。 [armlinux@lqm u-boot-1.1.1]$ cd board [armlinux@lqm board]$ cp -R at91rm9200dk/ myboard/
[armlinux@lqm board]$ cd myboard
[armlinux@lqm myboard]$ ls
at91rm9200dk.c  config.mk  flash.c  Makefile  u-boot.lds
(二)可以看到,这里共有5个文件。首先,要修改主文件的名字,即要把at91rm9200dk.c更改为myboard.c。其次,要更改config.mk中TEXT_BASE的数值,与loader等一级bootloader的要一致。接下来,因为在at91rm9200dk用的是AMD的flash,而我的开发板上用的是Intel的28F640J3,那么需要另外找Intel的flash.C,以减少工作量。在这里,推荐用source insight这个查看代码的工具。我是在win下面使用的,它可以很方便的读代码,并且查找调用函数等等的工作。在strong ARM构架里有xm250,它的flash是Intel的,修改的东西并不是很多。需要注意的是,xm250的flash位宽是32,而我的位宽是16,要根据这个进行相应的修改。最后,修改Makefile,主要是修改生成文件的名字。具体操作如下:
[armlinux@lqm myboard]$ mv at91rm9200dk.c myboard.c
[armlinux@lqm myboard]$ cat config.mk
TEXT_BASE = 0x21f80000
[armlinux@lqm myboard]$ vi config.mk
修改成:TEXT_BASE = 0x21f00000,然后保存退出。 [armlinux@lqm myboard]$ vi Makefile include $(TOPDIR)/config.mk LIB     = lib$(BOARD).a OBJS    := myboard.o flash.o
SOBJS   :=
$(LIB): $(OBJS) $(SOBJS)
        $(AR) crv $@ $(OBJS) $(SOBJS)
clean:
        rm -f $(SOBJS) $(OBJS)
[armlinux@lqm myboard]$ rm flash.c
[armlinux@lqm myboard]$ cp ../xm250/flash.c ./
[armlinux@lqm myboard]$ ls
config.mk  flash.c  Makefile  myboard.c  u-boot.lds
[armlinux@lqm myboard]$ vi flash.c
       34 #undef FLASH_PORT_WIDTH32   /*不定义位宽32*/
     35 #define FLASH_PORT_WIDTH16  /*定义位宽16*/
    216         switch (value) {
    217
    218         case (FPW) INTEL_ID_28F128J3A:
    219                 info->flash_id += FLASH_28F128J3A;
    220                 info->sector_count = 128;
    221                 info->size = 0x01000000;
    222                 break;                         
/* => 16 MB     */
    223
    224         case (FPW) INTEL_ID_28F640J3A:     /*就是这个芯片*/
    225                 info->