Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1489549
  • 博文数量: 267
  • 博客积分: 3010
  • 博客等级: 少校
  • 技术积分: 3089
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-05 17:09
个人简介

尊天命,尽人事

文章分类

全部博文(267)

文章存档

2017年(6)

2015年(4)

2014年(27)

2013年(52)

2012年(59)

2011年(120)

分类: LINUX

2011-12-13 10:30:04

该文档的目的是总结我们在工作中的一些经验,并把它们分享给喜欢 
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工具:

作用:查看文件目录树

下载:从 
下载编译

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 下载地址:.
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: 


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

3.2 ADS bootloader部分
作者:刘勇


email: 

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


email: 


3.4 uboot部分
作者:聂强


email: 

作者:孙贺


email: 


3.5内核部分
作者:聂大鹏 
email:
作者:牛须乐(8900a网卡移植部分) 
email:

3.6应用程序部分
作者:聂大鹏 
email:

3.7 Nand Flash 驱动部分
作者:孙磊,刘勇 
email:

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

1.1 ADS命令行命令介绍 
1.1.1 armasm 
1. 命令:armasm [选项] -o 目标文件源文件 
2. 选项说明 
-Errors 错误文件名 
;指定一个错误输出文件 
-I 目录[,目录] ;指定源文件搜索目录 
-PreDefine 预定义宏 
;指定预定义的宏 
-NOCache ;编译源代码时禁止使用Cache进行优化 
-MaxCache ;编译源代码时使用Cache进行优化 
-NOWarn ;关闭所有的警告信息 
-G ;输出调试表 
-keep ;在目标文件中保存本地符号表 
-LIttleend ;生成小端(Little-endian) ARM代码 
-BIgend ;生成大端(Big-endian) ARM代码 
-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 ;指定一个输出的目标文件 
-O[0/1/2] ;指定源代码的优化级别 
-S ;输出汇编代码来代替目标文件 
-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 

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


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


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


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

bl bdmain ;Jump to the main function

;Dead loop


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
下载地址:.
tar.gz


1.2.2 gcc
名称:gcc3.4.4.
tar.bz2
下载地址:
gcc3.4.4.
tar.bz2


1.2.3 glibc
名称:glibc2.3.5.
tar.gz 
glibclinuxthreads2.3.5.
tar.gz
下载地址: 
.
tar.gz 
.
tar.gz


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



下载地址: 
.
tar.gz


1.3准备补丁 
1.3.1 ioperm.c.diff
作用:打修正 
ioperm()函数.
下载地址:


1.3.2 flow.c.diff
作用:该补丁用于产生crti.o和crtn.o文件。
下载地址:
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
下载地址:.
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官方网站
工具链的官方下载地址:


....
可以从该站点下载2.95.3,.3.0以及3.2工具链

.
tar.bz2 
.
tar.bz2 
.
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. 
void.hellofirst(void) 

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


h2.c源文件 
#include. 
void.hellosecond(void) 
{


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


hello.c源文件 
#include. 
void.hellosecond(void); 
void.hellofirst(void);


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



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


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

[arm@localhost.gcc]#armlinuxgcc.c.h2.

[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.

[arm@localhost.gcc]#armlinuxranlib.libhello.

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.

2..查看静态库或.o文件的络组成部分的头部分 
[arm@localhost.gcc]$.armlinuxobjdump.h.libhello.

3..把目标文件代码反汇编 
[arm@localhost.gcc]$.armlinuxobjdump.d.libhello.

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 

.....................................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.ab***pr1,
.ab***pr2:
以某种对齐方式,在未使用的存储区域填充值..第一个值表示对齐方式,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..,.=.
相当于 
PC寄存器或其它寄存器的长转移.


3.ADR 
adr..


ADRL 
adrl..


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
的源代码。



[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 */ 

阅读(3271) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~