ARM处理器--寒枫25年6月
第一章 嵌入式系统基础
1.1 定义与要素
嵌入性、专用性与计算机系统是嵌入式系统的三个基本要素。
嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可剪裁,对功能、可靠性、成本、体积、功耗等有严格要求的嵌入到对象体系中的专用计算机系统。
1.2 硬件组成
嵌入式系统的硬件层的核心是嵌入式微处理器。
嵌入式微处理器的两种体系结构
冯诺依曼体系结构是将程序指令和数据存储器合并在一起的存储器结构(取指和取数据要分周期进行,不能同时进行,单次取指令长度和取数据的长度相同。
哈佛,程序指令和数据分开存储,指令和数据有不同的数据宽度。注意:arm9 是哈佛结构,但整体板子是冯诺依曼结构。
指令系统:精简指令集 RISC 和复杂指令集 CISC 的主要区别
CISC:复杂指令集具有大量的指令和寻址方式。指令长度不固定,执行需要多个周期。 指令的执行需要调用一段微程序,用于特定目的的专用寄存器,处理器能够直接处理存储器中的数据。
RISC:精简指令集,一个周期执行一条指令,通过简单指令的组合实现复杂操作,指令长度固定。流水线每周期前进一步,具有更多通用寄存器,独立的 Load/Store 指令完成数据在寄存器和外部存储器之间的传输。
嵌入式处理器分类
嵌入式微处理器 MPU,嵌入式微控制器 MCU(单片机),嵌入式 DSP 处理器(专用于通信),SOC 片上系统
1.3 软件组成
由嵌入式操作系统和嵌入式应用软件两大部分组成。
嵌入式系统软件一般包含四个层面:应用程序、应用程序接口 API、实时操作系统 RTOS、硬件抽象层(HAL)
嵌入式操作系统
实时操作系统
是指能在确定的时间内执行其功能并对外部的异步事件做出响应的计算机系统。可分为软实时和硬实时,抢占型和非抢占型
(1)系统响应时间:系统收到处理要求到系统给出应答信号的时间。
(2)任务换道时间:任务之间切换使用的时间。
(3)中断延迟:计算机接收到中断信号到操作系统作出响应,并完成换道转入中断服务程序的时间。
实时操作系统中的任务有四个状态:运行、就绪、挂起、冬眠。
① 运行:获得 CPU 的控制权。
② 就绪:进入任务就绪(等待)队列,等待通过调度转为运行状态。
③ 挂起:任务发生阻塞,移出任务就绪队列,等待系统实时事件的发生而唤醒,从而转为 就绪 或 运行。
④ 冬眠:任务完成 或 错误 等原因被清除的任务,也可以认为是系统中不存在的任务。
在嵌入式操作系统中,任务相当于 Linux 系统的线程。在所有的操作系统中,线程是一个单一顺序的执行流,是分配运行资源的基本单位。在 Linux 和 Windows 之类的操作系统中,一个或多个线程构成一个进程共享地址空间和全局变量,而嵌入式系统中一般没有进程的概念,也可以说整个系统就是一个进程,共享所有地址空间和全局变量。
1.4 嵌入式系统的特点
专用性,强调实时性,可裁减性,可靠性要求高,功耗低
第二章 ARM 处理器及系统结构
2.1 ARM 处理器简介
ARM 是一个公司的名称,ARM 是一类微处理器的通称,ARM 是一种技术的名称
2.2 ARM 微处理器系列
规则:ARM{x}{y}{z}{T}{D}{M}{I}{E}{J}{F}{-S}
x -- 处理器系列
y -- 存储管理/保护单元
z -- cache
T -- 支持Thumb指令集
D -- 支持片上调试
M -- 支持快速乘法器
I -- 支持Embedded ICE,支持嵌入式跟踪调试
E -- 支持增强型DSP指令
J -- 支持Jazelle
F -- 具备向量浮点单元VFP
-S -- 可综合版本
ARM 内核不是一个纯粹的 RISC 体系结构,ARM 指令集与纯粹的 RISC 的定义有以下几个不同。
① 一些特定指令的周期数可变,并不是每条 ARM 指令都是单周期的。
② 内嵌的桶形移位器产生了更为复杂的指令,扩展了指令的功能,因此改善了内核的性能。
③ 支持 16 位的 Thumb 指令集,提高了代码密度。
④ 支持条件执行:每条指令都可以设置一个执行条件,只有条件满足时才执行。
⑤ 增强指令:一些功能强大的数字信号处理指令被加入到 ARM 指令集中。
2.3 ARM9 处理器内核
ARM9 的 5 级流水线
5级流水线:取指、译码、执行、缓冲/数据、回写,减少了在每个时钟内必须完成的最大工作量,进而允许使用较高的时钟频率。执行效率高。
在它之前的三级流水线是指:取指、译码、执行。对比如下图:
5级流水线具体操作如下:**
取指:指令从存储器中取出,放入指令流水线,并将指令地址递增;
译码:指令译码,从寄存器堆中读取寄存器操作数;
执行:把一个操作数移位,产生 ALU 的结果。如果指令是 Load 或 Store,在 ALU 中计算存储器的地址
缓存/数据:如果需要,则访问数据存储器;否则,ALU 的结果只是简单地缓冲一个时钟周期,以便使所有指令具有同样的流水线流程;
回写:将指令产生的结果写回到寄存器堆,包括任何从寄存器读出的数据
2.4 ARM 处理器工作状态
ARM 状态和 Thumb 状态,分别用于执行对应指令集的指令
2.5 ARM 处理器运行模式
7 种模式,分为用户模式和特权模式
2.6 ARM 寄存器
汇编语言中 R0~R13 是通用寄存器,不随体系结构而改变
(1)未分组寄存器(对任意处理器模式,都访问该物理寄存器),包括 R0R7;
(2)分组寄存器,包括 R8R14
寄存器 R13 通常用作堆栈指针,称作 SP
链接寄存器 R14,用来保存子程序或异常的返回地址
寄存器 R15 用作程序计数器(PC)。程序计数器 R15(即 PC)总是指向“正在取指”的指令,人们习惯性约定将“正在执行的指令作为参考点”,称之为当前第 1 条指令。因此,PC 总是指向第 3 条指令。
2.7 存储器
存储器统一编址。目前几乎所有 MCU 的程序都存储在 Flash 中。
片外 Flash:NOR 和 NAND,片内 Flash
2.8 中断和异常(不考)
中断是主机与外设进行数据通信的重要机制,它负责处理处理器外部的事件 ;异常实质上也是一种中断,它主要负责处理处理器内部事件。由内部事件引起的中断叫做异常。
2.9 ARM 的中断(异常)
ARM 的中断向量表内存放的是响应异常和中断的转移指令而不是中断向量地址。
高端向量是 ARM 架构可选配置,可以通过硬件外部输入管脚来配置是低端向量还是高端向量。
1、处理器响应中断的三个条件:
(1)处理器程序状态寄存器的中断屏蔽标志处于非屏蔽状态;
(2)没有更高级的中断请求正在响应或正在发出、正挂起;
(3)处理器在现行指令执行结束后。
2、执行进入异常的操作:
当有中断请求发生且满足上述条件时,计算机系统就会响应中断请求,并自动将被中断程序的下一条指令地址(断点地址)保存和关闭中断;接下来便将自中断向量表查询得到的与该中断源对应的中断向量送入 PC,并转去执行中断服务程序。
当执行到中断服务程序末尾时,执行中断返回指令或跳转指令,把保存的断点地址送回 PC,以在断点处继续执行被中断的程序。
3、结合 ARM 处理器来说:
(1)在适当的 LR 中保存断点的地址,当异常入口来自:无论是 ARM 状态还是 Thumb 状态,ARM 都将当前 PC 寄存器的值(运行指令地址加 4 或加 8)复制到 LR 中;
(2)把当前程序状态寄存器(CPSR)中的内容保存到模式私有存器 SPSP 中(做备份用);
(3)将寄存器 CPSR 中的 MODE 域设置为中断(异常)应进入的运行模式;
(4)对 CPSR 的 I 位和 E 位进行相应的设置,以防止再次响应同级或低优先级中断的中断请求。
(5)强制 PC 从相关的异常向量处取指,到中断向量表中获取中断向量,转向用户所编写的中断(异常)服务程序。
ps:异常总是在 ARM 状态中进行处理。当处理器处于 Thumb 状态时发生了异常,在异常向量地址装入 PC 时,会自动切换到 ARM 状态。
第三章 ARM 指令集
3.1 ARM 指令集简介
ARM 指令集 ,所有的指令长度都是 32 位 ,并且大多数指令都在一个单独指令周期内执行,条件执行。ARM 微处理器的指令集是加载/存储型的(数据从内存加载到寄存器后再操作,数据处理指令只能操作寄存器数据),一次最多可以完成 16 个寄存器的数据传送。
3.1.1 ARM 指令格式
<opcode> {<cond>} {S} {<Rd>} { ,<Rn>} {,<OP2>}
{<cond>}表示指令执行的条件域,如EQ、NE
{S}决定指令的执行结果是否影响CPSR的值
机器码
后缀
S 后缀:指令执行后程序状态寄存器的条件标志位将被刷新。
!后缀:在指令中的地址表达式后。指令执行后,基址寄存器中的地址值将发生变化)=指令执行前的值+地址偏移量 B 后缀的含义是:指令所涉及的数据是一个字节,不是一个字或半字。
3.1.2 ARM 指令的条件码
根据 CPSR 中的条件标志位的状态和指令的条件域 有条件地执行。
3.1.3 ARM 指令分类
ARM 指令可以分为:分支指令、数据处理指令、存储访问指令、协处理器指令和杂项指令五类。 ① 分支指令 分支指令用于控制程序的执行流程、实现 ARM 代码与 Thumb 代码之间进行切换。
② 数据处理指令 数据处理指令在通用寄存器上执行计算,主要分为 3 种:算术/逻辑指令、比较指令和乘法指令。
③ 存储访问指令 用于加载/存储存放于 MCU 片外存储系统中的数据。加载指令用于从内存中读取数据放入寄存器中,存储指令用于将寄存器中的数据保存到内存中。
④ARM 协处理器指令 ARM 协处理器指令用于控制外部的协处理器。包括: 数据处理指令:启动一个协处理器专用的内部操作。 数据转移指令:使数据在协处理器和存储器之间进行转移。 寄存器转移指令:协处理器值转移到 ARM 寄存器或 ARM 寄存器的值转移到协处理器。
⑤ 杂项指令 包括状态寄存器转移指令和异常中断产生指令。 状态寄存器转移指令将 CPSR 或 SPSR 的内容转移到一个通用寄存器,或者反过来将通用寄存器的内容写入 CPSR 或 SPSR 寄存器。 ARM 有 两条 异常中断产生指令,分别为 软中断指令 SWI 和 断点中断指令 BKPT。
3.2 指令的寻址方式
3.2.1 立即数寻址
立即数寻址也叫立即寻址,操作数本身就在指令中给出,取出指令也就取到了操作数,这个操作数被称为立即数。 立即数要求以“#”为前缀,并附带 0x,0b 等。
例:ADD R0,R0,#1 ;R0←R0 + 1
MOV R0, #15 ; R0←#15
构造 32 位立即数:
immed_8:占 8 位,是一个无符号整数,代表一个 8 位位图,也就是一个范围在 0 - 255 之间的数值。
rot:占 4 位,是移位因子,其取值范围是 0 - 15。
有效立即数:<immediate>=immed_8`循环右移`(2×rot)
例如:`immed_8 = 0x0F`(二进制为`0000 1111`),`rot = 2`。
- 首先计算移位值:`2×rot = 4`。
- 然后将`immed_8`循环右移 4 位,得到`1111 0000`,这就是最终的立即数。
当立即数数值在0到0xFF范围时,令immed_8=<immediate>,rot=0。其它情况下,汇编编译器选择使rot数值最小的编码方式
合法立即数:立即数能由一个 8 位位图通过循环右移偶数位得到
3.2.2 寄存器寻址
寄存器寻址就是利用寄存器中的数值作为操作数。
3.2.3 寄存器移位寻址
当第二操作数为寄存器型时,在执行寄存器寻址操作时,也可以对第二操作数寄存器进行移位。
ADD Rd, Rn, Rm,{<shift>}
Rm称为第二操作数寄存器
<shift> 用来指定移位类型和移位位数,有两种形式:
5位立即数 (其值小于32)
寄存器(用Rs表示)(其值小于32)
例:ADD R3,R2,R1,LSR #2 ;R3←R2+(R1右移2位)
第二操作数移位方式
共有 6 种移位方式: —LSL 逻辑左移 —LSR 逻辑右移 —ASL 算术左移 —ASR 算术右移 —ROR 循环右移 —RRX 带扩展的循环右移
RRX:带进位位的循环右移(Rotate Right Extended) 。把寄存器中的 32 位数据整体向右移动 1 位,最右边的 1 位会被移出寄存器,但不会丢失,它会被送到 C 标志位。原来 C 标志位的值会被填充到寄存器最左边的空位上。
第二操作数的移位位数
移位位数可以用立即数方式或者寄存器方式给出,其值应为 0---31。
3.2.4 寄存器间接寻址
寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器中。
3.2.5 基址变址寻址
将基址寄存器的内容与指令中给出的地址偏移量相加,得到操作数所在的存储器的有效地址。常用于访问某基地址附近的地址单元。(4K 范围的偏移)
偏移地址方式
有三种加偏址的方式:前变址、自动变址和后变址寻址方式。 1、前变址模式(不修改基址寄存器): 先基址+偏址,生成操作数地址,再做指令指定的操作。也叫前索引偏移。
2、自动变址模式(修改基址寄存器): 先基址+偏移,生成操作数地址,做指令指定的操作。然后自动修改基址寄存器。
LDR R0,[R1,#4]! ;R0←mem32 [R1+4]
;R1←R1+4
! ——表示更新基址寄存器。
3、后变址模式(修改基址寄存器): 基址寄存器不加偏移作为操作数地址。完成指令操作后,用(基址+偏移)的值修改基址寄存器。
偏移地址形式
可以是一个立即数,也可以是另一个寄存器,并且还可以是寄存器移位操作。常用的是立即数偏移的形式。
3.2.6 多寄存器寻址
采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。这种寻址方式是多寄存器传送指令 LDM/STM 的寻址方式,这种寻址方式中用一条指令最多可传送 16 个通用寄存器的值。连续的寄存器间用“-”连接,否则用“,”分隔。
例 LDMIAR0!,{R1-R4}
;R1←[R0]、R2←[R0+4]、R3←[R0+8]、R4←[R0+12]
!对于所有 LDM/STM 指令而言,寄存器序号低的,在低地址单元,序号大的在高地址单元!与书写顺序无关!
4 种寻址操作
LDMIA/STMIA Increment After(先传送,后地址加 4)
LDMIB/STMIB Increment Before(先地址加 4 ,后传送)
LDMDA/STMDA Decrement After(先传送,后地址减 4)
LDMDB/STMDB Decrement Before (先地址减 4,后传送)

3.2.7 堆栈寻址
堆栈是一种数据结构,按后进先出(Last In First Out, LIFO)的方式工作,使用一个称作堆栈指针的专用寄存器指示当前的操作位置,堆栈指针总是指向栈顶。 堆栈可分为两种增长方式: •向上生长:向高地址方向生长,称为递增堆栈。 •向下生长:向低地址方向生长,称为递减堆栈。 根据堆栈指针指向的数据位置的不同,可分为: •满堆栈:堆栈指针指向最后压入堆栈的有效数据项,称为满堆栈; •空堆栈:堆栈指针指向下一个待压入数据的空位置,称为空堆栈。 这样就有 4 种类型的堆栈表示递增和递减的满和空堆栈的各种组合,且刚好与 4 种 STM 操作对应。
3.2.8 相对寻址
与基址变址寻址方式相类似,相对寻址以程序计数器 PC 的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。
BL SUBRl ;调用到SUBRl子程序
. . .; SUBRl经编译后为24位有符号数
SUBR1 … …
… …
MOV PC, LR ;返回
第四章 ARM 伪指令
4.1 伪指令概述
伪指令:专门用于指导汇编器进行汇编工作的指令,这些指令不形成机器码指令,只是在汇编器进行汇编工作的过程中起作用。 两个特征:(1)伪指令是一条指令; (2)伪指令没有指令代码。 本质区别:指令经过编译后会有对应的指令代码,而伪指令经过编译后没有对应的指令代码。伪指令是为汇编器服务的,用于指导汇编器的汇编工作。 作用:(1)程序定位的作用;(2)为非指令代码进行定义;(3)为程序完整性做标注;(4)有条件的引导程序段。
4.2 通用伪指令
通用伪指令用于协助汇编器生成目标代码,不直接对应 CPU 指令,但影响代码结构和数据布局。
变量定义伪指令
全局变量定义:
GBLA 变量名 ; 定义全局数字变量(初始化为0)
GBLL 变量名 ; 定义全局逻辑变量(初始化为FALSE)
GBLS 变量名 ; 定义全局字符串变量(初始化为空)
局部变量定义:
LCLA 变量名 ; 定义局部数字变量(初始化为0)
LCLL 变量名 ; 定义局部逻辑变量(初始化为FALSE)
LCLS 变量名 ; 定义局部字符串变量(初始化为空)
变量赋值:
变量名 SETA 表达式 ; 给数字变量赋值(如:Count SETA 10)
变量名 SETL 逻辑值 ; 给逻辑变量赋值(如:Flag SETL {TRUE})
变量名 SETS 字符串 ; 给字符串变量赋值(如:Msg SETS "Hello")
示例:
GBLA Num ; 定义全局数字变量
Num SETA 256 ; 赋值为256
GBLL IsReady ; 定义全局逻辑变量
IsReady SETL {TRUE}; 设置为真
GBLS Message ; 定义全局字符串变量
Message SETS "ARM Assembly" ; 设置字符串
数据结构伪指令
内存表定义:
MAP 基地址, 寄存器 ; 定义结构化内存表(可用^代替MAP)
FIELD 大小 ; 定义内存表中的数据域
示例:
MAP 0x40000000, R9 ; 定义基地址为0x40000000,使用R9作为基址寄存器
Data1 FIELD 4 ; 定义4字节数据域
Data2 FIELD 4 ; 定义4字节数据域
Data3 FIELD 8 ; 定义8字节数据域
; 使用方式
LDR R0, [R9, #Data1] ; 加载Data1的值
STR R1, [R9, #Data2] ; 存储R1到Data2
内存分配:
SPACE 大小 ; 分配连续内存并初始化为0(如:Buf SPACE 100)
DCB 值1, 值2, ... ; 分配内存并初始化(如:Msg DCB 'H','e','l','l','o')
DCD 值1, 值2, ... ; 分配字(4字节)内存并初始化(如:Array DCD 1,2,3)
DCDU 值1, 值2, ... ; 同上,但不更新基址寄存器(U=Unindexed)
控制流伪指令
条件汇编:
WHILE 条件表达式 ; 条件满足时重复汇编
... 代码块 ...
WEND ; WHILE结束标记
示例:
GBLA Count
Count SETA 1
WHILE Count LE 10 ; 当Count ≤ 10时
DCD Count ; 生成数据
Count SETA Count + 1
WEND
代码结构伪指令
对齐控制:
ALIGN [对齐方式] ; 按指定方式对齐(如:ALIGN 4 按4字节对齐)
段定义:
AREA 段名, 属性1, 属性2, ... ; 定义代码段或数据段
; 示例:
AREA MyCode, CODE, READONLY ; 定义只读代码段
AREA MyData, DATA, READWRITE ; 定义读写数据段
程序入口:
ENTRY ; 标记程序入口点(一个源文件只能有一个ENTRY)
其他常用伪指令
寄存器列表:
寄存器名 RLIST {寄存器1, 寄存器2, ...} ; 定义寄存器列表
; 示例:
Regs RLIST {R0-R7, LR} ; 定义寄存器列表
PUSH Regs ; 压栈保存多个寄存器
POP Regs ; 出栈恢复多个寄存器
文字池:
LTORG ; 声明文字池(数据缓冲池)开始
4.3 与 ARM 指令相关的宏指令
ADR 指令用于将一个 近地址值 传递到一个寄存器中。
中等范围的地址读取宏指令 ADRL
大范围的地址读取宏指令 LDR
4.4 ARM 工程
在汇编语言程序设计中,每一条指令的助记符可以全部用大写或全部用小写 ,但不允许在一条指令中大小写混用 。标号要顶格。
ELF(Executable and Linking Format):可执行连接格式。 .o ELF 格式的目标文件
4.5 ARM 程序框架
ARM 汇编程序设计模板要点
AREA example,CODE,READONLY
;定义代码段,一个ARM汇编程序至少有一个代码段
ENTRY ;定义程序入口点
……
……
END ;汇编语言程序结束
当所有的系统初始化工作完成之后,就需要把程序流程转入主应用程序。最简单的方法是,在汇编语言程序末尾使用跳转指令 B 或 BL 直接从启动代码转移到 C/C++ 程序入口。
B main ;跳转到 C/C++程序
同时在汇编文件中有如下代码:
IMPORT main
4.6 ARM 汇编语言程序设计
ARM(Thumb)汇编语言的语句格式为:
{<标号>} <指令或伪指令> {;注释}
- 指令助记符必须全部大写或小写(如
MOV或mov,但不可MoV)。 - 标号需顶格书写,用于标识代码位置(如函数入口、跳转目标)。
- 长语句可分行,行尾用
\连接,但\后不可有任何字符。
分支
分支指令用于改变程序执行流程,ARM 支持条件分支和无条件分支。
语法格式:
B{条件码} 目标地址 ; 无条件/条件跳转
BL{条件码} 子程序名 ; 带链接的跳转(保存返回地址到LR)
BX{条件码} Rn ; 带状态切换的跳转(可从ARM切换到Thumb)
**条件码:**EQ(相等)、NE(不等)、GT(大于)、LT(小于)等,基于 CPSR 标志位判断。
循环
ARM 汇编中通过分支指令实现循环,常见结构有计数循环和条件循环。
示例 :计数循环(计算 1 到 10 的和)
MOV R0, #1 ; 初始化计数器i=1
MOV R1, #0 ; 初始化累加器sum=0
loop:
ADD R1, R1, R0 ; sum += i
ADD R0, R0, #1 ; i++
CMP R0, #11 ; 比较i与11
BLT loop ; 如果i < 11,继续循环
子程序及其调用
子程序是模块化编程的核心,ARM 通过BL指令调用子程序,并通过返回地址(LR)实现返回。 为进行识别,子程序的第 1 条指令之前必须赋予一个标号,以便其他程序可以用这个标号调用子程序。 为使子程序执行完毕能返回主程序的调用处,子程序末尾处应有 MOV、B、BX、LDMFD 等指令,并在指令中将返回地址重新复制到 PC 中。
调用流程:
- 主程序通过
BL 子程序名调用,自动将下一条指令地址存入 LR(R14)。 - 子程序执行任务,使用
MOV PC, LR或BX LR返回。 - 若子程序需使用寄存器,需先压栈保存(PUSH),返回前恢复(POP)。
4.7 C/C++语言和汇编语言的混合编程。
汇编程序访问全局 C 变量
一般来说,汇编语言程序与 C 语言程序不在同一个文件上,所以实质上这是一个引用不同文件定义的变量问题。解决这个问题的办法就是使用关键字 IMPORT 和 EXPORT。 在 C 程序中声明的全局变量可以被汇编程序通过地址间接访问,具体访问方法如下。 使用 IMPORT 伪指令声明该全局变量; 使用 LDR 宏指令读取该全局变量的内存地址,通常该全局变量的内存地址值存放在程序的数据缓冲池中; 根据该数据的类型,使用相应的 LDR 指令读取该全局变量的值;使用相应的 STR 指令修改该全局变量的值。
各数据类型及其对应的 LDR/STR 指令如下。
① 对于无符号的 char 类型的变量通过指令 LDRB/STRB 来读写;
② 对于无符号的 short 类型的变量通过指令 LDRH/STRH 来读写;
③ 对于 int 类型的变量通过指令 LDR/STR 来读写;
④ 对于有符号的 char 类型的变量通过指令 LDRSB 来读取;
⑤ 对于有符号的 char 类型的变量通过指令 STRB 来写入;
⑥ 对于有符号的 short 类型的变量通过指令 LDRSH 来读取;
⑦ 对于有符号的 short 类型的变量通过指令 STRH 来写入;
⑧ 对于小于 8 个字的结构型变量,可以通过一条 LDM/STM 指令来读/写整个变量;
⑨ 对于结构型变量的数据成员,可以使用相应的 LDR/STR 指令来访问,这时必须知道该数据成员相对于结构型变量开始地址的偏移量。
ATPCS 规定,ARM 的数据堆栈为 FD 型堆栈,即递减满堆栈。 ATPCS 标准规定,对于参数个数不多于 4 的函数,编译器必须按参数在列表中的顺序,自左向右为它们分配寄存器 R0~R3。其中函数返回时,R0 还被用来存放函数的返回值。 如果函数的参数多于 4 个,那么多余的参数则按自右向左的顺序压入数据堆栈,即参数入栈顺序与参数顺序相反。
汇编子程序
嵌入式汇编
_ _asm return–type function–name(parameter-list)
{
asm (
"汇编指令序列\n"
: 输出操作数列表
: 输入操作数列表
: 被修改的寄存器列表
);
return 返回值;
}
return–type:函数返回值类型,C语言中的数据类型;
function–name:函数名;
parameter-list:函数参数列表。
嵌入式汇编程序是一个编写在 C 程序外的单独汇编程序,该程序段可以像函数那样被 C 程序调用。 与内联汇编不同,嵌入式汇编具有真实汇编的所有特性,数据交换符合 ATPCS 标准
参数名只允许使用在参数列表中,不能用在嵌入式汇编函数体内。
内联汇编
__asm__ (
"汇编指令序列\n"
: 输出操作数列表
: 输入操作数列表
: 被修改的寄存器列表
);
__asm__:GCC 编译器关键字,表示内联汇编。
如果在内联汇编程序指令中出现了以某个寄存器名称命名的操作数,那么它被叫做虚拟寄存器,而不是实际的物理寄存器。编译器在生成和优化代码的过程中,会给每个虚拟寄存器分配实际的物理寄存器,但这个物理寄存器可能与在指令中指定的不同。唯一的一个例外就是状态寄存器 PSR ,任何对 PSR 的引用总是执行指向物理 PSR;
附
MDK Arm Keil | MDK-Community edition 基于 Keil µVision 开发环境
DS-5 https://developer.arm.com/downloads/-/arm-development-studio-downloads 基于 Eclipse 开发环境。
常用 IDE:IAR,Embedded Studio,STM32CubeIDE
第五章 S3C2440A
5.1 S3C2440 信号描述
(1)管脚分配 289 个引脚
(2)总线控制信号
5.2 S3C2440 存储控制器
(1)小/大端(通过软件选择);
(2)地址空间:每 BANK 有 128MB(共有 1GB/8BANKS);
(3)除 BANK0(只能是 16/32 位宽)之外,其他 BANK 都具有可编程的访问大小(8/16/32 位);
(4)总共 8 个存储器 BANK,6 个是 ROM、SRAM 等类型存储器 BANK,剩下的 2 个可以为 ROM、SRAM、SDRAM 等存储器 BANK;
(5)7 个固定的存储器 BANK 的起止地址;
(6)最后一个 BANK 的起始地址是可调整的;
(7)最后 2 个 BANK 的大小是可编程的;
(8)所有存储器 BANK 的访问周期都是可编程的;
(9)总线访问周期可以通过插入外部等待(nWAIT)来延长;
(10)支持 SDRAM 的自刷新和掉电模式。
5.3 NAND FLASH 控制器
S3C2440A 的驱动代码可以在执行在存储在外部的 NAND Flash 存储器上的代码。为了支持 NAND Flash 的 boot loader,S3C2440A 配备了一个内部的 SRAM 缓冲器名为 “Steppingstone”(bootram)。
启动时,NAND Flash 上的前 4KByte 字节 将被装载到 Steppingstone 中,并且装载到 Steppingstone 上的启动代码会被执行。
一般情况下,启动代码会拷贝 NAND Flash 上的内容到 SDRAM 中,在引导代码执行完毕后就跳转到 SDRAM 执行。使用硬件的 ECC(纠错码)对 NAND Flash 的数据进行有效性检查。在完成拷贝的基础上,主程序将在 SDRAM 上被执行。
5.4 时钟和功率管理
能产生系统所需时钟,包括 FCLK、HCLK 和 PCLK,有两个 PLL。系统支持正常、低速、空闲和掉电四种模式,可降低功耗
时钟和功率管理模块由 三部分 组成:时钟控制、USB 控制 和 功率控制。
S3C2440 的时钟控制逻辑能够产生系统所需要的时钟,包括:CPU 的 FCLK、AHB 总线接口的 HCLK 和 APB 总线接口的 PCLK。
S3C2440 有两个 PLL(锁相环),一个用于 FCLK、HCLK、PCLK;另一个用于 USB 模块(48MHZ)。时钟控制逻辑能够由软件控制不将 PLL 连接到各接口模块以降低处理器时钟频率,从而降低功耗。
S3C2440 有各种针对不同任务提供的最佳功率管理策略,功率管理模块能够使系统工作在如下四种模式:正常模式、低速模式、空闲模式 和 掉电模式。
(1)正常模式:功率管理模块向 CPU 和 所有外部设备提供时钟。这种模式下,当所有外设都开启时,系统功率将达到 最大。用户可以通过 软件 控制各种外设的开关。
(2)低速模;式没有 PLL 的模式。与正常模式不同,低速模式 直接使用外部时钟(XTIpll 或者 EXTCLK)作为 FCLK,这种模式下,功率仅由外部时钟决定。
(3)空闲模式: 功率管理模块 仅关掉 FCLK,而继续提供时钟给其他外设。空闲模式可以 减少由于 CPU 核心产生的功耗。任何中断请求都可以将 CPU 从中断模式唤醒。
(4)掉电模式:功率管理模块断开内部电源,因此 CPU 和 除唤醒逻辑单元以外的外设 都不会产生功耗。要执行掉电模式需要有两个独立的电源,其中一个给唤醒逻辑单元供电,另一个给包括 CPU 在内的其他模块供电。在掉电模式下,第二个电源将被关掉。掉电模式可以由外设中断 EINT[15:0]或 RTC 唤醒。
5.5 DMA
S3C2440 拥有 4 个通道 的 DMA 控制器,相连于 系统总线 和 外围总线。DMA 控制器 的每一个通道可以在:系统总线上的存储器与外围总线之间、系统总线上的设备之间,以及外围总线设备之间操作数据传输而不被限制。
S3C2440 的 DMA 在以下 四种情况 可运行:
(1)源设备和目标都在系统总线 AHB 上;
(2)源设备和目标都在外围总线 APB 上;
(3)源设备在系统总线,而目标设备位于外围总线;
(4)源设备在外围总线,而目标设备位于系统总线。
DMA 的主要优点是:可以不通过 CPU 的中断来实现数据的传输,DMA 的运行可以通过软件或者通过外围设备的中断和请求来初始化。
传送完规定的数据后,DMA 撤销 HOLD 信号,CPU 也撤销 HLDA 信号,并且恢复对三条总线的控制。
S3C2440 的 DMA 工作过程可以分为以下 三个状态:
① 状态 1——等待状态
DMA 等待一个 DMA 请求。如果有请求到来,将转移到 状态 2。在这个状态下,DMA ACK 和 INT REQ 为 0。
② 状态 2——准备状态
DMA ACK 变为 1,计数器(CURR_TC)从 DCON[19:0] 寄存器装载计数值。注意:DMA ACK 保持为 1 直到它被清除。
③ 状态 3——传输状态
DMA 控制器从 源地址 读入数据并将它写到 目的地址,每传输 一次,CURR_TC 计数器减 1,并且可能做以下操作:
A.重复传输:在全服务模式下,将重复传输,直到计数器 CURR_TC 变为 0;在单服务模式下,仅传输一次;
B.设置中断请求信号:当 CURR_TC 变为 0 时,而且 DCON[29] 即中断使能设定位被设为 1 ,则 DMAC(DMA 控制器) 发出 INT REQ 信号;
C.清除 DMA ACK 信号:全服务模式 CURR_TC 变为 0。对单服务模式,执行完该次传输操作。
注意:在单服务模式下,DMAC 的三个状态(等待、准备和传输)被执行一遍,然后停止,等待下一个 DMA REQ 的到来。如果 DMA REQ 到来,则这些状态被重复操作,直到 CURR_TC 减为 0。 不管服务模式如何,一旦计数器(CURR_TC)变成 0,中断请求信号 INT REQ 发出。
外部 DMA 请求/响应协议
DMA 有 三种类型 的 外部 DMA 请求/响应 规则:
①single service demand,单服务请求(对应于需求模式);
②single service handshake,单服务握手(握手模式);
③whole service handshake,全服务握手(全服务模式)。
请求/握手(demand 与 handshake)模式的比较如下:
在一次传输结束时,DMA 检查 xnxDREQ(DMA 请求)信号的状态。
在需求模式下:如果 DMA 请求(xnxDREQ)信号仍然有效,则传输马上再次开始,否则等待;
在握手模式下:如果 DMA 请求信号无效,DMA 在 2 个时钟周期后将 DMA 响应(xnxDACK)信号变得无效,否则 DMA 等待直到 DMA 请求信号变得无效,每请求一次传输一次。
5.6 中断控制器
S3C2440X 中断控制器有 56 个 中断源,对外提供 24 个 外中断输入引脚,内部所有设备都有中断请求信号,例如:DMA 控制器、UART、IIC 等。 S3C2440X 的 ARM920T 内核有两个中断:IRQ 中断 和 快速中断 FIQ。 中断仲裁:当中断控制器接收到 多个中断请求时,其内的优先级仲裁器裁决后向 CPU 发出优先级最高的中断请求信号或快速中断请求信号。
中断控制器操作
(1)当前程序状态寄存器(CPSR)的 F 位 和 I 位
CPSR 指 ARM920T 处理器的程序状态寄存器。如果 CPSR 的 F 位 被设置为 1 ,处理器将不接受来自中断控制器的 FIQ(快速中断请求);如果 PSR 的 I 位 被设置为 1 ,处理器将不接受来自中断控制器的 IRQ(中断请求)。因此,为了使能 FIQ 和 IRQ ,PSR 的 F 位 或 I 位 必须被 清零,同时中断屏蔽寄存器 INTMASK 的相应位也必须被 清 0 。
(2)中断模式
ARM920T 有两种类型的中断模式(INTMOD),即 FIQ(快速中断请求)和 IRQ(普通中断模式)。所有的中断源在中断请求时都要确定使用哪一种中断模式。
(3)中断挂起寄存器
S3C2440 有两个中断挂起寄存器:源挂起寄存器(SRCPND) 和 中断挂起寄存器(INTPND)。这些挂起寄存器指示了一个中断请求是否被挂起。
当中断源请求中断服务时,SRCPND 相应位被置 1 。
并且同时在仲裁后 INTPND 寄存器 仅有 1 位被置 1。
如果中断被屏蔽,那么 SRCPND 相应位被 置 1,但并不能引起 INTPND 改变。
当 INTPND 的挂起位被设置时,只要相应的 标志位 I 或 标志位 F 被清 0,相应的中断服务程序都被执行。SRCPND 和 INTPND 可以被读写。
(4)中断屏蔽寄存器(INTMSK)
如果该寄存器的某一个位被 置 1 ,则该位对应的中断响应被 禁止 了;
如果某个中断在 INTMSK 寄存器的对应位 为 0 ,则这个中断发生时将会正常被响应。
如果某个中断在 INTMSK 的寄存器中的对应位 为 1,但是这个中断发生了,它的源挂起寄存器(SRCPND)对应位还是会 置 1。而对应中断挂起寄存器(INTPND)标志位,不会被置 1 。
中断优先级
(1)中断优先级仲裁器及工作原理
中断系统有 6 个 分仲裁器 和 1 个 总仲裁器,每一个仲裁器可以处理 6 路 中断。
S3C2440 将中断源分为两级: 中断源和子中断源(次级中断源):32 个中断源中包含单一中断源和复合中断源。 复合中断源是子中断源(次级中断源)的复合信号。 (2)中断优先级
每一个仲裁器可以控制 6 个 中断请求,其基于由仲裁模式控制的 1 位(ARB_MODE) 和 选择控制信号的 2 位(ARB_SEL)。① 如果 ARB_SEL 位为:00b,优先级次序为 REQ0、REQ1、REQ2、REQ3、REQ4 和 REQ5;② 如果 ARB_SEL 位为:01b,优先级次序为 REQ0、REQ2、REQ3、REQ4、REQ1 和 REQ5;③ 如果 ARB_SEL 位为:10b,优先级次序为 REQ0、REQ3、REQ4、REQ1、REQ2 和 REQ5;④ 如果 ARB_SEL 位为:11b,优先级次序为 REQ0、REQ4、REQ1、REQ2、REQ3 和 REQ5。注意:仲裁器的 REQ0 为最高优先级,REQ5 为最低优先级;通过改变 ARB_SEL 位的值,可以设定 REQ1~REQ4 优先级。
这里,如果 ARB_MODE 位 设置为 0 , ARB_SEL 位不会自动改变,仲裁器会在固定的优先级模式中操作(即使在这个模式中,也可以通过手动改变 ARB_SEL 位配置优先级)。
另一方面,如果 ARB_MODE 位设置为 1,ARB_SEL 位轮流改变。例如,如果 REQ1 被执行,为了把 REQ1 放在最低优先级,ARB_SEL 位会被自动改为 01b。 ARB_SEL 变化的详细规则如下:
① 如果 REQ0 或者 REQ5 被执行,ARB_SEL 不再改变; ② 如果 REQ1 被执行,ARB_SEL 位改变为 01b;也就是,REQ1 的优先级,被调换 到 倒数 第 2 位,只比 固定 最低 优先级 的 REQ5 高。 ③ 如果 REQ2 被执行,ARB_SEL 位改变为 10b;也就是,REQ2 的优先级,被调换 到 倒数 第 2 位。 ④ 如果 REQ3 被执行,ARB_SEL 位改变为 11b;也就是,REQ3 的优先级,被调换 到 倒数 第 2 位。 ⑤ 如果 REQ4 被执行,ARB_SEL 位改变为 00b。也就是,REQ4 的优先级,被调换 到 倒数 第 2 位。 优先级 以 轮流 的方式 在变化,对于 REQ1-4 的这 4 个 中断源 的优先级 在 被执行后,就会被调换到 倒数 第 2 位
特殊中断控制器
中断控制器 中 包括 5 个 控制寄存器:源挂起寄存器、中断模式寄存器、屏蔽寄存器、优先级寄存器、中断挂起寄存器。 来自中断 的 中断 请求 首先 寄存在 源挂起寄存器,也就是,只要 有 中断请求,该中断源 的 对应位 都会 被置 1。它们 基于 中断模式 寄存器 分为 两组:FIQ 中断请求 和 IRQ 中断请求。对 多重 IRQ 请求 的 仲裁 过程 使用 优先级寄存器,就是 利用 优先级寄存器 设置 的优先级 进行优先级 仲裁。
(1)源挂起寄存器
源挂起寄存器由 32 位 组成,每一个比特位均与一个中断源相连。当中断源产生中断请求并且等待中断服务程序的执行时,其相应的比特位设置为 1 。还有,源挂起寄存器指示此时哪一个中断源正在等待执行中断请求。注意: SRCPND 寄存器的各比特位均为 中断源自动设置,与屏蔽寄存器的相应位设置无关。
另外,SRCPND 寄存器 不受 中断控制 寄存器的 优先级 逻辑的 影响。因为,该寄存器,仅表示 有哪些 中断源 提出了 中断 请求。 当 中断服务 被 执行时,SRCPND 寄存器 的 相应位 应该 及时 清 0,也就是 你在 中断 服务程序 中,应该 主动 把 对应 位 清 0,以便 正确地 接收 相应 中断源的 中断 请求。如果 没有 清除 源挂起 位,当 中断服务 返回 时,中断 控制 寄存器 会 将之 作为 来自 相同 中断源 的 中断请求 的 第二次 执行。也就是说,如果 SRCPND 寄存器 的 某位为 1,系统 一般 会 当作 一个 有效的 等待 执行 的 中断请求。
清除 相应位 的 时间 依赖于 用户的 需求。如果 想要 接收 来自 相同源 的 另一个 有效 中断请求,那么 应该 清除 相应 挂起位 并且 使能 中断。可以 通过 写入 一个 数据 到 此 寄存器 来 清除 SRCPND 寄存器 的 指定位, 这时 只 清除 那些 数据中 被 设置为 1 的 相应位置 的 SRCPND 位。那些 数据中 被 设置为 0 的 相应 位置 的 位 保持 不变。注意 这 句话:写入 数据中 被 设置为 1 的 相应 位置 才 被 清 0 ,其余 为 0 的位置 的数据 保持 不变。这 不是 单纯的 写 寄存器 操作,不要 理解 错误。这个 操作 类似 执行 了 把 写入 数据 先 取反 再 与 寄存器 中 原数据 相与 的 操作。 (2)中断模式寄存器
中断模式寄存器 INTMOD 的 32 个 比特位分别与一个中断源相对应。如果某位被设置为 1 ,则相应的中断会以 FIQ 的模式来处理。相反,以 IRQ 的模式来处理。 注意:中断控制器中 仅有一个中断源 可以由 FIQ 模式来处理(只紧急中断使用 FIQ 中断),所以 INTMOD 中只有一个比特位可以被设置为 1 。
(3)中断屏蔽寄存器
中断屏蔽寄存器 INTMSK 也包括了 32 位,每一个比特位均与相应的一个中断源相对应。如果某位被设置为 1,那么 CPU 不会执行相应中断源提出的中断请求(即使源挂起寄存器的相应位被设置为 1)。如果屏蔽位为 0,那么中断请求会被正常执行。
(4)优先级控制寄存器
(5)中断挂起寄存器
中断挂起寄存器 INTPND 的 32 位,显示具有最高优先级,且未被屏蔽的中断请求,在等待中断服务。因为 INTPND 寄存器位于优先级逻辑之后,仅 1 位可以被置 1。该中断请求将生成对 CPU 的 IRQ。在对于 IRQ 的中断服务程序中,我们可以读取该寄存器,来查看哪个中断源被服务。同 SRCPND 一样,INTPND 也需要在中断服务程序中加入 清 0 操作,位于 SRCPND 寄存器 清 0 操作之后。 可以通过向 INTPND 寄存器写入一个数据对相应位 清 0 。仅将 1 对应位清除,其余保持原值不变。
(6)INTOFFSET 寄存器
INTOFFSET 寄存器的值说明了 INTPND 寄存器中哪一个 IRQ 模式的中断请求有效。这个比特位可以通过清除 SRCPND 和 INTPND 寄存器来自动清除。
(7)次级源挂起寄存器
可以通过向 SUBSRCPND 寄存器某一位写入 1 来清除该位。此数据仅清除数据对应的比特位,其它的比特位不变。
(8)中断次级屏蔽寄存器
中断次级屏蔽寄存器 INTSUBMSK 中的 11 位 和响应的中断源有联系,如果某一比特位设置为 1 ,那么来自相应中断源的中断请求便不会被 CPU 执行(注意此种情况下,SUBSRCPND 寄存器相应位会被设置为 1)。如果屏蔽位为 0 ,那么中断请求将会被执行。
5.7 I/O 端口
共有 130 个通用可编程多功能输入 / 输出引脚,分为多个端口组,I/O 端口 的各种功能主要通过对端口各个寄存器 进行设置而实现的
(1)端口配置寄存器(GPACON~GPJCON)
在 S3C2440 中,大多数的引脚 都是 多功能引脚,所以应该为 每一个引脚 选择功能。端口控制字寄存器(GPnCON)决定了 每一个引脚的功能。 如果 GPF0GPF7 和 GPG0GPG7 在 掉电的模式下 被用作唤醒信号,则这些端口必须被配置,必须被配置为外中断功能输入口。
(2)端口数据寄存器(GPADAT~GPJDAT)
如果这些端口被配置为 输出端口,则输出数据可以被写入 GPnDAT 的相应位 。如果被设定为 输入端口,则输入数据可以从 GPnDAT 的相应位读取。
(3)端口上拉寄存器(GPBUP~GPJUP)
端口上拉寄存器控制 每一个端口组的上拉电阻的使能端。当相应的位被设为 0 时,引脚接上拉电阻;当相应的位被设置为 1 时,引脚不接上拉电阻。如果引脚设置接上拉电阻,那么上拉电阻与引脚的功能设置无关(例如 input、output、DATAn、EINTn 等)。
(4)杂项控制寄存器 MISCCR
这个寄存器控制 DATA 端口 的 上拉电阻、hi-z(高阻)状态、USB 和 CLKOUT 选择。
(5)外部中断控制寄存器(EXTINTN)
24 个 外部中断源 可用各种信号来请求。外部中断寄存器为外部中断请求设置了信号 触发方法 ,包括:低电平触发、高电平触发、上升沿触发、下降沿触发和双边沿触发。8 个外部中断引脚 有一个 数字滤波器(见 EINTFLTn),16 个引脚 EINT[15:0]用作唤醒源。
(6)掉电模式 和 I/O 口
所有的 GPIO 寄存器 的值在掉电模式下 被保存。这在时钟功率管理模块中的掉电模式下提到。 EINTMSK 不能禁止从掉电模式唤醒,但是如果 EINTMSK 屏蔽了 EINT[15:4] 中的对应位,系统可以被唤醒,但是 SRCPND 中的 EINT4_7 位 和 EINT8_23 位 不会 在唤醒后被 置 1。
端口 A-H 寄存器
(12)外部中断控制寄存器(EXTINTn)
24 个外部中断 可以有不同的信号方式请求。EXTINTn 为外部中断请求,配置信号的方式为:电平触发 或者 边沿触发,也可以配置信号极性。
(13)外部中断过滤寄存器(EINTFLTn)(了解)
(14)外部中断屏蔽寄存器(EINTMASK)
针对 20 个 外部中断(EINT[23:4])的中断屏蔽寄存器(即 EINTMASK),
(15)外部中断挂起寄存器(EINTPENDn)
外部中断挂起寄存器 EINTPENDn 是针对 20 个 外部中断(EINT[23:4])的,可以通过向此 EINTPEND 寄存器相应位 写 1 来清除比特位。
5.8 PWM 定时器
有 5 个 16 位定时器,部分具有 PWM 功能,可实现脉宽调制、自动加载等操作,用于产生特定波形。
(1)5 个 16 位定时器;
(2)2 个 8 位预分频器 和 2 个 4 位分频器(时钟除法器);
(3)输出波形的占空比可编程控制(PWM);
(4)自动加载模式 或 单触发脉冲模式;
(5)死区产生器。
S3C2440 具有 5 个 16 位定时器,定时器 0、1、2、和 3 具有 PWM 功能(脉宽调制),定时器 4 是一个内部定时器,不具有对外输出口线。定时器 0 具有死区发生器,通常用于大电流设备应用。 定时器 0 和 1 公用 一个 8 位预分频器,定时器 2、3 和 4 公用 另一个 8 位预分频器。每一个定时器通过除法器可以得到 5 种不同的信号(1/2、1/4、1/8、1/16 和 TCLK ) 。 每一个时钟模块 从其时钟除法器中 接收时钟信号,时钟除法器 从其相应的 8 位预分频器 中接收时钟信号。8 位预分频器 是可编程的,并根据存储在 TCFG0 和 TCFG1 的值来对 PCLK 信号 进行分频。
PWM 概念(脉宽调制)就是只对 一方波序列信号的占空比 按要求进行调制,而不是 改变方波信号的其它参数,即不改变 幅度和周期,因此脉宽调制信号的产生和传输,都是数字式的。
定时器计数缓冲寄存器(TCNTBn)的值 是当定时器使能时装载到减法计数器的 初值;(周期) 定时器比较缓冲器(TCMPBn)的值 将被装载到比较寄存器并与减法计数器的值进行比较;(占空比) TCNTBn 和 TCMPBn 双重缓冲器的特性使 定时器频率 和 占空比改变时,确保产生稳定的输出。
每个计数器都有自己的 16 位减法器,由定时器时钟驱动。当定时器计数器值 达到 0 时,定时器发出中断请求,通知 CPU 定时工作已经完成,相应的 TCNTBn 将自动装入计数器,以继续下一个操作。但是,如果,定时器控制寄存器 TCONn 中的自动重装载开/关被清除, 则 TCNTBn 中的值将不会被装载到计数器。 TCMPBn 的值用于脉宽调节,当该计数器值与定时器控制逻辑中的比较寄存器值相等时,定时控制逻辑改变输出电平。因此,比较寄存器决定 PWM 输出的高电平时间(或低电平时间)。
定时器基本操作:一个定时器(定时器 4 除外)包含:TCNTBn、TCNTn、TCMPBn 和 TCMPn 几个寄存器(TCNTn 和 TCMPn 是减法计数器内部寄存器的名称,TCNTn 的值可以通过读 TCNTOn 得到)。当定时器达到 0 时 ,TCNTBn 和 TCMPBn 的值将 自动加载 到 TCNTn 和 TCMPn 中。当 TCNTn 到 0 且中断使能时,定时器将 产生一个中断请求。
双缓冲模式
脉宽调制定时器 有一个 双缓冲功能,在这种情况下,改变下次加载值的同时 不影响 当前定时周期。因此,尽管设置一个 新的定时器值,当前定时器的操作将会继续完成而不受影响。双缓冲功能时序图如下所示:
在原周期时修改 TCNTBn 的值不会影响当前的计数周期,在计数满一个周期时系统产出中断并重新从定时器计数缓冲寄存器加载初值到减法计数器。
自动 加载模式
定时器的值可以写入定时器计数值缓冲寄存器(TCNTBn)中,而当前计数器的值可以通过读定时器计数值观测寄存器(TCNTOn)得到。 当 TCNTn 的值到 0 时,自动加载操作复制 TCNTBn 的值到 TCNTn 中。但是如果 自动加载模式 没有使能, TCNTn 将不进行任何操作。