[转]arm开发经验!

http://www.laogu.com/wz_1428.htm

 http://www.laogu.com/wz_1429.htm

http://www.laogu.com/wz_1430.htm

http://www.laogu.com/wz_1431.htm

前一段时间做了arm的一些开发,主要是编写了arm的启动软件和移植了uCOS-II到arm7。我做事情喜欢深入简出,及从最简单,最原理的方面先做一个框架,然后在这个框架里面进行补充。我还是一个很喜欢和别人讨论的人,希望有人可以给我提出意见和建议。我的这个心得很初级,都是一些基本的东西。现在拿出来和大家分享,希望在我毕业之前能给大家留一些纪念。^_^
    由于这些东西发paper实在是没有价值,但是我感觉可以作为arm开发的入门。由于我的水平和经验有限,错误也是难免的。但是如果不拿出来和大家分享,就算有错误我也发现不了,是么?呵呵。我现试试发连载的第一篇,看看有多少价值,如果大家觉得有价值,我会继续连载的。
连载一:
前言
这个文档是我学习ARM编程的总结和心得。阅读这个文档的人应当首先阅读ADS1.2的帮助文档及相关内容。这个文档不会对编译器及连接器做出详细的说明,在需要的时候会指出具体内容在相关资料的章节。同时阅读这个文档的人需要了解ARM指令集和一些ARM汇编的基本内容以及C和C++的相关编程内容。同时还需要了解ARM的流水线结构及一些基本的编程知识。同时为了方便查阅英文文档,所有的相关术语都使用英文原文

第一章 STARTUP
1 ARM的启动
一般的嵌入式系统在主程序执行之前都需要执行一些初始化的过程以创造嵌入式程序运行的环境,尤其是一些高级的嵌入式系统,由于核心芯片使用内存映射、内存保护等机制以及编程使用高级语言C,C++甚至JAVA语言,都需要先创建一个适合程序运行的硬件环境,然后初始化或者配置或者剪裁run-time library, 这些工作都必须在主程序运行前完成,所以一个startup程序或者程序组对于一个嵌入式系统来说是非常重要的。要编写startup程序,需要对编译器、链接器和汇编器的细节有一定的了解,同时对ARM芯片硬件本身的地址分配以及memory mapping机制也需要有一些了解。
2 ARM 程序的工作过程
首先由各种source file经过编译产生object文件,然后object文件经过链接生成Image文件,然后通过ICE的方法,根据描述文件的指定下载到目标板上的固态存储器指定地址当中,比如flash,EEPROM, ROM等等。在程序执行之前,根据某些描述文件,将需要读写数据的部分读出放入动态存储器比如RAM当中,然后程序从ROM开始执行。或者有时为了提高程序的运行速度,也可以将所有的程序(有一些root的部分除外,以后会提及)通过一个描述文件放入指定的RAM当中,然后程序从RAM开始执行,但是这样会耗费大量的动态存储器,所以大部分程序会取折中的方法,将需要快速运行的部分和要读写的部分放入RAM中(一般读固态存储器的过程和动态存储器的过程是一样的,但是写就不同了,所以读写的部分一定要放到RAM中),而只读的部分和对速度要求不是那么高的部分放入固态存储器。同时ARM结构的异常向量表规定放在地址为0x00000000开始的地址空间上,而一般的CPU为了提高异常相应速度,会将这个向量段remap到其他的RAM当中,所以在描述文件当中必须精确指定异常向量跳转程序的地址到remap的地方。在application程序执行前,还需要由一些文件描述application程序执行的环境。比如系统工作时钟,总线频率。现在一般嵌入式编程语言为C,C++等。如果在使用它们的时候使用的runtime-library,那么在程序执行前还需要为这些库函数初始化heap。然后ARM可能工作在不同的模式,还需要为不同的工作模式设置stack。这样,描述链接地址的文件,以及在application运行前所有的初始化程序就是startup程序组
3 STARTUP分类
这样,将startup程序所完成的功能分类。一类是链接地址描述,一类是各种初始化的程序。根据不同的应用,描述文件和初始化程序的内容以及结构和复杂程度都会不同。但是基本上,它们都必须实现以下功能。
3.1 描述文件实现功能
描述文件可以是链接命令行上简单的几个字符,也可以是一个非常复杂的文件,但是它必须完成如下功能:
; 指定程序下载的地址
; 指定程序执行的地址
3.2 初始化程序实现的功能
初始化程序根据不同的应用,其结构和复杂度也不同,但是它必须完成如下基本功能:
; 异常向量初始化
; 内存环境初始化
; 其他硬件环境初始化

4 描述文件
要编写描述文件,必须知道ARM Image文件的组成及ARM Image文件执行的机理。
4.1 ARM Image的结构
一个ARM Image structure由linker在以下几个方面定义:
 组成它的regions 和 output sections
 当Image 下载的时候这些regions 和 sections 在内存中的位置
 当Image 执行时这些regions和sections在内存中的位置
4.1.1 ARM Image的组成
一个ARM Image被保存在可执行文件当中,它的层次结构可以包括Image,regions,output sections和input sections。
 一个Image由一个或多个regions组成,每个region包括一个或多个output sections
 每个output section由一个或多个input sections组成
 Input sections是一个object file中的code和data信息。
Image的结构如
下图:
1 附图: tu1.JPG (24684 字节)
NOTE Input section,output section和region的定义见ADS_LinkerGuide 3-3页。
同时Input section 有几种属性,分别为readonly,read-write,zero-initialized。分别称为RO,RW和ZI。属性来源于AREA后的attr属性。
比如CODE是RO,DATA是RW,NOINT默认为ZI,即用0值初始化,但是可以选择不进行0值初始化。ZI属性仅仅来源于SPACE, DCB, DCD, DCDU, DCQ, DCQU, DCW, 或者DCWU。由以上定义,ZI属性的包含于RW属性,它是有初始值的RW数据。又例如在C语言中,代码为RO,静态变量和全局变量是RW,ZI的。

 

4.1.2 Image 的Load view 和 execution view
在下载的时候Image regions被放置在memory map当中,而在执行Image前,或许你需要将一些regions放置在它们执行时的地址上,并建立起ZI regions。例如,你初始化的RW数据需要从它在下载时的在ROM中的地址处移动到执行时RAM的地址处。
1 附图: tu2.jpg (640566 字节)
 
NOTE Load view 和execution view的详细定义见ADS_LinkerGuide 3-4
以上的描述包括二个内容,一是要指定各个section在load view和execution view时的地址即memory map,二是要在执行前根据这些地址进行section的初始化。
4.1.3 制定Memory map
制定memory map的方法基本上有二种,一是在link时使用命令行选项,并在程序执行前利用linker pre-define symbol使用汇编语言制定section的段初始化,二是使用scatter file。以上二种方法依应用程序的复杂度而定,一针对简单的情况,二针对复杂的情况。

4.1.1.1 利用linker pre-define symbol使用汇编程序
这是简单的方法,针对简单的memory map。在link时使用选项-ro, -rw, 等等指定memory map的地址。详细说明参看ADS_LinkerGuide中命令行选项说明。然后利用汇编使用pre-define symbol,来进行各种段的定位。Linker pre-define定义如下:
1 附图: tu1.jpg (22811 字节)
 
由前面对ZI的说明,Image$$RW$$Limit = Image$$ZI$$Limit。
2 附图: tu2.jpg (30577 字节)
 
这些都是linker预先定义的外部变量,在使用的时候可以用IMPORT引入。下面给出一个例子。
假设linker 选项为:-ro-base 0x40000000 -rw-base 0x40003000。程序和只读变量(const 变量)大小为0x84,这样RO section的大小为0x84 bytes。Data的大小为0x04 bytes,并且data被初始化,则RW section的大小为0x04,ZI section的大小为0x04。这样程序
在load view,地址是这样的:
0x40000000开始到地址0x40000080,是RO section部分(程序从0x40000000开始),Image$$RO$$Limit = 0x40000084.
0x40000084地址开始到地址0x40000084,是RW section部分。

在execution view,由linker的选项,各个section的地址是这样的:
RO section的地址不变。
RW section的起始地酚Φ蔽?x40003000,则Image$$RW$$Base = 0x40003000。
因为全部的0x04 bytes data被初始化,所以Image$$RW$$Limit = Image$$ZI$$Limt = 0x40003004。
现在要做的就是将RW section移到以0x40003000开始的地方,并且创造一个ZI section。
一个更通用的做法是:
首先比较Image$$RO$$Limit和mage$$RW$$Base,如果相等,说明execution view下RW section的地址和load view 下RW section的地址相同,这样,不需要移动RW section;如果不等,说明需要移动RW section 到它在execution view中的地方。然后将Image$$ZI$$Base地址到Image$$ZI$$Limt地址的内容清零。
示例代码如下:
;读入linker pre-define symbols

IMPORT Image$$RO$$Limit
IMPORT Image$$RW$$Base
IMPORT Image$$ZI$$Base
IMPORT Image$$ZI$$Limit

; .......一些其他的代码或伪指令

;R0读入section load address
LDR R0,= Image$$RO$$Limit
;R1读入section execution address
LDR R1,= Image$$RW$$Base
;R2读入execution section 后的紧跟的word address
LDR R2,= Image$$ZI$$Base
;检查RW section的地址在load view和execution view下
;是否相等,如果相等,就不移动RW section,直接建立
;ZI scetion
CMP R0,R1
BEQ do_zi_init

;否则就copy RW section到execution view下指定的地址
BL copy

; ......
; ......

;copy 是一个用于copy的子函数,它把从R0中的地址开始的
;section copy到R1中的地址开始的section,这个section的
;上限地址后紧跟的word address保存在R2中
copy
CMP R1,R2
LDRCC R3,[R0],#4
STRCC R3,[R1],#4
BCC copy
MOV PC,LR

; ......
; ......
;do_zi_int子函数是为创建ZI section做一些准备工作
do_zi_int
;将ZI section开始的地址装入R1
LDR R1,= Image$$ZI$$Base
;将ZI section结束后紧跟的word address装入R2
LDR R2,= Image$$ZI$$Limit
;将ZI section 需要的初始化量装入R3
MOV R3,#0
BL zi_int


; ......
; ......
;zi_int子函数用于建立并初始化ZI section,ZI section的
;开始地址储存在R1,ZI section结束后紧跟的word address
;地址储存在R2

zi_int
CMP R1,R2
STRCC R3,[R1],#4
BCC zi_int
MOV PC,LR

; ......
; ......
这个方法针对比较简单的应用,如果需要进行一个比较复杂的memory map,如下图,那么这个方法就不适用了。为了解决复杂memory map的问题
需要用到scatter load 机制。
3 附图: tu3.jpg (32473 字节)

目录 第1 章 ARM 微处理器概述 5 1.1 ARM-Advanced RISC Machines 5 1.2 ARM 微处理器的应用领域及特点 5 1.2.1 ARM 微处理器的应用领域 5 1.2.2 ARM 微处理器的特点 6 1.3 ARM 微处理器系列 6 1.3.1 ARM7 微处理器系列 6 1.3.2 ARM9 微处理器系列 7 1.3.3 ARM9E 微处理器系列 7 1.3.4 ARM10E 微处理器系列 7 1.3.5 SecurCore 微处理器系列 8 1.3.6 StrongARM 微处理器系列 8 1.3.7 Xscale 处理器 8 1.4 ARM 微处理器结构 8 1.4.1 RISC 体系结构 8 1.4.2 ARM 微处理器的寄存器结构 9 1.4.3 ARM 微处理器的指令结构 9 1.5 ARM 微处理器的应用选型 10 1.6 本章小节 10 第2 章 ARM 微处理器的编程模型 11 2.1 ARM 微处理器的工作状态 11 2.2 ARM 体系结构的存储器格式 11 2.3 指令长度及数据类型 12 2.4 处理器模式 12 2.5 寄存器组织 13 2.5.1 ARM 状态下的寄存器组织 13 2.5.2 Thumb 状态下的寄存器组织 15 2.5.3 程序状态寄存器 16 2.6 异常(Exceptions) 18 2.6.1 ARM 体系结构所支持的异常类型 18 2.6.2 对异常的响应 18 2.6.3 从异常返回 19 2.6.4 各类异常的具体描述 19 2.6.5 异常进入/退出小节 20 2.6.6 异常向量(Exception Vectors) 20 2.6.7 异常优先级(Exception Priorities) 21 2.6.8 应用程序中的异常处理 21 2.7 本章小节 21 ARM 应用系统开发详解──基于S3C4510B 的系统设计 2 第3 章 ARM 微处理器的指令系统 22 3.1 ARM 微处理器的指令集概述 22 3.1.1 ARM 微处理器的指令的分类与格式 22 3.1.2 指令的条件域 23 3.2 ARM 指令的寻址方式 23 3.2.1 立即寻址 24 3.2.2 寄存器寻址 24 3.2.2 寄存器间接寻址 24 3.2.3 基址变址寻址 24 3.2.4 多寄存器寻址 25 3.2.5 相对寻址 25 3.2.6 堆栈寻址 25 3.3 ARM 指令集 25 3.3.1 跳指令 25 3.3.2 数据处理指令 26 3.3.3 乘法指令与乘加指令 30 3.3.4 程序状态寄存器访问指令 32 3.3.5 加载/存储指令 32 3.3.6 批量数据加载/存储指令 34 3.3.7 数据交换指令 35 3.3.8 移位指令(操作) 35 3.3.9 协处理器指令 36 3.3.10 异常产生指令 38 3.4 Thumb 指令及应用 38 3.5 本章小节 39 第4 章 ARM 程序设计基础 40 4.1 ARM 汇编器所支持的伪指令 40 4.1.1 符号定义(Symbol Definition)伪指令 40 4.1.2 数据定义(Data Definition)伪指令 41 4.1.3 汇编控制(Assembly Control)伪指令 43 4.1.4 其他常用的伪指令 45 4.2 汇编语言的语句格式 48 4.2.1 在汇编语言程序中常用的符号 49 4.2.2 汇编语言程序中的表达式和运算符 49 4.3 汇编语言的程序结构 52 4.3.1 汇编语言的程序结构 52 4.3.2 汇编语言的子程序调用 52 4.3.3 汇编语言程序示例 53 4.3.4 汇编语言与C/C++的混合编程 55 4.4 本章小节 56 第5 章 应用系统设计与调试 57 ARM 应用系统开发详解──基于S3C4510B 的系统设计 3 5.1 系统设计概述 57 5.2 S3C4510B 概述 58 5.2.1 S3C4510B 及片内外围简介 58 5.2.2 S3C4510B 的引脚分布及信号描述 61 5.2.3 CPU 内核概述及特殊功能寄存器(Special Registers) 67 5.2.4 S3C4510B 的系统管理器(System Manager) 72 5.3 系统的硬件选型与单元电路设计 82 5.3.1 S3C4510B 芯片及引脚分析 82 5.3.2 电源电路 83 5.3.3 晶振电路与复位电路 83 5.3.4 Flash 存储器接口电路 85 5.3.5 SDRAM 接口电路 89 5.3.6 串行接口电路 93 5.3.7 IIC 接口电路 94 5.3.8 JTAG 接口电路 95 5.3.9 10M/100M 以太网接口电路 96 5.3.10 通用I/O 接口电路 100 5.4 硬件系统的调试 101 5.4.1 电源、晶振及复位电路 101 5.4.2 S3C4510B 及JTAG 接口电路 102 5.4.3 SDRAM 接口电路的调试 103 5.4.4 Flash 接口电路的调试 105 5.4.5 10M/100M 以太网接口电路 105 5.5 印刷电路板的设计注意事项 105 5.5.1 电源质量与分配 105 5.5.2 同类型信号线的分布 106 5.6 本章小节 106 第6 章 部件工作原理与编程示例 107 6.1 嵌入式系统的程序设计方法 107 6.2 部件工作原理与编程示例 108 6.2.1 通用I/O 口工作原理与编程示例 108 6.2.2 串行通讯工作原理与编程示例 111 6.2.3 中断控制器工作原理与编程示例 120 6.2.4 定时器工作原理与编程示例 123 6.2.5 GDMA 工作原理与编程示例 127 6.2.6 IIC 总线控制器工作原理 133 6.2.7 以太网控制器工作原理 138 主要特性 139 MAC 功能模块 140 带缓冲DMA 接口(Buffered DMA Interface) 144 以太网控制器特殊功能寄存器(Ethernet Controller Special Registers) 147 MAC 寄存器(Media Access Control(MAC)Register) 154 以太网控制器的操作(Ethernet Controller Operation) 160 发送一个帧(Transmitting a Frame) 162 ARM 应用系统开发详解──基于S3C4510B 的系统设计 4 接收一个帧(Receiving a Frame) 162 6.2.8 Flash 存储器工作原理与编程示例 162 6.3 BootLoader 简介 167 6.4 本章小节 167 第7 章 嵌入式uClinux 及其应用开发 168 7.1 嵌入式uClinux 系统概况 168 7.2 开发工具GNU 的使用 170 7.2.1 GCC 编译器 170 7.2.2 GNU Make 172 7.2.3 使用GDB 调试程序 177 7.3 建立uClinux 开发环境 180 7.3.1 建立交叉编译器 181 7.3.2 uClinux 针对硬件的改动 184 7.3.3 编译uClinux 内核 185 7.3.4 内核的加载运行 187 7.4 在uClinux 下开发应用程序 188 7.4.1 串行通信 190 7.4.2 socket 编程 195 7.4 .3 添加用户应用程序到uClinux 202 7.4.4 通过网络添加应用程序到目标系统 205 7.5 本章小结 207 第8 章ARM ADS 集成开发环境的使用 209 8.1 ADS 集成开发环境组成介绍 209 8.1.1 命令行开发工具 209 8.1.2 ARM 运行时库 218 8.1.3 GUI 开发环境(Code Warrior 和AXD) 219 8.1.4 实用程序 221 8.1.5 支持的软件 221 8.2 使用ADS 创建工程 222 8.2.1 建立一个工程 222 8.2.2 编译和链接工程 225 8.2.3 使用命令行工具编译应用程序 229 8.3 用AXD 进行代码调试 230 8.4 本章小结 233
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值