ARM处理器是一种16/32位的高性能、低成本、低功耗的嵌入式RISC微处理器,由ARM公司设计,然后授权给各半导体厂商生产,它目前已经成为应用最为广泛的嵌入式处理器。《ARM体系结构与编程(第3版)》分为16章,对ARM处理器的体系结构、指令系统和开发工具进行了较全面的介绍。其中包括ARM体系结构、ARM程序设计模型、ARM汇编语言程序设计、ARMC/C++编译器、ARM连接器的使用、ARM集成开发环境CodeWarriorIDE及高性能调试工具ADW的使用。此外还介绍一些典型的基于ARM体系的嵌入式应用系统设计的基本技术。最后讲述了STM32微控制器应用开发和自动驾驶系统应用开发。通过阅读《ARM体系结构与编程(第3版)》,读者可以掌握开发基于ARM应用系统各方面的知识。《ARM体系结构与编程(第3版)》可作为学习ARM技术的材料,也可作为嵌入式系统开发人员的参考手册。
对ARM处理器的体系结构、指令系统和开发工具进行了比较全面的介绍,可以使读者掌握开发基于ARM的应用系统的各方面的知识。
前 言
嵌入式系统是指以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积和功耗严格要求的专用计算机系统。
嵌入式系统并不是最近出现的新技术,只是随着微电子技术和计算机技术的发展,微控制芯片功能越来越强大,嵌入微控制芯片的设备和系统也越来越多,从而使得这种技术越来越引人注目。嵌入式系统与通用的计算机系统既有相似之处,也有明显的区别。通常,嵌入式系统中的系统程序(包括操作系统)与应用程序是浑然一体的,这些程序被编译连接成一个可执行的二进制映像文件(Image),这个二进制映像文件被固化在系统中,在系统复位后自动执行。嵌入式系统的开发系统与实际运行的系统并不相同,需要交叉编译系统和适当的调试系统。
ARM嵌入式处理器是一种高性能、低功耗的RISC芯片。它由英国ARM公司设计,世界上几乎所有的主要半导体厂商都生产基于ARM体系结构的通用芯片,或在其专用芯片中嵌入ARM相关技术。如TI、Motorola、Intel、NS、Philips、Altera、Agilent、Atmel、Hynix、Sharp、Triscend、NEC、Cirrus Logic、Samsung和LinkUp等公司都有相应的产品。目前ARM芯片广泛应用于无线产品、PDA、GPS、网络、消费电子产品、STB及智能卡中,基于ARM内核的处理器年产量突破90亿个,已经成为业界的龙头。本书较全面地介绍基于ARM技术的嵌入式应用系统的开发技术。
1. 本书的主要读者
本书对ARM处理器的体系结构、指令系统、开发工具做了较全面的介绍。并在此基础上讨论一些典型的基于ARM体系嵌入式应用系统设计时的基本技术。通过阅读本书,读者可以掌握开发基于ARM应用系统各方面的知识。它可作为学习ARM技术的材料,也可作为嵌入式系统开发人员的参考手册。
2. 本书的主要内容
本书以可执行的二进制映像文件为中心,介绍基于ARM微处理器的嵌入式系统的开发过程所涉及的知识,主要包括以下几部分内容。
?Image文件的“原材料”,包括*.c、*.h、*.obj、*.asm及*.lib文件。这些文件包括操作系统,通常以*.lib形式提供,也有一些操作系统附属的源代码,可以是*.c、*.h、*.asm;BSP(其实也是操作系统的一部分,因为它对于不同的计算机主板是不同的,这里将其单独列出),它通常为*.c、*.h、*.asm;语言库(如C语言运行库),通常为*.lib;用户自己的应用程序,通常为*.c、*.h、*.asm。
本书将对应地介绍ARM体系结构;ARM指令系统;ARM汇编语言,对应于*.asm文件;ARM C语言的独特部分(与标准C相同的部分这里不再介绍),对应于*.c;ARM编程指南;ARM编译器使用。
本书还将介绍ARM公司提供的集成开发环境CodeWarrior IDE的使用方法。
?Image文件各部分的组织方法以及在内存中的安排。
本书将对应地介绍ELF格式映像文件的组成、ARM连接器的使用、程序在 ROM中的存放技术。
?Image文件中各部分的功能。
本书将对应地介绍一个嵌入式系统各部分的功能,着重介绍系统启动部分的设计。这部分内容是嵌入式系统涉及的难点,将通过一些实例来介绍。
?Image的调试。
本书主要介绍ARM公司的调试工具ADW的使用方法,同时将介绍嵌入式系统的基本调试方法。
3. 本书的结构安排
全书包括16章。各章主要内容说明如下。
第1章简要介绍ARM公司的情况以及基于ARM技术的嵌入式系统的应用情况,比较详细地介绍了ARM系列处理器及其特点,并介绍了ARM的寄存器及其使用方法、ARM的存储系统和异常中断等知识。通过对本章的学习,读者可以对ARM技术有一个总体了解。
第2章简要介绍了ARM指令集和主要寻址方式。通过学习本章,读者能够详细了解ARM指令集的相关知识,同时能够掌握ARM指令的寻址方式,为下一章学习各种ARM指令集打下坚实的基础。
第3章详细介绍了ARM指令集。通过介绍各指令的编码格式、语法格式、执行的操作以及应用方法,向读者全面阐述了ARM指令集的用法,同时通过介绍一些常用的ARM指令代码段,帮助读者进一步理解各指令的应用方法,从而使读者能够快速理解和掌握ARM指令的应用,为进行嵌入式编程积累经验。
第4章介绍ARM汇编语言程序设计的基本方法以及ARM汇编器armasm的使用方法。其中包括ARM汇编语言中的伪操作(Directives)、宏指令(Pseudo-instruction)、汇编语言格式、armasm的使用方法以及一些汇编语言程序示例。通过这些介绍,读者可以掌握ARM汇编语言设计的方法。
第5章介绍ARM体系的存储系统。在一个嵌入式系统中,存储系统是非常重要的一部分。这里将介绍ARM体系中用于存储管理的协处理器CP15、存储管理单元MMU、写缓冲以及高速缓存、快速上下文切换技术,还将介绍有关存储系统的程序设计。并以LinkUp公司ARM处理器芯片L7210中的存储系统为例,介绍ARM存储系统的设计技术。其中没有介绍存储保护单元MPU,这是因为MPU更简单,而MMU的应用更为广泛。本章对于虚拟存储技术、缓冲技术以及高速缓存技术都将做比较详细的介绍,使那些从事基于低端单片机应用的开发人员更容易理解ARM体系中存储系统的设计技术。
第6章介绍ARM/Thumb过程调用的标准。为了能使单独编译的C语言程序和汇编程序之间能够相互调用,必须为子程序间的调用制定一定的规则。ATPCS规定了ARM程序和Thumb程序中子程序调用的基本规则。这些基本规则包括子程序调用过程中寄存器的使用规则、数据栈的使用规则和参数的传递规则等。同时,该章还将介绍支持数据栈检查的ATPCS以及与代码/数据位置无关的ATPCS。
第7章介绍ARM程序和Thumb程序混合使用的方法。如果程序遵守支持ARM程序和Thumb程序混合使用的ATPCS,则程序中的ARM子程序和Thumb子程序可以相互调用。对于C/C++源程序而言,只要在编译时指定-apcs /interwork选项,编译器生成的代码就遵守支持ARM程序和Thumb程序混合使用的ATPCS。而对于汇编源程序而言,用户必须编写的代码遵守支持ARM程序和Thumb程序混合使用的ATPCS。该章还将介绍相关的选项和编程技术。
第8章介绍ARM汇编程序以及C/C++程序之间相互调用的技术。其中将介绍C编译器中内嵌的汇编器的使用方法。
第9章详细介绍ARM体系中的异常中断技术。其中包括异常中断处理的过程,各种异常中断处理的进入和返回机制,在应用程序中使用异常中断处理的方法以及各种异常中断的详细使用技术。
第10章主要介绍ARM体系中C/C++语言程序设计的基本知识。其中包括ARM C/C++语言的一些特性、ARM C/C++编译器的使用方法,以及ARM C/C++运行时库的使用方法。通过这些介绍,可以使读者掌握开发嵌入式C/C++应用程序的基本知识和方法,进一步了解嵌入式应用系统的特点。
第11章介绍如何由目标文件以及库文件得到可执行的映像文件。其中包括ELF格式的可执行映像文件的组成、ARM连接器的使用方法,以及连接过程所执行的各种操作。最后通过一些实例介绍在
陈长生,河南省教育厅学术技术带头人,河南省文明教师;数据安全与恢复竞赛指导、评委;河南省高职高专院校电工电子示范性实训基地建设项目负责人;主要从事电子技术和嵌入式物联网技术的研究和教学工作。先后发表论文17篇,出版专著、教材7部,参与省部级以上科研项目3项。
目 录
第1章 ARM概述及其基本编程模型 1
1.1 ARM技术的应用领域及其特点 1
1.1.1 ARM技术的应用领域 1
1.1.2 ARM技术的特点 2
1.2 ARM体系结构的版本及命名方法 3
1.2.1 ARM体系结构的版本 3
1.2.2 ARM体系的变种 6
1.2.3 ARM/Thumb体系版本的命名
格式 8
1.3 ARM处理器系列 9
1.3.1 ARM7系列 10
1.3.2 ARM9系列 10
1.3.3 ARM9E系列 11
1.3.4 ARM10E系列 12
1.3.5 SecurCore系列 12
1.4 ARM处理器的运行模式 13
1.5 ARM寄存器介绍 14
1.5.1 通用寄存器 15
1.5.2 程序状态寄存器 17
1.6 ARM体系的异常中断 19
1.6.1 ARM中异常中断的种类 20
1.6.2 ARM处理器对异常中断的
响应过程 20
1.6.3 从异常中断处理程序中返回 21
1.7 ARM体系中的存储系统 21
1.7.1 ARM体系中的存储空间 21
1.7.2 ARM存储器格式 22
1.7.3 非对齐的存储访问操作 22
1.7.4 指令预取和自修改代码 23
第2章 ARM指令分类及其寻址方式 24
2.1 ARM指令集概述 24
2.1.1 ARM指令的分类 24
2.1.2 ARM指令的一般编码格式 24
2.1.3 ARM指令的条件码域 25
2.2 ARM指令的寻址方式 26
2.2.1 数据处理指令的操作数的寻址
方式 26
2.2.2 字及无符号字节的Load/Store
指令的寻址方式 36
2.2.3 杂类Load/Store指令的寻址
方式 48
2.2.4 批量Load/Store指令的寻址
方式 53
2.2.5 协处理器Load/Store指令的
寻址方式 58
第3章 精通ARM指令集 62
3.1 ARM指令集 62
3.1.1 跳转指令 62
3.1.2 数据处理指令 66
3.1.3 乘法指令 79
3.1.4 杂类的算术指令 85
3.1.5 状态寄存器访问指令 85
3.1.6 Load/Store 内存访问指令 88
3.1.7 批量Load/Store 内存访问
指令 98
3.1.8 信号量操作指令 103
3.1.9 异常中断产生指令 105
3.1.10 ARM协处理器指令 106
3.2 一些基本的ARM指令代码段 111
3.2.1 算术逻辑运算指令的应用 111
3.2.2 跳转指令的应用 113
3.2.3 Load/Store指令的应用 114
3.2.4 批量Load/Store指令的
应用 116
3.2.5 信号量指令的应用 116
3.2.6 与系统相关的一些指令
代码段 117
3.3 Thumb指令概述 121
第4章 ARM汇编语言程序设计 122
4.1 伪操作 122
4.1.1 符号定义伪操作 122
4.1.2 数据定义伪操作 126
4.1.3 汇编控制伪操作 135
4.1.4 数据帧描述伪操作 138
4.1.5 信息报告伪操作 138
4.1.6 其他的伪操作 141
4.2 ARM汇编语言伪指令 150
4.3 ARM汇编语言语句的格式 153
4.3.1 ARM汇编语言中的符号 154
4.3.2 ARM汇编语言中的表达式 156
4.4 ARM汇编语言程序及子程序调用的
格式 162
4.4.1 汇编语言程序的格式 162
4.4.2 汇编语言子程序调用的
格式 163
4.5 ARM汇编编译器的使用 163
4.6 汇编程序设计举例 166
4.6.1 ARM中伪操作的实例 166
4.6.2 ARM汇编程序的实例 168
第5章 ARM的存储系统 174
5.1 ARM存储系统概述 174
5.2 ARM中用于存储管理的系统控制
协处理器CP15 175
5.2.1 访问CP15寄存器的指令 175
5.2.2 CP15中的寄存器 177
5.3 存储器管理单元MMU 185
5.3.1 存储器管理单元MMU
概述 185
5.3.2 禁止/使能MMU 186
5.3.3 MMU中的地址变换过程 188
5.3.4 MMU中的存储访问权限
控制 197
5.3.5 MMU中的域 197
5.3.6 关于快表的操作 197
5.3.7 ARM中的存储访问失效 200
5.4 高速缓冲存储器和写缓冲区 203
5.4.1 基本概念 203
5.4.2 Cache的工作原理和地址
映像方法 204
5.4.3 Cache的分类 206
5.4.4 Cache的替换算法 207
5.4.5 缓冲技术的使用注意事项 208
5.4.6 存储系统的一致性问题 209
5.4.7 Cache内容锁定 211
5.4.8 与Cache和写缓冲区相关的
编程接口 212
5.5 快速上下文切换技术 215
5.5.1 快速上下文切换技术原理 215
5.5.2 快速上下文切换技术编程
接口 216
5.6 与存储系统相关的程序设计指南 217
5.6.1 地址空间 217
5.6.2 存储器的格式 218
5.6.3 非对齐的存储访问操作 219
5.6.4 指令预取和自修改代码 220
5.6.5 IMB技术 221
5.6.6 存储器映射的I/O空间 222
5.7 ARM存储系统的实例 223
5.7.1 L7205的存储系统概述 223
5.7.2 L7205中的SDRAM 224
5.7.3 L7205中的MMU 232
第6章 ATPCS规则 239
6.1 ATPCS概述 239
6.2 基本ATPCS 239
6.2.1 寄存器的使用规则 240
6.2.2 数据栈的使用规则 241
6.2.3 参数的传递规则 242
6.3 几种特定的ATPCS 243
6.3.1 支持数据栈限制检查的
ATPCS 243
6.3.2 支持只读段位置无关
(ROPI)的ATPCS 245
6.3.3 支持可读写段位置无关
(RWPI)的ATPCS 245
6.3.4 支持ARM程序和Thumb程序
混合使用的ATPCS 245
6.3.5 处理浮点运算的ATPCS 246
第7章 ARM程序和Thumb程序混合
使用 247
7.1 概述 247
7.2 在汇编语言程序中通过用户代码
支持interwork 248
7.2.1 可以实现程序状态切换的
指令 248
7.2.2 与程序状态切换相关的
伪操作 251
7.2.3 进行状态切换的汇编程序
实例 252
7.3 在C/C++程序中实现interwork 253
7.4 在汇编语言程序中通过连接器
支持interwork 255
7.4.1 利用veneers实现汇编程序
间的程序状态切换 256
7.4.2 利用veneers实现汇编程序
与C/C++程序间的程序状态
切换 257
第8章 C/C++以及汇编语言的混合
编程 259
8.1 内嵌汇编器的使用 259
8.1.1 内嵌的汇编指令用法 259
8.1.2 内嵌的汇编器和armasm的
区别 261
8.1.3 在C/C++程序中使用内嵌的
汇编指令 261
8.1.4 内嵌汇编指令应用举例 263
8.2 从汇编程序中访问C程序变量 266
8.3 汇编程序、C程序以及C++程序的
相互调用 267
8.3.1 在C++程序中使用C程序
头文件 267
8.3.2 汇编程序、C程序以及C++
程序的相互调用举例 268
第9章 异常中断处理 272
9.1 ARM中的异常中断处理概述 272
9.1.1 ARM体系中的异常中断
种类 272
9.1.2 异常中断向量表及异常中断
优先级 273
9.1.3 异常中断使用的寄存器 274
9.2 进入和退出异常中断的过程 275
9.2.1 ARM处理器对异常中断的
响应过程 275
9.2.2 从异常中断处理程序中
返回 278
9.3 在应用程序中安排异常中断处理
程序 281
9.3.1 在系统复位时安排异常中断
处理程序 281
9.3.2 在C程序中安排异常中断
处理程序 282
9.4 SWI异常中断处理程序 284
9.4.1 SWI异常中断处理程序的
实现 284
9.4.2 SWI异常中断调用 288
9.5 FIQ和IRQ异常中断处理程序 293
9.5.1 IRQ/FIQ异常中断处理
程序 293
9.5.2 IRQ异常中断处理程序
举例 296
9.6 复位异常中断处理程序 297
9.7 未定义指令异常中断 298
9.8 指令预取中止异常中断处理程序 298
9.9 数据访问中止异常中断处理程序 299
第10章 ARM C/C++编译器 300
10.1 ARM C/C++编译器概述 300
10.1.1 ARM C/C++编译器及语言库
介绍 300
10.1.2 ARM编译器中与搜索路径
相关的一些基本概念 301
10.2 ARM编译器命令行格式 302
10.2.1 过程调用标准 303
10.2.2 设置源程序语言类型 304
10.2.3 指定搜索路径 305
10.2.4 设置预处理选项 305
10.2.5 设置输出文件的类型 306
10.2.6 指定目标处理器和ARM
体系版本 307
10.2.7 生成调试信息 308
10.2.8 代码生成的控制 309
10.2.9 控制警告信息的产生 311
10.2.10 编译时进行的一些额外
检查 313
10.2.11 控制错误信息 314
10.3 ARM编译器中的pragmas 314
10.4 ARM编译器特定的关键词 316
10.4.1 用于声明函数的关键词 317
10.4.2 用于声明变量的关键词 328
10.4.3 用于限定数据类型的
关键词 329
10.5 ARM编译器支持的基本数据
类型 330
10.6 ARM编译器中的预定义宏 332
10.7 ARM中的C/C++库 334
10.7.1 ARM中的C/C++运行时库
概述 334
10.7.2 建立一个包含C/C++运行时
库的C/C++应用程序 336
10.7.3 建立不包含C运行时库的
应用程序 339
10.7.4 裁剪C/C++运行时库以适应
特定的目标运行环境 340
第11章 ARM连接器 342
11.1 ARM映像文件 342
11.1.1 ARM映像文件的组成 342
11.1.2 ARM映像文件的入口点 344
11.1.3 输入段的排序规则 345
11.2 ARM连接器概述 346
11.3 ARM连接器生成的符号 348
11.3.1 连接器生成的与域相关的
符号 348
11.3.2 连接器生成的与输出段
相关的符号 349
11.3.3 连接器生成的与输入段
相关的符号 349
11.4 连接器的优化功能 349
11.5 运行时库的使用 350
11.5.1 C/C++运行时库与目标
文件 351
11.5.2 查找需要的C/C++
运行时库 351
11.5.3 选择合适种类的C/C++
运行时库 352
11.5.4 扫描C/C++运行时库 354
11.6 从一个映像文件中使用另一个映像
文件中的符号 354
11.6.1 symdefs文件 354
11.6.2 建立symdefs文件 356
11.6.3 symdefs文件的使用 356
11.7 隐藏或者重命名全局符号 357
11.7.1 steering文件的格式 357
11.7.2 steering文件中的命令 357
11.8 ARM连接器的命令行选项 358
11.9 使用scatter文件定义映像文件的
地址映射 365
11.9.1 scatter文件概述 366
11.9.2 scatter文件中各部分的
介绍 368
11.9.3 scatter文件使用举例 370
第12章 设计嵌入式应用程序案