Linux系统移植

发 布 时 间 : 2008-11-17 来 源 : 未知 作 者 : 刘勇 浏 览 :
Linux系统移植


该文档的目的是总结我们在工作中的一些经验,并把它们分享给喜欢
ARM和Linux的朋友, 如有错误
之处,请大家多多指点. 同样, 我们也希望更多人能把自己的工作经验和体会加入该文档,让大家共同进步.
该文档是一份交流性文档, 只供个人学习与交流,不允许公司和企业用于商业行为.

第一部分前言

1硬件环境

1.1主机硬件环境
开发机:Pentium-4 CPU
内存: 512MB
硬盘: 60GB


1.2目标板硬件环境
CPU: S3C2410
SDRAM: HY57V561620
Nand flash: K9F1208U0B(64MB)
以太网芯片:CS8900A (10M/100MB)


1.3工具介绍
仿真器:Dragon-ICE
电缆:串口线,并口线


2软件环境

2.1主机软件环境
2.1.1 Windows操作系统
ADS编译工具:ADS1.2
仿真器软件: Dragon-ICE daemon程序


2.1.2 Linux操作系统
GNU交叉编译工具:


2.95.3:
作用:编译u-boot
3.3.2, 3.4.4:


作用:编译内核和应用程序
其它工作:



tree工具:

作用:查看文件目录树

下载:从
ftp://mama.indstate.edu/linux/tree/下载编译

2.1.3目标板最后运行的环境
启动程序:
u-boot-1.1.4
内核:
linux-2.6.14.1
应用程序:


1. busybox-1.1.3
2. TinyLogin-1.4
3. Thttpd-2.25
2.2 Linux下工作用户及环境
2.2.1交叉工具的安装
工具链的编译过程请参考第三部分.
1. 下载交叉工具
2.95.3 下载地址:ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross2.95.3.
tar.bz2
3.3.4 下载地址:
2. 编译交叉工具
[root@localhost ~]mkdir /usr/local/arm
[root@localhost ~]cd /usr/local/arm
把cross-2.95.2.tar.bz2, cross-3.4.4.tar.gz 拷贝到/usr/local/arm目录中。解压这两个包。
[root@localhost ~]tar -xjvf cross-2.95.2.tar.bz2
[root@localhost ~]tar -xzvf cross-3.4.4.tar.gz
2.2.2 u-boot移植工作目录
1. 添加工作用户
[root@localhost ~]#useradd -G root -g root -d/home/uboot uboot
2. 建立工作目录
[uboot@localhost ~]$mkdir dev_home
[uboot@localhost ~]$cd dev_home
[uboot@localhost dev_home]$mkdir doc mybootloader uboot
.
|-- doc
|-- mybootloader
`-- uboot
3. 建立环境变量
[uboot@localhost ~]vi ~/.bashrc
export PATH=/usr/local/arm/2.95.3/bin:$PATH
2.2.3内核及应用程序移植工作
1. 添加工作用户
[root@localhost ~]#useradd -G root -g root -d/home/arm arm
2. 建立工作目录

[arm@localhost arm]$mkdir dev_home
[arm@localhost arm]$cd dev_home
[arm@localhost arm]$mkdir bootldr btools debug doc images kernel localapps \
rootfs sysapps tmp tools
[arm@localhost arm]$tree -L 1
.
|-- bootldr
|-- btools
|-- debug
|-- doc
|-- images
|-- kernel
|-- localapps
|-- rootfs
|-- sysapps
|-- tmp
`-- tools


可以看到如上树形结构。

注:tree命令

3. 建立环境变量设置脚本
[arm@localhost arm]$vi env_sh
#!/bin/bash
PRJROOT=~/dev_home
KERNEL=$PRJROOT/kernel
ROOTFS=$PRJROOT/rootfs
LAPP=$PRJROOT/localapps
DOC=$PRJROOT/doc
TMP=$PRJROOT/tmp
export PRJROOT KERNEL LAPP ROOTFS
export PATH=/usr/local/arm/3.4.4/bin:$PATH


4. 登陆时启动环境变量
[arm@localhost arm]$vi ~/.bashrc
. ~/dev_home/env_sh
重新登陆
arm用户,环境变量生效
[arm@localhost arm]$su arm

2.3配置系统服务
2.3.1 tftp服务器的配置
如果用下面一条命令能够看到服务已经启动, 则不用安装, 否则需要按
1或
2点安装tftp-server服务器.
[arm@localhost arm]#netstat -a | grep tftp
udp 0 0 *:tftp *:*


1. 从
RPM包安装tftp-server
从对应Linux操作系统版本的安装光盘上找到tftp-server的安装包.
下面
tftp-server-0.32-4.i386.rpm包为例,把rpm包拷贝到dev_home/btools/下.
[arm@localhost arm]#cp tftp-server-0.32-4.i386.rpm /home/arm/dev_home/btools/
[arm@localhost arm]#su root
[root@localhost arm]#rpm -q tftp-server
如果没有安装tftp-server,就要用下面命令安装,否则,直接进入第2步配置服务.
[root@localhost arm]#cd /home/arm/dev_home/btools/
[root@localhost btools]#rpm -ivh tftp-server-0.32-4.i386.rpm



建立tftp的主工作目录
[root@localhost btools]#mkdir /tftpboot

2. 修改配置文件并启动服务
备份配置文件
[root@localhost btools]#if [ -f /etc/xinetd.d/tftp ]
> then
> cp /etc/xinetd.d/tftp /etc/xinetd.d/tftp.old
> fi


修改配置文件

[root@localhost btools]#vi /etc/xinetd.d/tftp
service tftp
{


disable = no
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
per_source = 11
cps = 100 2
flags = IPv4


}
检查
tftp服务是否打开
[root@localhost btools]#chkconfig --list
如果
tftp的服务没有打开,则用下面命令打开tftp服务开关
[root@localhost btools]#chkconfig tftp on

重启服务

#/etc/init.d/xinetd restart
#netstat -a | grep tftp
udp 0 0 *:tftp *:*


2.3.2 NFS服务器的配置
1. 安装NFS服务器
[root@localhost btools]#rpm -q nfs-utils
如果没有安装,从对应Linux操作系统版本的安装光盘上找到nfs-utils的安装包.Fedora 5中的安装包
名称为nfs-utils-1.0.8.rc2-4.FC5.2.i386.rpm。下面以该安装包为例说明:
[root@localhost btools]#rpm -ivh nfs-utils-1.0.8.rc2-4.FC5.2.i386.rpm

2. 配置NFS服务器
[root@localhost btools]#vi /etc/exports
#加入要允许被另外计算机mount的目录:
#/home/arm/dev_home/tmp 为被另外计算机mount的目录
#192.168.1.134 允许另外计算机mount的IP
#rw,sync,no_root_squash表示访问限制,更详细说明见相关手册.
/home/arm/dev_home/tmp 192.168.1.134(rw,sync,no_root_squash)

3. 启动NFS服务器
第一启动NFS服务器时用下面命令.
[root@localhost btools]#/etc/init.d/nfs start
如果你已经启动了
NFS服务器时,并且重新修改了/etc/exports文件,用如下命令使新加入的目录生效:


[root@localhost btools]#/etc/init.d/nfs reload



4. 测试NFS服务器
[root@localhost btools]#netstat -a | grep nfs
5. 显示被
export出的目录列表
[root@localhost btools]#exportfs
2.4工具使用
2.4.1 minicom的使用
1.切换到root用户.
[root@localhost btools]#su 2.
查找有效的串设备.
[root@localhost ~]#cat /proc/devices
...
4 ttyS
...
188 ttyUSB
...


如果是普通串口设备, 设备名前缀为ttyS, 第一串口为ttyS0, 第二串口为ttyS1,依次类推.
如果是
USB转串口的设备, 设备名前缀为ttyUSB, 第一串口为ttyUSB0.

3. 配置ttyUSB设备
[root@localhost ~]#minicom -s ttyUSB0
会出现一个configuration窗口,
┌──[configuration]────┐

Filenames and paths │

File transfer protocols │

Serial port setup │

Modem and dialing │

Screen and keyboard │

Save setup as ttyUSB0 │

Save setup as.. │

Exit │

Exit from Minicom │
└───────────────┘


选择Serial port setup配置. 会出现如下窗口:
┌────────────────────────────────────────────┐

A -Serial Device : /dev/ttyUSB0 │

B -Lockfile Location : /var/lock │

C -Callin Program : │

D -Callout Program : │

E -Bps/Par/Bits : 115200 8N1 │

F -Hardware Flow Control : No │

G -Software Flow Control : No │
││

Change which setting? │


└───────────────────────────────────────────┘
我的设置如上所示, 设置完成后, Change which setting?项上按回车退出当前窗口, 回到第一个窗口.按
Save
setup as ttyUSB0保存设置. 再按
Exit from Minicom退出
Minicom.

4. 启动minicom
[root@localhost ~]#minicom

3作者介绍

3.1策划,组织,指导,发布者
刘勇


email: littlegenius2008@163.com


如果您有新的内容,请发到这个电子邮件,我们会把您的内容加入文档,并在作者列表中加入您的名字.

3.2 ADS bootloader部分
作者:刘勇


email:
littlegenius2008@163.com

3.3交叉工具部分
作者:孙贺


email:
msunhe@gmail.com


3.4 uboot部分
作者:聂强


email:
wolfwind9779@yahoo.com.cn

作者:孙贺


email:
msunhe@yahoo.com.cn


3.5内核部分
作者:聂大鹏
email:dozec@mail.csdn.net
作者:牛须乐(8900a网卡移植部分)
email:clizniu@hotmail.com

3.6应用程序部分
作者:聂大鹏
email:dozec@mail.csdn.net

3.7 Nand Flash 驱动部分
作者:孙磊,刘勇
email:sunlei3448@yahoo.com.cn

第部分系统启动 bootloader的编写(ADS)
1工具介绍

1.1 ADS命令行命令介绍
1.1.1 armasm
1. 命令:armasm [选项] -o 目标文件源文件
2. 选项说明
-Errors 错误文件名
;指定一个错误输出文件
-I 目录[,目录] ;指定源文件搜索目录
-PreDefine 预定义宏
;指定预定义的宏
-NOCache ;编译源代码时禁止使用Cache进行优化
-MaxCache <n> ;编译源代码时使用Cache进行优化
-NOWarn ;关闭所有的警告信息
-G ;输出调试表
-keep ;在目标文件中保存本地符号表
-LIttleend ;生成小端(Little-endian) ARM代码
-BIgend ;生成大端(Big-endian) ARM代码
-CPU <target-cpu> ;设立目标板ARM核类型,如: arm920t.
-16 ;建立16位的thumb指令.
-32 ;建立32位的ARM指令.
3. 编译一个汇编文件

c:\adsloader>armasm -LIttleend -cpu ARM920T -32 bdinit.s
把汇编语言编译成小端, 32位, ARM920T CPU.

1.1.2 armcc, armcpp
1. 命令:armcc [选项] 源文件1 源文件2 ... 源文件n
2. 选项说明
-c ;编译但是不连接
-D ;指定一个编译时使用的预定义宏常量
-E ;仅仅对
C源文件做预处理
-g ;产生调试信息表
-I ;指头文件的搜索路径
-o<file> ;指定一个输出的目标文件
-O[0/1/2] ;指定源代码的优化级别
-S ;输出汇编代码来代替目标文件
-CPU <target-cpu> ;设立目标板ARM核类型,如: arm920t.
3.编译一个C程序

c:\adsloader>armcc -c -O1 -cpu ARM920T bdisr.c
编译不连接, 二级优化, ARM920T CPU.

1.1.3 armlink
1. 命令:armlink [选项] 输入文件
2. 选项说明
-partial ;合并目标文件

-Output 文件 ;指定输出文件名
-scatter 文件 ;按照指定的文件为可执行文件建立内存映射
-ro-base 地址值
;只读代码段的起始地址
-rw-base 地址值
;RW/ZI段的起始地址

3. 把多个目标文件合并成一个目标文件
c:\adsloader>armlink -partial bdmain.o bdport.o bdserial.o bdmmu.o bdisr.o -o
bd.o
4. 把几个目标文件编译一个可执地文件
c:\adsloader>armlink bd.o bdinit.o -scatter bdscf.scf -o bd.axf
1.1.4 fromelf
1. 命令:fromelf [选项] 输入文件
2. 选项说明
-bin 二进制文件名
;产生的二进制文件
-elf elf文件名
;产生一个elf文件
-text text文件名
;产生text文件

3. 产生一个可执行的二进制代码
c:\adsloader>fromelf.bd.axf.bin.o.bd.
bin
2基本原理

2.1可执行文件组成及内存映射
2.1.1可执行文件的组成
在ADS下,可执行文件有两种,一种是.axf文件,带有调试信息,可供AXD调试工具使用.另一种是.bin
文件,可执行的二进制代码文件。我们重点是讲描.bin文件的组成。
我们把可执行文件分为两种情况:分别为存放态和运行态。


1. 存放态
存放态是指可执行文件通过fromelf产生后,在存储介质(flash或磁盘)上的分布. 此时可执行文件一
般由两部分组成:分别是代码段和数据段。代码段又分为可执行代码段(.text)和只读数据段(.rodata),
数据段又分为初始化数据段(.data)和未初始化数据段(.bss)。可执行文件的存放态如下:


+-------------+----------|
.bss |
+-------------+--数据段
| .data |
+-------------+----------|
.rodata |
|_____________| 代码段
| .text |
+-------------+----------


2. 运行态
可执行文件通过装载过程, 搬入到RAM中运行, 这时候可执行文件就变成运行态。在ADS下对可执行代
码各段有另一个名称:
| ... |
+-------------+----------|
.bss | ZI 段
+-------------+--数据段


| .data | RW 段
+-------------+----------|
.rodata |
|_____________| 代码段(RO 段)
| .text |
+-------------+----------|
... |


装载前

当可执行文件装载后, 在RAM中的分布如下:


| ... |
+-------------+-- ZI段结束地址
| ZI 段 |
+-------------+-- ZI段起始地址
| 保留区2 |
+-------------+-- RW段结束地址
| RW 段 |
+-------------+-- RW段起始地址
| 保留区1 |
+-------------+-- RO段结束地址
| RO 段 |
+-------------+-- RO段起始地址
| ... |


装载后

所以装载过程必须完成把执行文件的各个段从存储介质上搬到RAM指定的位置。而这个装载过程由谁来完
成呢?由我们的启动程序来完成.

2.1.2装载过程
在ADS中,可以通过两种方式来指定可执行代码各段在RAM中的位置,一个是用armlink来指定,一种是
用scatter文件来指定.RAM区的起始地址:0x30000000.

1. armlink指定代码段地址
我们通常的代码,只用指定两个段开始地址, RO段的起始地址和RW段的起始地址, ZI段紧接在RW段之
后.示例见该部分的1.1.3.

2. scatter指定代码段地址
我们也可以通过scatter文件指定可执行文件各段的详细地址. Scatter文件如下:
MYLOADER.0x30000000
;MYLOADER:为可执行文件的名称,.可自定义
;0x3000000:起始地址

{
RO.0x30000000
;RO只读代码段的名称
;0x30000000:只读代码段的起始地址
{
init.o.(Init,.+First)
.....;.Init代码段为可执行文件的第一部分.


*.(+RO).;所有其它的代码段和只读数据段放在该部分
}

RW.+0


;RW:.RW段的名称


;+0:表示
RW段紧接着
RO段

{


*.(+RW).;所有RW段放在该部分
}
ZI..+0


;ZI:.ZI段的名称


;+0:表示
ZI段紧接着
RW段

{


*(+ZI).;所有ZI段放在该部分
}
}


3..ADS产生的各代码段宏
|Image$$RO$$Base|./*.RO代码段起始地址 */
|Image$$RO$$Limit|./*.RO代码段结束地址 */
|Image$$RW$$Base|./*.RW代码段起始地址 */
|Image$$RW$$Limit|./*.RW代码段结束地址 */
|Image$$ZI$$Base|./*.ZI代码段起始地址 */
|Image$$ZI$$Limit|./*.ZI代码段结束地址 */
注意:在两个$$之间的名称,.与scatter中指定的段的名称相同..

4..装载过程说明
当从
NorFlash启动时,.要把flash芯片的首地址映射到0x00000000位置,.系统启动后,.启动程序本身把自己从
flash中搬到RAM中运行..搬移后的各段起始地址,.由以上宏来确定.
当从
NandFlash启动时,.S3C2410会自动把前NandFlash的前4k搬到S3C2410的内部RAM中,并把内部
RAM的首地址设为0x00000000,CPU从
0x00000000开始执行..所以,.在nandFlash的前4k程序中,必须包含从
NandFlash把BootLoader的其余部分装入RAM的程序.


2.1.3启动过程的汇编部分
当系统启动时,.ARM.CPU会跳到0x00000000去执行。一般
BootLoader都包括如下几个部分:
1..建立中断向量异常表
2..显示的切换到SVC且
32指令模式
3..关闭S3C2410的内部看门狗
4..禁止所有的中断
5..配置系统时钟频率和总线频率
6..设置内存区的控制寄存器
7..初始化中断
8..安装中断向表量
9..把可执行文件的各个段搬到运行态的各个位置
10..跳到C代码部分执行
2.1.4启动过程的C部分
1..初始化MMU
2.初始化外部端口
3..中断处理程序表初始化
4..串口初始化

5..其它部分初始化(可选)
6..主程序循环
3 AXD的使用以及源代码说明

3.1源代码说明
3.1.1汇编源代码说明
;===============================================================================
;引用头文件
;===============================================================================


get bdinit.h

;===============================================================================
;引用标准变量
;===============================================================================


IMPORT |Image$$RO$$Base| ; Base address of RO section
IMPORT |Image$$RO$$Limit| ; End address of RO section
IMPORT |Image$$RW$$Base| ; Base address of RW section
IMPORT |Image$$RW$$Limit| ; End address of RW section
IMPORT |Image$$ZI$$Base| ; Base address of ZI section
IMPORT |Image$$ZI$$Limit| ; End addresss of ZI section

IMPORT bdmain ; The entry function of C program

;===============================================================================
;宏定义
;===============================================================================


; macro HANDLER

MACRO
$HandlerLabel HANDLER $HandleLabel

$HandlerLabel
sub sp,sp,#4 ;Decrement sp (to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack
ldr r0,=$HandleLabel;Load the address of HandleXXX to r0
ldr r0,[r0] ;Load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;Store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND

;===============================================================================
;汇编语言的入口代码
;===============================================================================


AREA Init,CODE,READONLY
CODE32

ENTRY
;=====================
; 建立中断向量表
;=====================


b reset_handler ;0x00000000: Reset (SVC)
b undef_handler ;0x00000004: Undefined instruction (Undef)
b swi_handler ;0x00000008: Software Interrupt (SVC)
b iabr_handler ;0x0000000C: Instruction Abort (Abort)
b dabr_handler ;0x00000010: Data Abort (Abort)
b no_handler ;0x00000014:
b irq_handler ;0x00000018: IRQ (IRQ)
b fiq_handler ;0x0000001C: FIQ (FIQ)
LTORG

undef_handler HANDLER HandleUndef


swi_handler HANDLER HandleSWI
iabr_handler HANDLER HandlePabort
dabr_handler HANDLER HandleDabort
no_handler HANDLER HandleReserved
irq_handler HANDLER HandleIRQ
fiq_handler HANDLER HandleFIQ

;=============================
;复位时运行的主程序
;=============================


reset_handler
;Set the cpu to SVC32 mode

mrs r0,cpsr

bic r0,r0,#0x1f

orr r0,r0,#0xd3

msr cpsr_cxsf,r0

;Turn off watchdog

ldr r0,=WTCON

ldr r1,=0x0

str r1,[r0]

;Disable all the first level interrupts


ldr r0,=INTMSK
ldr r1,=0xffffffff
str r1,[r0]

;Disable all the second level interrupts
ldr r0,=INTSUBMSK
ldr r1,=0x7ff
str r1,[r0]


;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)
str r1,[r0]


;Set FCLK:HCLK:PCLK = 1:2:4
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]


;Set memory control registers
ldrr0,=SMRDATA

 ;Fin=12MHz,Fout=200MHz



ldr r1,=BWSCON
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0

;Initialize stacks
bl InitStacks

;Setup IRQ handler
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ
str r1,[r0]

;Copy RW/ZI section into RAM
ldr r0, =|Image$$RO$$Limit|;Get pointer to ROM data
ldr r1, =|Image$$RW$$Base| ;and RAM copy
ldr r3, =|Image$$ZI$$Base|

cmp r0, r1 ; Check that they are different
beq %F2

1
cmp r1, r3 ; Copy init data
ldrcc r2, [r0], #4 ;--> LDRCC r2, [r0] + ADD r0, r0, #4
strcc r2, [r1], #4 ;--> STRCC r2, [r1] + ADD r1, r1, #4
bcc %B1

2
ldr r1, =|Image$$ZI$$Limit| ; Top of zero init segment
mov r2, #0

3
cmp r3, r1 ; Zero init
strcc r2, [r3], #4
bcc %B3

bl bdmain ;Jump to the main function

;Dead loop

1
nop
b %B1

;===============================================================================
;初始中断处理程序
;===============================================================================


IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}

ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]


str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}

;===============================================================================
;初始化各个模式下堆栈
;===============================================================================


InitStacks
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack

orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack

orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack

orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack

bic r0,r0,#MODEMASK|NOINT

orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack

mov pc,lr ;Return the call routine

LTORG

;===============================================================================
;内存区控制寄存器值表;你可根据需要修改bdinit.h文件,.下面代码不用做任何改动
;===============================================================================


SMRDATA DATA

DCD
(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(
B7_BWSCON<<28))

DCD
((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0
DCD
((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
DCD
((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
DCD
((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
DCD
((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
DCD

((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7


DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
DCD 0x32 ;SCLK power saving mode, BANKSIZE 128M/128M
DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7


ALIGN

;===============================================================================
;异常及中断向量表空间;安装异常或中断处理程序在bdisr.c中,isr_setup()来完成.
;===============================================================================


AREA RamData, DATA, READWRITE

^ _ISR_STARTADDRESS ;表示下面数据区从_ISR_STARTADDRESS指定的位置开始
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4

;=============================
;.The.Interrupt.table
;=============================


HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4


HandleRTC # 4
HandleADC # 4
END

3.1.2 C语言源代码说明
void bdmain(void)

{

/* 禁止Cache 和MMU */

cache_disable();

mmu_disable();

/* 端口初始化 */
port_init();

/* 中断处理程序 */
isr_init();

/* 串口初始化 */
serial_init(0, 115200);

/* 输出信息进行主循环 */
serial_printf("is ok!\n");
while(1) {

}
}
通常基本ADS的测试程序都可以在这个架构上加入自己的代码..

3.2 AXD的使用
3.2.1配置仿真器
1..为仿真器安装Server
一般的仿真器都对应有一个Server程序,所以在使用在线仿真之前,必须先安装这个Server程序。我使用

DragonICE
仿真器,.所以先要安装DragonICE.Server
程序。


2..连接仿真器
把dragonICE
仿真器的JTAG口连接上
ARM板(注意:ARM板要断电连接),.另一端通过并口连接到PC上,
有的仿真器是通过USB口连接到PC上,.这与仿真器的硬件相关。连接好后,.打开ARM电源,启动ARM板。
当ARM通电启动后,启动DragonICE.Server
检测ARM板,详细步骤及设置参见对应的仿真器手册。我的
dragonICE.Server
启动,.按”自动检测”可以检测到ARM920T。


3.2.2启动AXD配置开发板
1..启动AXD
先启动DragonICE.Server
程序.
按如下步聚启动AXD:
开始>
所有程序>
ARM.Developer.Suite.v1.2>
AXD.Debugger


2..装载仿真器库文件

AXD菜单的Options>
.Configure.Target...启动”Choose.Target”目标板配置窗口.
在”Choose.Target”窗口中,点击”
Add”按钮,选择仿真器的库文件..我的仿真器服务器程序安装在
c:\DragonICE
下,所以选择项
c:\DragonICE\
dragonice.
dll文件.

3..为AXD在线仿真配置仿真器
在"Target.Environments"中选中DragonICE
中,点击右边的"Configure"按钮.
在”FJB.DragonICE.Release.v1.2”
窗口点击"This.computer..."按钮,再点击"OK"按钮。
回到”Choose.Target”窗口,点击"OK"按钮。完成配置.
回到主界面,.在右边的”Target”窗口会出现
ARM920T_0.这表明AXD已经进入ARM板的在线仿真状态.
点击菜单"System.Views">"
Controls.Monitors".会出现"ARM920TRegister"
窗口.此时,会显示当前ARM板上所
有寄存器的状态。


4..配置ARM板
如果
ARM板通电后,没有程序运行并把内存区控制寄存器配置好的说,外部RAM是不能使用的..所以必须
通过仿真器来设置这些寄存器..如果
ARM板已经有启动程序并且已经配置好,.这一步可以省略.
首先把2410cfg.txt拷贝到c:\下.
回到AXD主界面,.从菜单”
System.Views”.>
.“Command.Line.Interface”。会出现一个Command.Line


Interface的调试命令行窗口,并显示如下提示符:
Debug.>
输入obey.c:\2410cfg.txt装载所有配置命令.
Debug.>obey.c:\2410cfg.txt


5..2410cfg.txt文件说明
sreg.psr,.0x00000013
;设置当前CPSR的值,.把CPU的模式切换到SVC模式和32位指令集,.关闭IRQ和FIQ。
smem.0x53000000,0,32
;设置看门狗控制寄存器WTCON
;禁止看门狗定时器

smem.0x4C000004,((0x74<<12)+(0x3<<4)+0x1),32
;设置主频率设置寄存器MPLLCON
;目前CPU的工作频率FCLK是
124.00MHz


smem.0x4C000014,0x3,32
;设置时钟分频寄存器CLKDIVN
;设置FCLK/HCLK/PCLK.的频率比例
1:2:4


smem.0x48000000,((2<<28)+(2<<24)+(1<<20)+(1<<16)+(1<<12)+(1<<8)+(1<<4)+0),32
;设置内存总线控制BWSCON
;SDRAM.BANK.6&7.is.32位
;其它
BANK.is.16位


smem.0x48000004,((3<<13)+(3<<11)+(7<<8)+(3<<6)+(3<<4)+(3<<2)+3),32
;设置寄存器区0控制寄存器:BANKCON0


smem.0x4800001c,((3<<15)+(1<<2)+1),32
;设置寄存器区6控制寄存器:.BANKCON6(SDRAM)
;RAS.to.CAS延时3.时钟周期
;列地址是
9位


smem.0x48000020,((3<<15)+(1<<2)+1),32
;设置寄存器区7控制寄存器:.BANKCON7(SDRAM)
;RAS.to.CAS延时 3.时钟周期
;列地址是
9位


smem.0x48000024,((1<<23)+(3<<18)+(2<<16)+1113),32
;set外部RAM刷新寄存器:REFRESH
;允许自刷新
;HCLK=FCLK/2,.60MHz,刷新计算器是
1113


smem.0x48000028,0x31,32



;设置寄存器的大小
;禁止burst操作
;允许
SDRAM.power.down模式
;SCLK在访问期间仍在活动状态


;SDRAM模式寄存器设置
smem.0x4800002c,0x30,32
smem.0x48000030,0x30,32


3.2.3使用AXD在线仿真调试程序
1..装载可执行的文件
AXD只支持.axf格式的可执行文件.
启动AXD,.在菜单的File中,选择Load.Image...,.选择c:\adsbloadter\prj\prj_Data\DebugRel\prj.axf加载执行
image..就可以执行并调试了..AXD提供了非常方便的调试手段,.包括在线单步,.自由设置断点等.

第三部分 GNU交叉工具链

1设置环境变量,准备源码及相关补丁

1.1设置环境变量
[arm@localhost arm]#vi.~/.bashrc
export.PREFIX=/usr/local/arm/3.4.4
export.TARGET=armlinux
export.SYSROOT=${PREFIX}/sysroot
export.ARCH=arm
export.CROSS_COMPILE=${TARGET}export.PATH=${
PREFIX}/bin:$PATH
export.SRC=/home/arm/dev_home/btools/tchain3.4.4


1. 2准备源码包
1.2.1 binuils
名称:binutils2.16.
tar.gz
下载地址:http://ftp.gnu.org/gnu/binutils/binutils2.16.
tar.gz


1.2.2 gcc
名称:gcc3.4.4.
tar.bz2
下载地址:http://ftp.gnu.org/gnu/gcc/gcc3.4.4/
gcc3.4.4.
tar.bz2


1.2.3 glibc
名称:glibc2.3.5.
tar.gz
glibclinuxthreads2.3.5.
tar.gz
下载地址:
http://ftp.gnu.org/gnu/glibc/glibc2.3.5.
tar.gz
http://ftp.gnu.org/gnu/glibc/glibclinuxthreads2.3.5.
tar.gz


1.2.4 linux kernel
名称:linux2.6.14.1.
tar.gz



下载地址:
http://ftp.kernel.org/pub/linux/kernel/v2.6/linux2.6.14.1.
tar.gz


1.3准备补丁
1.3.1 ioperm.c.diff
作用:打修正
ioperm()函数.
下载地址:http://frank.harvard.edu/~coldwell/toolchain/ioperm.c.diff


1.3.2 flow.c.diff
作用:该补丁用于产生crti.o和crtn.o文件。
下载地址:http://gcc.gnu.org/cgibin/
cvsweb.cgi/gcc/gcc/flow.c.diff?cvsroot=gcc&only_with_tag=cslarmbranch&
r1=1.563.4.2&r2=1.563.4.3


1.3.3 t-linux.diff
作用:修改gcc一处
bug
下载地址:http://frank.harvard.edu/~coldwell/toolchain/tlinux.
diff


1.4编译 GNU binutils
重新以arm用户登陆,让新设置的环境变量起作用.
[arm@localhost.arm]#su.arm
[arm@localhost.arm]#cd.${SRC}
[arm@localhost.tchain3.4.4]#tar.xzvf.binutils2.16.
tar.gz
[arm@localhost.tchain3.4.4]#mkdir.p.BUILD/
binutils2.16
[arm@localhost.binutils2.16]#
cd.BUILD/binutils2.16
[arm@localhost.binutils2.16]#
.../../binutils2.16/
configure.prefix=${
PREFIX}.target=${
TARGET}.\
withsysroot=${
SYSROOT}
[arm@localhost.binutils2.16]#
make
[arm@localhost.binutils2.16]#
su.root
[root@localhost.binutils2.16]#
make.install
[root@localhost.binutils2.16]#
exit
[arm@localhost.binutils2.16]#


1.5准备内核头文件
1.5.1使用当前平台的gcc编译内核头文件
[arm@localhost tchain3.4.4]#cd.${KERNEL}
[arm@localhost.kernel]#tar.xvfz.linux2.6.14.1.
tar.gz
[arm@localhost.kernel]#cd..linux2.6.14.1
[arm@localhost.linux2.6.14.1]#
make.ARCH=arm.menuconfig
[arm@localhost.linux2.6.14.1]#
make


1.5.2复制内核头文件
[arm@localhost.kernel]#su.root
[root@localhost.kernel]#mkdir.p.${
SYSROOT}/usr/include



[root@localhost.kernel]#cp.a.include/
linux.${SYSROOT}/usr/include/linux
[root@localhost.kernel]#cp.a.include/
asmi386.${
SYSROOT}/usr/include/asm
[root@localhost.kernel]#cp.a.include/
asmgeneric.${
SYSROOT}/usr/include/asmgeneric
[root@localhost.kernel]#exit
[arm@localhost.kernel]#


1.6译编glibc头文件
[arm@localhost.kernel]#cd.${SRC}
[arm@localhost.chain3.4.4]#tar.xvfz.glibc2.3.5.
tar.gz
[arm@localhost.chain3.4.4]#patch.d.glibc2.3.5.p1.<
.ioperm.c.diff
[arm@localhost.glibc2.3.5]#
cd.glibc2.3.5
[arm@localhost.glibc2.3.5]#
tar.xvfz.../glibclinuxthreads2.3.5.
tar.gz
[arm@localhost.chain3.4.4]#cd...
[arm@localhost.chain3.4.4]#mkdir.BUILD/glibc2.3.5headers
[arm@localhost.chain3.4.4]#cd.BUILD/glibc2.3.5headers
[arm@localhost.glibc2.3.5headers]#../../
glibc2.3.5/
configure.prefix=/
usr.host=${
TARGET}.\
enableaddons=
linuxthreads.–withheaders=${
SYSROOT}/usr/include
[arm@localhost.glibc2.3.5headers]#
su.root
[root@localhost.glibc2.3.5headers]#
make.crosscompiling=
yes.install_root=${SYSROOT}.installheaders
[root@localhost.glibc2.3.5headers]#
touch.${SYSROOT}/usr/include/gnu/stubs.h.[root@localhost.glibc2.3.5headers]#
touch.${SYSROOT}/usr/include/bits/stdio_lim.h
[root@localhost.glibc2.3.5headers]#
exit
[arm@localhost.glibc2.3.5headers]#
注意:.prefix=/
usr.:是
gcc寻找库的搜索路径。


1.7编译gcc第一阶段
[arm@localhost.glibc2.3.5headers]#
cd.${SRC}
[arm@localhost.chain3.4.4]#tar.xjvf.gcc3.4.4.
tar.bz2
[arm@localhost.chain3.4.4]#patch.d.gcc3.4.4.p1.<
.flow.c.diff
[arm@localhost.chain3.4.4]#patch.d.gcc3.4.4.p1.<
.tlinux.
diff
[arm@localhost.chain3.4.4]#mkdir.p.BUILD/
gcc3.4.4stage1
[arm@localhost.chain3.4.4]#cd.BUILD/gcc3.4.4stage1
[arm@localhost.gcc3.4.4stage1]#../../
gcc3.4.4/
configure.prefix=${
PREFIX}.target=${
TARGET}.\
enablelanguages=
c.withsysroot=${
SYSROOT}

注意:不能加上"disableshared"
选项。
[arm@localhost.gcc3.4.4stage1]#
make.allgcc
[arm@localhost.gcc3.4.4stage1]#
su.root
[root@localhost.gcc3.4.4stage1]#
make.installgcc
[root@localhost.gcc3.4.4stage1]#
exit
[arm@localhost.gcc3.4.4stage1]#


1.8编译完整的glibc
[arm@localhost.gcc3.4.4stage1]
.#cd.${SRC}
[arm@localhost.tchain3.4.4]#mkdir.BUILD/glibc2.3.5
[arm@localhost.tchain3.4.4]#cd.BUILD/glibc2.3.5
[arm@localhost.glibc2.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.\
../../glibc2.3.5/
configure.prefix=/
usr.build=
i386redhatlinux.host=
armunknownlinuxgnu.\
target=
armunknownlinuxgnu.without__
thread.enableaddons=
linuxthreads.\
withheaders=${
SYSROOT}/usr/include



说明:
prefix:
指定安装路径。
target:
指定目标平台。
host:
指定当前平台。
build:
指定编译平台。
withsysroot:
用于指定编译所需要的头文件,及链接库。
enableaddons:
加入其它的库,如线程库等。
enablelanguages:
指定gcc所支持的语言。


[arm@localhost.glibc2.3.5]#
make
[arm@localhost.glibc2.3.5]#
su.root
[root@localhost.glibc2.3.5]#
make.install_root=${SYSROOT}.install
[root@localhost.glibc2.3.5]#
exit
[arm@localhost.glibc2.3.5]#


1.9编译完整的gcc
[arm@localhost.glibc2.3.5]#
cd.${SRC}
[arm@localhost.tchain3.4.4]#mkdir.BUILD/gcc3.4.4
[arm@localhost.tchain3.4.4]#cd.BUILD/gcc3.4.4
[arm@localhost.gcc3.4.4]#../../
gcc3.4.4/
configure.prefix=${
PREFIX}.target=${
TARGET}.\
enablelanguages=
c.withsysroot=${
SYSROOT}
[arm@localhost.gcc3.4.4]#
make
[arm@localhost.gcc3.4.4]#
su.root
[root@localhost.gcc3.4.4]#
make.install
[root@localhost.gcc3.4.4]#
exit
[arm@localhost.gcc3.4.4]#


2 GNU交叉工具链的下载

2.1 ARM官方网站
工具链的官方下载地址:


http://www.arm.linux.org.uk....
可以从该站点下载2.95.3,.3.0以及3.2工具链

ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross2.95.3.
tar.bz2
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross3.0.
tar.bz2
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross3.2.
tar.bz2


3 GNU交叉工具链的介绍与使用

3.1常用工具介绍
名称归属作用

armlinuxas
binutils编译ARM汇编程序

armlinuxar
binutils把多个.o合并成一个.o或静态库(.a)


armlinuxranlib
binutils为库文件建立索引,相当于
armlinuxar.s


armlinuxld
binutils连接器(Linker),.把多个.o或库文件连接成一个可执行文件


名称归属作用

armlinuxobjdump
binutils查看目标文件(.o)和库(.a)的信息

armlinuxobjcopy
binutils转换可执行文件的格式

armlinuxstrip
binutils去掉elf可执行文件的信息..使可执行文件变小


armlinuxreadelf
binutils读
elf可执行文件的信息

armlinuxgcc
gcc编译.c或.S开头的C程序或汇编程序

armlinuxg++
gcc编译c++程序

3.2主要工具的使用
3.2.1 arm-linux-gcc的使用
1..编译C文件,生成elf可执行文件
h1.c源文件
#include.<stdio.h>
void.hellofirst(void)
{
printf("The.first.hello!.\n");
}


h2.c源文件
#include.<stdio.h>
void.hellosecond(void)
{


printf("The.second.hello!.\n");
}


hello.c源文件
#include.<stdio.h>
void.hellosecond(void);
void.hellofirst(void);


int.main(int.argc,.char.*argv[])


{
hellofirst();
hellosecond();
return(0);


}
编译以上
3个文件,有如下几种方法:
方法1:
[arm@localhost.gcc]#armlinuxgcc.c.h1.
c
[arm@localhost.gcc]#armlinuxgcc.c.h2.
c
[arm@localhost.gcc]#armlinuxgcc.o.hello.hello.
c.h1.o.h2.o
方法2:
[arm@localhost.gcc]#armlinuxgcc.c.h1.
c.h2.c
[arm@localhost.gcc]#armlinuxgcc.o.hello.hello.
c.h1.o.h2.o
方法3:
[arm@localhost.gcc]#armlinuxgcc.c.o.h1.
o.h1.c



[arm@localhost.gcc]#armlinuxgcc.c.o.h1.
o.h1.c
[arm@localhost.gcc]#armlinuxgcc.o.hello.hello.
c.h1.o.h2.o
方法4:
[arm@localhost.gcc]#armlinuxgcc.o.hello.hello.
c.h1.c.h2.c
c:
只编译不连接。
o:
编译且连接。


2..产生一个预处理文件
当要看一个宏在源文件中产生的结果时,比较合适。
[arm@localhost.gcc]#armlinuxgcc.E.h1.
i.h1.c
E:
产生一个预处理文件.


3..产生一个动态库
动态库是在运行时需要的库。
[arm@localhost.gcc]#armlinuxgcc.c.fpic.h1.
c.h2.c
[arm@localhost.gcc]#armlinuxgcc.shared.h1.
o.h2.o.o.hello.
so
[arm@localhost.gcc]#armlinuxgcc.o.hello.hello.
c.hello.so
把hello.so拷贝到目标板的/lib目录下,把可执行文件拷贝目标板的/tmp目录下,在目标板上运行hello.
#/tmp/hello
或把hello.so和hello一起拷贝到/tmp目标下,并设置LD_LIBRARY_PATH环境变量
#export.LD_LIBRARY_PATH.=/tmp:$LD_LIBRARY_PATH
#/tmp/hello


3.2.2 arm-linux-ar和 arm-linux-ranlib的使用
静态库是在编译时需要的库。


1..建立一个静态库
[arm@localhost.gcc]#armlinuxar.r.libhello.
a.h1.o.h2.o
2..为静态库建立索引
[arm@localhost.gcc]#armlinuxar.s.libhello.
a
[arm@localhost.gcc]#armlinuxranlib.libhello.
a
3..由静态库产生可执行文件
[arm@localhost.gcc]#armlinuxgcc.o.hello.hello.
c.lhello.L./
[arm@localhost.gcc]#armlinuxgcc.o.hello.hello.
c.libhello.a
hello文件可以直接拷贝到/tmp目录下运行,不需
libhello.a.
3.2.3 arm-linux-objdump的使用
1..查看静态库或.o文件的组成文件
[arm@localhost.gcc]$.armlinuxobjdump.a.libhello.
a
2..查看静态库或.o文件的络组成部分的头部分
[arm@localhost.gcc]$.armlinuxobjdump.h.libhello.
a
3..把目标文件代码反汇编
[arm@localhost.gcc]$.armlinuxobjdump.d.libhello.
a
3.2.4 arm-linux-readelf的使用
1..读
elf文件开始的文件头部

[arm@localhost.gcc]$.armlinuxreadelf.h.hello


ELF.Header:
Magic:...7f.45.4c.46.01.01.01.61.00.00.00.00.00.00.00.00


Class:
Data:
Version:
OS/ABI:
ABI.Version:
Type:
Machine:
Version:
Entry.point.address:
Start.of.program.headers:
Start.of.section.headers:
Flags:
Size.of.this.header:
Size.of.program.headers:


.....................................ELF32
......................................2's.complement,.little.endian
................................1.(current)
................................ARM
0
.....................................EXEC.(Executable.file)
................................ARM
0x1


0x82b4
......52.(bytes.into.file)
........10240.(bytes.into.file)
.....................................0x2,.has.entry.point
................52.(bytes)
.......32.(bytes)


Number.of.program.headers:.6
Size.of.section.headers:..........40.(bytes)
Number.of.section.headers:.28
Section.header.string.table.index:.25


2..读
elf文件中所有ELF的头部:
[arm@localhost.gcc]#armlinuxreadelf.e.hello
......
3..显示整个文件的符号表
[arm@localhost.gcc]#armlinuxreadelf.s.hello
......
4..显示使用的动态库
[arm@localhost.gcc]#armlinuxreadelf.d.hello
......
3.2.5 arm-linux-strip的使用
1..移除所有的符号信息
[arm@localhost.gcc]#cp.hello.hello1
[arm@localhost.gcc]#armlinuxstrip.stripall.hello
stripall:
是移除所有符号信息
[arm@localhost.gcc]#ll
rwxrxrx..1.arm.root.2856.7

3.15:14.hello
rwxrxrx..1.arm.root.13682..7

3.15:13.hello1

strip后的hello程序比原来的hello1程序要小很多。
2..移除调试符号信息
[arm@localhost.gcc]#armlinuxstrip.g.hello
[arm@localhost.gcc]#ll
rwxrxrx..1.arm.root.4501.7

3.15:17.hello
rwxrxrx..1.arm.root.13682..7

3.15:13.hello1

3.2.6 arm-linux-copydump的使用
生成可以执行的2进制代码
[arm@localhost.gcc]#armlinuxcopydump.O.binary.hello.hello.
bin


4 ARM GNU常用汇编语言介绍

4.1 ARM GNU常用汇编伪指令介绍
1..abort
.abort:停止汇编
.align.absexpr1,
.absexpr2:
以某种对齐方式,在未使用的存储区域填充值..第一个值表示对齐方式,4,.8,16或
32..第
二个表达式值表示填充的值.
2..if...else...endif
.if
.else
.endif:支持条件预编译
3..include
.include."file":包含指定的头文件,.可以把一个汇编常量定义放在头文件中.
4..comm
.comm.symbol,.length:在bss段申请一段命名空间,该段空间的名称叫
symbol,.长度为length...Ld连接器在连接会
为它留出空间.
5..data
.data.subsection:说明接下来的定义归属于
subsection数据段.
6..equ
.equ.symbol,.expression:把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.
7..global
.global.symbol:定义一个全局符号,.通常是为ld使用.
8..ascii
.ascii."string":定义一个字符串并为之分配空间.
9..byte
.byte.expressions:定义一个字节,.并为之分配空间.
10..short
.short.expressions:定义一个短整型,.并为之分配空间.
11..int
.int.expressions:定义一个整型,并为之分配空间.
12.long
.long.expressions:定义一个长整型,.并为之分配空间.
13.word
.word.expressions:定义一个字,并为之分配空间,.4bytes.
14..macro/endm
.macro:定义一段宏代码,..macro表示代码的开始,..endm表示代码的结束.
15..req
name..req.register.name:为寄存器定义一个别名.
16..code
.code.[16|32]:指定指令代码产生的长度,.16表示
Thumb指令,.32表示
ARM指令.
17..ltorg
.ltorg:表示当前往下的定义在归于当前段,并为之分配空间.

4.2 ARM GNU专有符号
1..@
表示注释从当前位置到行尾的字符.


2..#
注释掉一整行.
3..;
新行分隔符.
4.3操作码
1..NOP
nop
空操作,.相当于
MOV.r0,.r0
2..LDR
ldr.<register>.,.=.<expression>
相当于
PC寄存器或其它寄存器的长转移.


3.ADR
adr.<register>.<label>
相于
PC寄存器或其它寄存器的小范围转移.


ADRL
adrl.<register>.<label>
相于
PC寄存器或其寄存器的中范围转移.


5可执行生成说明

5.1 lds文件说明
5.1.1主要符号说明
1..OUTPUT_FORMAT(bfdname)
指定输出可执行文件格式.
2.
.
OUTPUT_ARCH(bfdname)
指定输出可执行文件所运行CPU平台
3..ENTRY(symbol)
指定可执行文件的入口段

5.1.2段定义说明
1.
.
段定义格式
SECTIONS.{....
段名
:.{
内容


}
...
}



5.1.3.uboot.
lds文件说明
OUTPUT_FORMAT("elf32littlearm",
."elf32littlearm",
."elf32littlearm")
;指定输出可执行文件是
elf格式,32位
ARM指令,小端
OUTPUT_ARCH(arm)
;指定输出可执行文件的平台为ARM
ENTRY(_start)
;指定输出可执行文件的起始代码段为_start.
SECTIONS
{


..=.0x00000000..;从
0x0位置开始

..=.ALIGN(4).;代码以4字节对齐
.text.:.;指定代码段
{


cpu/arm920t/start.o..(.text).;代码的第一个代码部分

*(.text).;其它代码部分
}
..=.ALIGN(4)
.rodata.:.{.*(.rodata).}.;指定只读数据段


..=.ALIGN(4);
.data.:.{.*(.data).}.;指定读/写数据段


..=.ALIGN(4);
.got.:.{.*(.got).}.;指定got段,.got段式是
uboot自定义的一个段,.非标准段


__u_boot_cmd_start.=...;把__u_boot_cmd_start赋值为当前位置,.即起始位置
.u_boot_cmd.:.{.*(.u_boot_cmd).}.;指定u_boot_cmd段,.uboot把所有的uboot命令放在该段.
__u_boot_cmd_end.=..;把__u_boot_cmd_end赋值为当前位置,即结束位置

..=.ALIGN(4);
__bss_start.=..;把__bss_start赋值为当前位置,即
bss段的开始位置
.bss.:.{.*(.bss).};指定bss段
_end.=..;把_end赋值为当前位置,即
bss段的结束位置


}

第四部分 u-boot的移植

1 u-boot的介绍及系统结构

1.1 u-boot介绍
Uboot
是德国
DENX小组的开发用于多种嵌入式CPU的bootloader程序,.UBoot
不仅仅支持嵌入式Linux
系统的引导,当前,它还支持NetBSD,.VxWorks,.QNX,.RTEMS,.ARTOS,.LynxOS嵌入式操作系统。UBoot

了支持PowerPC系列的处理器外,还能支持MIPS、
x86、ARM、NIOS、XScale等诸多常用系列的处理器。


1.2获取u-boot
以uboot用户登陆.



[uboot@localhost.~]#mkdir.p.dev_
home/uboot
[uboot@localhost.~]#cd.dev_home/uboot
从下面地址下载uboot
的源代码。


http://sourceforge.net/projects/uboot


[uboot@localhost.uboot]#tar.xjvf.uboot1.1.4.
tar.bz2
[uboot@localhost.uboot]#cd.uboot1.1.4


1.3 u-boot体系结构
1.3.1 u-boot目录结构
1..目录树
[uboot@localhost.uboot1.1.4]#
tree.L.1.d
.
|board
|common
|cpu
|disk
|doc
|drivers
|dtt
|examples
|fs
|include
|lib_
arm
|lib_
generic
|lib_
i386
|lib_
m68k
|lib_
microblaze
|lib_
mips
|lib_
nios
|lib_
nios2
|lib_
ppc
|net
|post
|rtc
`tools
2..board:和一些已有开发板有关的文件..每一个开发板都以一个子目录出现在当前目录中,比如说:SMDK2410,
子目录中存放与开发板相关的配置文件.
3..common:实现
uboot
命令行下支持的命令,每一条命令都对应一个文件。例如
bootm命令对应就是
cmd_bootm.c。
4..cpu:与特定CPU架构相关目录,每一款
Uboot
下支持的CPU在该目录下对应一个子目录,比如有子目录
arm920t等。
5..disk:对磁盘的支持。
5..doc:文档目录。Uboot
有非常完善的文档,推荐大家参考阅读。
6..drivers:Uboot
支持的设备驱动程序都放在该目录,比如各种网卡、支持CFI的Flash、串口和USB等。
7..fs:支持的文件系统,Uboot
现在支持cramfs、fat、fdos、jffs2和registerfs。
8..include:Uboot
使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的
文件。该目录下configs目录有与开发板相关的配置头文件,如
smdk2410.h。该目录下的asm目录有与CPU体

系结构相关的头文件,asm对应的是
asmarm.


9..lib_xxxx:与体系结构相关的库文件。如与ARM相关的库放在lib_arm中。
10..net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。
11..tools:生成Uboot
的工具,如:mkimage,.crc等等。
2 uboot的启动过程及工作原理

2.1启动模式介绍
大多数 Boot.Loader都包含两种不同的操作模式:"启动加载"模式和"下载"模式,这种区别仅对于开发人
员才有意义。但从最终用户的角度看,Boot.Loader的作用就是用来加载操作系统,而并不存在所谓的启动加
载模式与下载工作模式的区别。

启动加载(Boot.loading)模式:这种模式也称为"自主"(Autonomous)模式。也即
Boot.Loader从目标机
上的某个固态存储设备上将操作系统加载到 RAM中运行,整个过程并没有用户的介入。这种模式是
Boot
Loader的正常工作模式,因此在嵌入式产品发布的时侯,Boot.Loader显然必须工作在这种模式下。

下载(Downloading)模式:在这种模式下,目标机上的 Boot.Loader将通过串口连接或网络连接等通信手
段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被
Boot
Loader保存到目标机的 RAM中,然后再被
BootLoader写到目标机上的FLASH.类固态存储设备中。Boot
Loader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 Boot
Loader的这种工作模式。工作于这种模式下的 Boot.Loader通常都会向它的终端用户提供一个简单的命令
行接口。


UBoot
这样功能强大的 Boot.Loader同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行
切换。

大多数bootloader都分为阶段1(stage1)和阶段2(stage2)两大部分,uboot
也不例外。依赖于
CPU体系结构
的代码(如
CPU初始化代码等)通常都放在阶段1中且通常用汇编语言实现,而阶段2则通常用C语言来实
现,这样可以实现复杂的功能,而且有更好的可读性和移植性。


2.2阶段1介绍
uboot
的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要代码部分如下:


2.2.1定义入口
由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0
地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。


1..board/crane2410/uboot.
lds:..ENTRY(_start)...==>.cpu/arm920t/start.S:..globl._start
2..uboot代码区(TEXT_BASE.=.0x33F80000)定义在board/crane2410/config.mk
2.2.2设置异常向量
_start: b reset @ 0x00000000
ldr pc, _undefined_instruction @ 0x00000004
ldr pc, _software_interrupt @ 0x00000008
ldr pc, _prefetch_abort @ 0x0000000c
ldr pc, _data_abort @ 0x00000010
ldr pc, _not_used @ 0x00000014
ldr pc, _irq @ 0x00000018
ldr pc, _fiq @ 0x0000001c


当发生异常时,执行cpu/arm920t/interrupts.c中定义的中断处理函数。


2.2.3设置CPU的模式为SVC模式
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0

2.2.4关闭看门狗
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr r0, =pWTCON
mov r1, #0x0 @ 根据三星手册进行调置。
str r1, [r0]

2.2.5禁掉所有中断
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]

# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]

2.2.6设置以CPU的频率
默认频率为 FCLK:HCLK:PCLK = 1:2:4,默认FCLK的值为120 MHz,该值为S3C2410手册的推荐值。
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]

2.2.7设置CP15
设置CP15,.失效指令(I)Cache和数据(D)Cache后,.禁止MMU与Cache。
cpu_init_crit:
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* 失效 I/D cache, 见 S3C2410手册附录的 2-16 */
mcr p15, 0, r0, c8, c7, 0 /* 失效 TLB, 见 S3C2410手册附录的 2-18 */

/*

* 禁止 MMU 和caches, 详见S3C2410手册附录2-11
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* 清除 bits 13, 9:8 (--V- --RS)

* Bit 8: Disable System Protection
* Bit 7: Disable ROM Protection
* Bit 13: 异常向量表基地址: 0x0000 0000
*/
bic r0, r0, #0x00000087 /* 清除 bits 7, 2:0 (B--- -CAM)

* Bit 0: MMU disabled
* Bit 1: Alignment Fault checking disabled
* Bit 2: Data cache disabled
* Bit 7: 0 = Little-endian operation

*/
orr r0, r0, #0x00000002 /* set bit 2 (A) Align, 1 = Fault checking enabled */
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache, 1 = Instruction cache enabled

*/
mcr p15, 0, r0, c1, c0, 0

2.2.8配置内存区控制寄存器
配置内存区控制寄存器,寄存器的具体值通常由开发板厂商或硬件工程师提供..如果您对总线周期及外围
芯片非常熟悉,.也可以自己确定,.在UBOOT
中的设置文件是
board/crane2410/lowlevel_init.S,.该文件包含
lowleve_init程序段..详细寄存器设置及值的解释见
3.2.2.启动AXD配置开发板一节中的第5点.


mov ip, lr
bl lowlevel_init
mov lr, ip


2.2.9安装U-BOOT使的栈空间
下面这段代码只对不是从
Nand.Flash启动的代码段有意义,对从
Nand.Flash启动的代码,没有意义。因为

Nand.Flash中把UBOOT执行代码搬移到RAM,由
2.1.9中代码完成..

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
...
#endif
stack_setup:


ldr r0, _TEXT_BASE /* 代码段的起始地址 */
sub r0, r0, #CFG_MALLOC_LEN/* 分配的动态内存区 */
sub r0, r0, #CFG_GBL_DATA_SIZE /* UBOOT开发板全局数据存放 */


#ifdef CONFIG_USE_IRQ/* 分配IRQ和FIQ栈空间 */
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif
sub sp, r0, #12 /* 留下3个字为Abort */

2.2.10 BSS段清0
clear_bss:
ldr r0, _bss_start/* BSS段的起始地址 */
ldr r1, _bss_end/* BSS段的结束地址 */
mov r2, #0x00000000/* BSS段置0 */

clbss_l:str r2, [r0]/* 循环清除BSS段 */
add r0, r0, #4
cmp r0, r1
ble clbss_l

2.2.11搬移Nand Flash代码

Nand.Flash中,.把数据拷贝到RAM,.是由
copy_myself程序段完成,.该程序段详细解释见:第七部分的3.1节.


#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself

@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop



1: b 1b @ infinite loop
on_the_ram:
#endif

2.2.12进入C代码部分
ldr pc, _start_armboot
_start_armboot: .word start_armboot


2.3阶段2的C语言代码部分 
lib_arm/board.c中的start.armboot是
C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个
uboot(
armboot)的主函数,该函数主要完成如下操作:


2.3.1调用一系列的初始化函数
1..指定初始函数表:
init_fnc_t *init_sequence[] = {

cpu_init,
board_init,
interrupt_init,
env_init,
init_baudrate,
serial_init,
console_init_f,
display_banner,
dram_init,
display_dram_config,

/* cpu的基本设置 */
/* 开发板的基本初始化 */
/* 初始化中断 */
/* 初始化环境变量 */
/* 初始化波特率 */
/* 串口通讯初始化 */
/* 控制台初始化第一阶段 */
/* 通知代码已经运行到该处 */
/* 配制可用的内存区 */

#if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
checkboard,
#endif
NULL,
};

执行初始化函数的代码如下:


for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}

2..配置可用的Flash区
flash_init ()

3..初始化内存分配函数
mem_malloc_init()

4..nand.flash初始化
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
puts ("NAND:");
nand_init();/* 初始化 NAND */


见第七部分3.2.3 节中的第3点nand_init()函数.

5..初始化环境变量

env_relocate.();


6.
.
外围设备初始化
devices_init()
7..I2C总线初始化
i2c_init();
8..LCD初始化
drv_lcd_init();
9..VIDEO初始化
drv_video_init();
10..键盘初始化
drv_keyboard_init();
11..系统初始化
drv_system_init();
2.3.2初始化网络设备
初始化相关网络设备,填写IP、MAC地址等。
1..设置IP地址
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");


/* MAC Address */

{
int i;
ulong reg;
char *s, *e;
uchar tmp[64];


i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;

for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)

s = (*e) ? e + 1 : e;
}
}


2.3.3进入主UBOOT命令行
进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
for (;;) {
main_loop (); /* 在common/main.c */
}



上一篇:没有了 下一篇:VMWARE中如何实现文件共享