第1章 ARM Cortex-M处理器简介 1
1.1 什么是ARM Cortex-M处理器 1
1.1.1 Cortex-M3和Cortex-M4处理器 1
1.1.2 Cortex-M处理器家族 2
1.1.3 处理器和微控制器的区别 3
1.1.4 ARM和微控制器供应商 4
1.1.5 选择Cortex-M3和Cortex-M4微控制器 4
1.2 Cortex-M处理器的优势 6
1.2.1 低功耗 6
1.2.2 性能 6
1.2.3 能耗效率 6
1.2.4 代码密度 6
1.2.5 中断 6
1.2.6 易于使用 7
1.2.7 可扩展性 7
1.2.8 调试特性 7
1.2.9 OS支持 7
1.2.10 多种系统特性 7
1.2.11 软件可移植性和可重用性 7
1.2.12 选择(设备、工具和OS等) 7
1.3 MAR Cortex-M处理器应用 8
1.4 ARM处理器和ARM微控制器的资源 8
1.4.1 ARM网站上有什么 8
1.4.2 微控制器供应商提供的文档 10
1.4.3 工具供应商提供的文档 10
1.4.4 其他资源 10
1.5 背景和历史 11
1.5.1 ARM简史 11
1.5.2 ARM处理器的发展 11
1.5.3 Thumb ISA的架构版本 13
1.5.4 处理器命名 15
1.5.5 关于ARM生态系统 16
第2章 嵌入式软件开发简介 18
2.1 ARM微控制器是怎样构成的 18
2.2 开始时需要准备什么 19
2.2.1 开发组件 19
2.2.2 开发板 19
2.2.3 调试适配器 20
2.2.4 软件设备驱动 21
2.2.5 例子 21
2.2.6 文档和其他资源 21
2.2.7 其他设备 21
2.3 软件开发流程 22
2.4 编译应用程序 23
2.5 软件流程 24
2.5.1 轮询 24
2.5.2 中断驱动 25
2.5.3 多任务系统 27
2.6 C程序中的数据类型 27
2.7 输入、输出和外设访问 28
2.8 微控制器接口 31
2.9 Cortex微控制器软件接口标准(CMSIS) 32
2.9.1 CMSIS简介 32
2.9.2 CMSIS-Core所做的标准化 34
2.9.3 CMSIS-Core的组织结构 34
2.9.4 如何使用CMSIS-Core 35
2.9.5 CMSIS的优势 36
2.9.6 CMSIS的多个版本 38
第3章 技术综述 40
3.1 Cortex-M3和Cortex-M4处理器的一般信息 40
3.1.1 处理器类型 40
3.1.2 处理器架构 40
3.1.3 指令集 41
3.1.4 模块框图 43
3.1.5 存储器系统 44
3.1.6 中断和异常支持 45
3.2 Cortex-M3和Cortex-M4处理器的特性 45
3.2.1 性能 45
3.2.2 代码密度 46
3.2.3 低功耗 46
3.2.4 存储器系统 47
3.2.5 存储器保护单元 47
3.2.6 中断处理 47
3.2.7 OS支持和系统级特性 48
3.2.8 Cortex-M4的特殊特性 48
3.2.9 易于使用 49
3.2.10 调试支持 49
3.2.11 可扩展性 50
3.2.12 兼容性 51
第4章 架构 52
4.1 架构简介 52
4.2 编程模型 52
4.2.1 操作模式和状态 52
4.2.2 寄存器 54
4.2.3 特殊寄存器 56
4.2.4 浮点寄存器 62
4.3 应用程序状态寄存器 65
4.3.1 整数状态标志 65
4.3.2 Q状态标志 66
4.3.3 GE位 66
4.4 存储器系统 67
4.4.1 存储器系统特性 67
4.4.2 存储器映射 68
4.4.3 栈存储 69
4.4.4 存储器保护单元(MPU) 72
4.5 异常和中断 73
4.5.1 什么是异常 73
4.5.2 嵌套向量中断控制器(NVIC) 74
4.5.3 向量表 75
4.5.4 错误处理 76
4.6 系统控制块(SCB) 76
4.7 调试 76
4.8 复位和复位流程 78
第5章 指令集 80
5.1 ARM Cortex-M处理器指令集的背景简介 80
5.2 ARM Cortex-M处理器间的指令集比较 82
5.3 理解汇编语言语法 83
5.4 指令后缀的使用 87
5.5 统一汇编语言(UAL) 88
5.6 指令集 89
5.6.1 处理器内传送数据 90
5.6.2 存储器访问指令 92
5.6.3 算术运算 100
5.6.4 逻辑运算 101
5.6.5 移位和循环移位指令 102
5.6.6 数据转换运算(展开和反序) 103
5.6.7 位域处理指令 105
5.6.8 比较和测试 106
5.6.9 程序流控制 106
5.6.10 饱和运算 113
5.6.11 异常相关指令 115
5.6.12 休眠模式相关指令 116
5.6.13 存储器屏障指令 117
5.6.14 其他指令 118
5.6.15 不支持的指令 119
5.7 Cortex-M4特有的指令 120
5.7.1 Cortex-M4的增强DSP扩展简介 120
5.7.2 SIMD和饱和指令 121
5.7.3 乘法和MAC指令 124
5.7.4 打包和解包 127
5.7.5 浮点指令 128
5.8 桶形移位器 130
5.9 在编程中访问特殊寄存器和特殊指令 131
5.9.1 简介 131
5.9.2 内在函数 132
5.9.3 内联汇编和嵌入汇编 132
5.9.4 使用其他的编译器相关的特性 132
5.9.5 访问特殊寄存器 132
第6章 存储器系统 134
6.1 存储器系统特性简介 134
6.2 存储器映射 134
6.3 连接处理器到存储器和外设 137
6.4 存储器需求 140
6.5 存储器的端 140
6.6 数据对齐和非对齐数据访问支持 142
6.7 位段操作 143
6.7.1 简介 143
6.7.2 位段操作的优势 146
6.7.3 不同数据大小的位段操作 148
6.7.4 C程序实现的位段操作 148
6.8 默认的存储器访问权限 149
6.9 存储器访问属性 150
6.10 排他访问 152
6.11 存储器屏障 154
6.12 微控制器中的存储器系统 154
第7章 异常和中断 157
7.1 异常和中断简介 157
7.2 异常类型 158
7.3 中断管理简介 159
7.4 优先级定义 160
7.5 向量表和向量表重定位 165
7.6 中断输入和挂起行为 168
7.7 异常流程简介 171
7.7.1 接受异常请求 171
7.7.2 异常进入流程 171
7.7.3 执行异常处理 171
7.7.4 异常返回 172
7.8 中断控制用的NVIC寄存器细节 172
7.8.1 简介 172
7.8.2 中断使能寄存器 173
7.8.3 设置中断挂起和清除中断挂起 174
7.8.4 活跃状态 175
7.8.5 优先级 176
7.8.6 软件触发中断寄存器 176
7.8.7 中断控制器类型寄存器 177
7.9 用于异常和中断控制的SCB寄存器细节 177
7.9.1 SCB寄存器简介 177
7.9.2 中断控制和状态寄存器(ICSR) 178
7.9.3 向量表偏移寄存器(VTOR) 179
7.9.4 应用中断和复位控制寄存器(AIRCR) 179
7.9.5 系统处理优先级寄存器(SCB->SHP[0~11]) 180
7.9.6 系统处理控制和状态寄存器(SCB->SHCSR) 181
7.10 用于异常或中断屏蔽的特殊寄存器细节 182
7.10.1 PRIMASK 182
7.10.2 FAULTMASK 182
7.10.3 BASEPRI 183
7.11 设置中断的步骤示例 184
7.11.1 简单情况 184
7.11.2 向量表重定位时的情况 185
7.12 软件中断 185
7.13 要点和提示 186
第8章 深入了解异常处理 188
8.1 简介 188
8.1.1 关于本章 188
8.1.2 C实现的异常处理 188
8.1.3 栈帧 189
8.1.4 EXC_RETURN 191
8.2 异常流程 192
8.2.1 异常进入和压栈 192
8.2.2 异常返回和出栈 193
8.3 中断等待和异常处理优化 195
8.3.1 什么是中断等待 195
8.3.2 多周期指令执行时的中断 196
8.3.3 末尾连锁 196
8.3.4 延迟到达 196
8.3.5 出栈抢占 197
8.3.6 惰性压栈 197
第9章 低功耗和系统控制特性 199
9.1 低功耗设计 199
9.1.1 低功耗对微控制器有什么意义 199
9.1.2 低功耗系统需求 200
9.1.3 Cortex-M3和Cortex-M4处理器的低功耗特点 201
9.2 低功耗特性 201
9.2.1 休眠模式 201
9.2.2 系统控制寄存器(SCR) 202
9.2.3 进入休眠模式 202
9.2.4 唤醒条件 203
9.2.5 退出时休眠特性 204
9.2.6 挂起发送事件(SEVONPEND) 205
9.2.7 休眠扩展/唤醒延迟 205
9.2.8 唤醒中断控制器(WIC) 206
9.2.9 事件通信接口 207
9.3 在编程中使用WFI和WFE 211
9.3.1 何时使用WFI 211
9.3.2 使用WFE 212
9.4 开发低功耗应用 212
9.4.1 降低动态功耗 213
9.4.2 降低活跃周期 214
9.4.3 减小休眠模式电流 214
9.5 SysTick定时器 215
9.5.1 为什么要有SysTick定时器 215
9.5.2 SysTick定时器操作 215
9.5.3 使用SysTick定时器 217
9.5.4 其他考虑 218
9.6 自复位 219
9.7 CPU ID基本寄存器 220
9.8 配置控制寄存器 220
9.8.1 CCR简介 220
9.8.2 STKALIGN位 221
9.8.3 BFHFNMIGN位 221
9.8.4 DIV_O_TRP位 221
9.8.5 UNALIGN_TRP位 221
9.8.6 USERSETMPEND位 222
9.8.7 NONBASETHRDENA位 222
9.9 辅助控制寄存器 222
9.10 协处理器访问控制寄存器 224
第10章 OS支持特性 226
10.1 OS支持特性简介 226
10.2 影子栈指针 226
10.3 SVC异常 228
10.4 PendSV异常 232
10.5 实际的上下文切换 234
10.6 排他访问和嵌入式OS 243
第11章 存储器保护单元 246
11.1 MPU简介 246
11.1.1 关于MPU 246
11.1.2 使用MPU 246
11.2 MPU寄存器 247
11.2.1 MPU类型寄存器 248
11.2.2 MPU控制寄存器 248
11.2.3 MPU区域编号寄存器 249
11.2.4 MPU基地址寄存器 249
11.2.5 MPU区域基本属性和大小寄存器 250
11.2.6 MPU别名寄存器 253
11.3 设置MPU 253
11.4 存储器屏障和MPU配置 259
11.5 使用子区域禁止 260
11.5.1 允许高效的存储器划分 260
11.5.2 减少所需的区域总数 261
11.6 使用MPU时的注意事项 261
11.6.1 程序代码 261
11.6.2 数据存储器 262
11.6.3 外设 262
11.7 MPU的其他用法 262
11.8 与Cortex-M0+处理器中的MPU间的差异 262
第12章 错误异常和错误处理 264
12.1 错误异常简介 264
12.2 错误的原因 265
12.2.1 存储器管理(MemManage)错误 265
12.2.2 总线错误 266
12.2.3 使用错误 267
12.2.4 HardFault 267
12.3 使能错误处理 268
12.3.1 MemManage错误 268
12.3.2 总线错误 268
12.3.3 使用错误 268
12.3.4 HardFault 268
12.4 错误状态寄存器和错误地址寄存器 269
12.4.1 简介 269
12.4.2 MemManage错误信息 269
12.4.3 总线错误信息 270
12.4.4 使用错误信息 271
12.4.5 HardFault状态寄存器 271
12.4.6 调试错误状态寄存器(DFSR) 271
12.4.7 错误地址寄存器MMFAR和BFAR 272
12.4.8 辅助错误状态寄存器 273
12.5 分析错误 273
12.6 异常处理相关的错误 275
12.6.1 压栈 275
12.6.2 出栈 275
12.6.3 惰性压栈 276
12.6.4 取向量 276
12.6.5 非法返回 276
12.6.6 优先级和压栈或出栈错误 276
12.7 锁定 277
12.7.1 什么是锁定 277
12.7.2 避免锁定 278
12.8 错误处理 279
12.8.1 用于调试的HardFault 279
12.8.2 错误屏蔽 282
12.9 其他信息 282
12.9.1 运行具有两个栈的系统 282
12.9.2 检测栈溢出 283
第13章 浮点运算 285
13.1 关于浮点数 285
13.1.1 简介 285
13.1.2 单精度浮点数 285
13.1.3 半精度浮点数 286
13.1.4 双精度浮点数 287
13.1.5 Cortex-M处理器中的浮点支持 288
13.2 Cortex-M4浮点单元(FPU) 289
13.2.1 浮点单元简介 289
13.2.2 浮点寄存器简介 290
13.2.3 CPACR寄存器 290
13.2.4 浮点寄存器组 291
13.2.5 浮点状态和控制寄存器(FPSCR) 291
13.2.6 浮点上下文控制寄存器(FPU->FPCCR) 293
13.2.7 浮点上下文地址寄存器(FPU->FPCAR) 294
13.2.8 浮点默认状态控制寄存器(FPU->FPDSCR) 295
13.2.9 介质和浮点特性寄存器(FPU->MVFR0、FPU->MVFR1) 296
13.3 惰性压栈详解 296
13.3.1 惰性压栈特性的关键点 296
13.3.2 第1种情况:被打断的任务中没有浮点上下文 297
13.3.3 第2种情况:被打断的任务中有浮点上下文,ISR中没有 298
13.3.4 第3种情况:被打断的任务和ISR中都有浮点上下文 298
13.3.5 第4种情况:中断嵌套,且第2个中断处理中存在浮点上下文 299
13.3.6 第5种情况:中断嵌套,且两个中断处理中都存在浮点上下文 299
13.3.7 惰性压栈的中断 299
13.3.8 浮点指令的中断 300
13.4 使用浮点单元 301
13.4.1 CMSIS-Core中的浮点支持 301
13.4.2 用C语言实现浮点编程 302
13.4.3 编译器命令行选项 302
13.4.4 ABI选项:Hard-vfp和Soft-vfp 303
13.4.5 特殊的FPU模式 304
13.5 浮点异常 305
13.6 要点和提示 307
13.6.1 微控制器的运行时库 307
13.6.2 调试操作 308
第14章 调试和跟踪特性 309
14.1 调试和跟踪特性简介 309
14.1.1 什么是调试特性 309
14.1.2 什么是跟踪特性 310
14.1.3 调试和跟踪特性总结 311
14.2 调试架构 312
14.2.1 CoreSight调试架构 312
14.2.2 处理器调试接口 313
14.2.3 调试端口(DP)、访问端口(AP)和调试访问端口(DAP) 314
14.2.4 跟踪接口 315
14.2.5 CoreSight的特点 316
14.3 调试模式 317
14.4 调试事件 318
14.5 断点特性 320
14.6 调试部件简介 320
14.6.1 处理器调试支持 320
14.6.2 Flash补丁和断点(FPB)单元 323
14.6.3 数据监视点和跟踪(DWT)单元 326
14.6.4 指令跟踪宏单元 328
14.6.5 嵌入式跟踪宏单元(ETM) 331
14.6.6 跟踪端口接口单元(TPIU) 332
14.6.7 ROM表 333
14.6.8 AHB访问端口(AHB-AP) 335
14.7 调试操作 336
14.7.1 调试连接 336
14.7.2 Flash编程 336
14.7.3 断点 336
第15章 Keil ARM微控制器开发套件入门 337
15.1 简介 337
15.2 典型的程序编译流程 338
15.3 μVision入门 339
15.4 工程选项 347
15.4.1 Device选项 348
15.4.2 Target选项 348
15.4.3 Output选项 349
15.4.4 Listing选项 350
15.4.5 User选项 350
15.4.6 C/C++选项 350
15.4.7 Asm选项 351
15.4.8 Linker选项 352
15.4.9 Debug选项 353
15.4.10 Utilities选项 354
15.5 使用IDE和调试器 354
15.6 使用指令集模拟器 357
15.7 在SRAM中运行程序 358
15.8 优化选项 362
15.9 其他信息和要点 363
15.9.1 栈和堆存储大小配置 363
15.9.2 其他信息 363
第16章 IAR Embedded Workbench for ARM入门 364
16.1 IAR Embedded Workbench for ARM简介 364
16.2 典型的程序编译流程 364
16.3 创建简单的blinky工程 366
16.4 工程选项 371
16.5 提示和要点 373
第17章 GCC入门 374
17.1 GCC工具链 374
17.2 典型开发流程 374
17.3 创建简单的blinky工程 376
17.4 命令行选项简介 377
17.5 Flash编程 379
17.5.1 使用Keil MDK-ARM 379
17.5.2 使用第三方Flash编程工具 380
17.6 Keil MDK-ARM和ARM嵌入式处理器GNU工具一起使用 381
17.7 CoIDE和ARM嵌入式处理器GNU工具一起使用 383
17.8 基于gcc的商业版开发组件 388
17.8.1 Atollic TrueSTUDIO for ARM 388
17.8.2 Red Suite 389
17.8.3 CrossWorks for ARM 389
第18章 输入和输出软件实例 390
18.1 产生输出 390
18.2 重定向到指令跟踪宏单元(ITM) 390
18.2.1 简介 390
18.2.2 Keil MDK-ARM 391
18.2.3 IAR Embedded Workbench 394
18.2.4 GCC 395
18.3 半主机 396
18.4 重定向到外设 399
第19章 使用嵌入式操作系统 407
19.1 嵌入式OS简介 407
19.1.1 什么是嵌入式OS 407
19.1.2 何时使用嵌入式OS 407
19.1.3 CMSIS-RTOS的作用 408
19.2 Keil RTX Real-Time Kernel 409
19.2.1 关于RTX 409
19.2.2 特性简介 410
19.2.3 RTX和CMSIS-RTOS 410
19.2.4 线程 411
19.3 CMSIS-RTOS实例 412
19.3.1 具有两个线程的简单CMSIS-RTOS 412
19.3.2 线程间通信简介 418
19.3.3 信号事件通信 418
19.3.4 互斥体(MUTEX) 420
19.3.5 信号量 422
19.3.6 消息队列 424
19.3.7 邮件队列 425
19.3.8 内存池管理特性 427
19.3.9 通用等待函数和超时数值 428
19.3.10 定时器特性 429
19.3.11 访问非特权设备 431
19.4 OS感知调试 432
19.5 疑难解答 434
19.5.1 栈大小和栈对齐 434
19.5.2 特权等级 434
19.5.3 其他问题 434
第20章 汇编和混合语言工程 435
20.1 汇编代码在工程中的使用 435
20.2 C和汇编间的交互 435
20.3 汇编函数的结构 437
20.4 例子 438
20.4.1 ARM工具链的简单例子(Keil MDK-ARM、DS-5) 438
20.4.2 ARM嵌入式处理器GNU工具的简单例子 440
20.4.3 访问特殊寄存器 441
20.4.4 数据存储器 442
20.4.5 Hello world 443
20.4.6 显示十六进制和十进制的数据 444
20.4.7 NVIC中断控制 446
20.4.8 无符号整数平方根 447
20.5 混合语言工程 448
20.5.1 从汇编中调用C函数 448
20.5.2 从C中调用汇编函数 449
20.5.3 嵌入汇编(Keil MDK-ARM/ARM DS-5 professional) 449
20.5.4 内联汇编 450
20.6 内在函数 451
20.7 习语识别 452
第21章 ARM Cortex-M4和DSP应用 454
21.1 微控制器上的DSP 454
21.2 点积实例 454
21.3 传统DSP处理器的架构 456
21.4 Cortex-M4的DSP指令 459
21.4.1 寄存器和数据类型 459
21.4.2 小数运算 460
21.4.3 SIMD数据 461
21.4.4 加载和存储指令 462
21.4.5 算术指令 462
21.4.6 Cortex-M4的一般优化策略 469
21.4.7 指令限制 471
21.5 为Cortex-M4编写优化的DSP代码 471
21.5.1 Biquad滤波器 471
21.5.2 快速傅里叶变换 475
21.5.3 FIR滤波器 479
第22章 使用ARM CMSIS-DSP库 486
22.1 DSP库简介 486
22.2 预构建的二进制代码 486
22.3 函数命令规则 487
22.4 获得帮助 487
22.5 例1:DTMF解调 487
22.5.1 产生正弦波 488
22.5.2 使用FIR滤波器进行解析 488
22.5.3 使用FFT进行解析 490
22.5.4 使用Biquad滤波器进行解析 492
22.5.5 DTMF示例代码 493
22.6 例2:最小二乘法运动跟踪 495
第23章 高级话题 500
23.1 决断和跳转 500
23.1.1 条件跳转 500
23.1.2 复杂的判决树 502
23.2 性能考虑 503
23.3 双字栈对齐 505
23.4 信号量设计的各种方法 506
23.4.1 用SVC服务实现信号量 506
23.4.2 使用位段实现信号量 507
23.5 非基本线程使能 507
23.6 中断服务的重入 510
23.7 C语言实现的位数据处理 513
23.8 启动代码 515
23.9 栈溢出检测 516
23.9.1 工具链的栈分析 516
23.9.2 栈的测试分析 516
23.9.3 根据栈布局检测栈溢出 516
23.9.4 使用MPU 517
23.9.5 使用DWT和调试监控异常 517
23.9.6 OS上下文切换中的栈检查 517
23.10 Flash补丁特性 517
23.11 Cortex-M3和Cortex-M4处理器的版本 520
23.11.1 简介 520
23.11.2 Cortex-M3 r0p0到r1p0/r1p1的变动 520
23.11.3 Cortex-M3 r1p1到r2p0的变动 521
23.11.4 Cortex-M3 r2p0到r2p1的变动 523
23.11.5 Cortex-M4 r0p0到r0p1的变动 523
第24章 软件移植 524
24.1 简介 524
24.2 从8位/16位MCU移植到Cortex-M MCU 524
24.2.1 架构差异 524
24.2.2 一般调整 525
24.2.3 存储器大小需求 526
24.2.4 8位或16位微控制器不再适用的优化 527
24.2.5 例子:从8051移植到ARM Cortex-M 527
24.3 从ARM7 TDMI到Cortex-M3/M4的软件移植 529
24.3.1 硬件差异简介 529
24.3.2 汇编语言文件 531
24.3.3 C语言文件 533
24.3.4 预编译的目标文件和库 533
24.3.5 优化 534
24.4 不同Cortex-M处理器间的软件移植 534
24.4.1 不同Cortex-M处理器间的差异 534
24.4.2 所需的软件变动 539
24.4.3 嵌入式OS 539
24.4.4 创建Cortex-M处理器的可移植程序代码 539
参考文献 541