基于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)应用程序开发。
图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接口连接。使用工作站上的超级终端作为嵌入式目标系统输入/输出端。
对于开发流程有了一定的了解后就有了目标,这样才能够不是太郁闷。
我的开发环境: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
一、了解一下存储器的基本分类情况。
存储器的物理实质是一组或多组具备数据输入输出和数据存储功能的集成电路,用于充当设备缓存或保存固定的程序及数据。存储器按存储信息的功能可分为只读存储器 ROM ( Read Only Memory )和随机存储器 RAM ( Random Access Memory )。
图 1 常见存储器分类
1、 ROM
ROM 中的信息一次写入后只能被读出,而不能被操作者修改或删除,一般由芯片制造商进行掩膜写入信息,价格便宜,适合于大量的应用。一般用于存放固定的程序,如监控程序、汇编程序等,以及存放各种表格。 EPROM ( Erasable Programmable ROM )和一般的 ROM 不同点在于它可以用特殊的装置擦除和重写它的内容,一般用于软件的开发过程。
特别介绍:闪存(Flash Memory )
闪速存储器(Flash Memory )又称PEROM (Programmable and Erasable Read Only Memory ), 是Intel 公司在80 年代末90 年代初推出的,由于它的众多优点而深受用户的青睐。Flash Memory 的两个主要特点是可以按整体/ 扇区擦除和按字节编程。它是完全非易失的,可以在线写入, 并且可以按页连续字节写入, 读出速度高。Flash 芯片划分成很多扇区,把一位从0 重置为1 不能通过对该位单独操作来实现,而必须擦除整个扇区。Flash 芯片的寿命就用擦除周期来衡量。通常的寿命为每个扇区可擦除100 ,000 次。为了避免任意一个扇区在其他扇区之前达到这个极限,大多数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-RAM 同 DRAM 相似,但在把数据发送给 CPU 的同时可以去访问下一个页面,故而速度要比普通 DRAM 快 15~30% 。 SDRAM 同 DRAM 有很大区别,它使用同一个 CPU 时钟周期即可完成数据的访问和刷新,即以同一个周期、相同的速度、同步的工作,因而可以同系统总线以同频率工作,可大大提高数据传输率,其速度要比 DRAM 和 EDO-RAM 快很多(比 EDO-RAM 提高近 50% )。
二、AT91RM9200 开发板的存储器情况
第一 级 地址 译码 由 存 储 控制器 执 行, 即 由 具 有附加功能的高 级 系 统总线 (ASB) 执 行 。 译码将 4G 的 地址空 间 分 为 16 个 256M 字 节 的 区 域。 区 域 1 ~ 8 对应 EBI , 和 外部片 选 NC0 ~ NCS7 相 联 系 。 区 域 0 为内 部存 储 器 地址 ,第二 级译码 提供 1M 字 节内 部存 储 空 间 。 区 域 15 为 外 设 地址 , 且 提供 对 高 级 外 设总线 (APB) 的 访问 。其 它区 域未 使用,使用 它们进 行 访问时将 向 发 出 访问请 求 的主机 发 出 异 常 中 断 。 注意,地址的转换都是按照字节为单位的。
1 、内部存储器映射
内部 ROM : AT91RM9200 集成了一 个 128-K 字 节 的 内 部 ROM 。 任何 时 候 , ROM 均 被 映射到地址 0x10 0000 。若 复 位 时 BMS 为 高, 则 在 复 位 后到重新映射命 令 执 行 前 ,可 访问 地址 0x0 。 ROM 容量为 128KB ,即对应 0x20000 。所以范围为 0x100000 - 0x120000 。
内 部 RAM : AT91RM9200 集成了高速, 16-K 字 节 的 内 部 SRAM 。 复 位 后到重新映射命 令 执 行 前 , 只 可 访问 SRAM 中 0x20 0000 的 地址空 间 。重新映射后 , SRAM 在地址 0x0 同 样 有 效。 SRAM 容量为 16KB ,即对应 0x4000 ,所以范围为 0x200000 - 0x204000 。
USB 主机端口 : AT91RM9200 集成了一 个 USB 主机端口 开 放 主机控制器接口 (OHCI) 。 ASB 可 直 接 访问该 接口 寄 存器, 且 同 标 准 内 部存 储 器一 样 映射到地址 0x30 0000 。
图 2 内部存储器映射
2 、外部存储器映射
图3 外部存储器映射
嵌入式存储设备通常主要是RAM 和作为永久存储媒质的Flash 。
现在所用的AT91RM9200 开发板所用的SDRAM 是HY57V281620HCT -H ,其容量为4banks ×2Mbits ×16 ,即128Mbits =16Mbytes 。SDRAM 共有两片HY57V281620HCT -H ,所以SDRAM 容量为32MB 。
现在所用的Flash 芯片为Intel 的28F640J3 ,容量为8MB ,地址映射从0x10000000 到0x10800000 。现在将Flash 分为64 个扇区,每个扇区为128KB =0x20000 ,每个扇区分为两个擦除块,为64KB =0x10000 。
-------------------------------------------------------------------
Chip Select 0 ――Flash (0x1000 0000 -0x1FFF 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 扇区)
u-boot 环境变量 Flash
-------------------------------------------------------------------
Chip Select 1 ――SDRAM (0x2000 0000 -0x2200 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->
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮