Cortex-M4内核参考手册笔记-Cortex-M4处理器
2.1 编程模型
2.1.1 处理器模式和软件执行特权级
处理器模式包括:
-
线程模式(Thread mode):用于执行应用软件。
-
处理器复位后自动进入线程模式。
-
通过CONTROL寄存器控制软件执行权限为特权或非特权(详见第25页CONTROL寄存器)。
-
-
处理模式(Handler mode):用于处理异常。
-
异常处理完成后,处理器返回线程模式。
-
在此模式下,软件始终以特权级别执行。
-
软件执行的特权级别分为:
-
非特权级(Unprivileged):
-
对MSR和MRS指令的访问受限,且无法使用CPS指令。
-
无法访问系统定时器、HVIC或系统控制块。
-
可能对内存或外设的访问受限。
-
需通过SVG指令发起超级用户调用(supervisor call),将控制权转移至特权级软件。
-
-
特权级(Privileged):
-
可执行所有指令并访问全部资源。
-
可通过写CONTROL寄存器切换软件执行的特权级别。
-
2.1.2 栈
处理器采用满递减堆栈(full descending stack)。处理器实现两种堆栈——主堆栈(main stack)和进程堆栈(process stack),二者拥有独立的栈指针副本。
在线程模式下,CONTROL寄存器决定使用主堆栈还是进程堆栈;在处理模式下,处理器始终使用主堆栈。处理器操作的选项包括:

2.1.3 核心寄存器


通用寄存器
R0-R13是用于数据操作的32位通用寄存器
栈指针
栈指针(Stack Pointer, SP)为寄存器R13。在线程模式下,CONTROL寄存器的bit[1]决定当前使用的栈指针:
-
0:主栈指针(Main Stack Pointer, MSP),此为复位后的默认值。
-
1:进程栈指针(Process Stack Pointer, PSP)。
复位时,处理器会从地址0x00000000加载MSP的初始值。
链接寄存器
链接寄存器(Link Register, LR)为寄存器R14,用于存储子程序、函数调用及异常的返回地址。复位时,处理器将LR初始化为0xFFFFFFFF。
程序计数器
程序计数器(Program Counter, PC)为寄存器R15,保存当前程序地址。复位时,处理器会从复位向量地址0x00000004加载PC值,并将该值的bit[0]载入EPSR的T-bit(复位时此位必须为1)。
程序状态寄存器
程序状态寄存器(Program Status Register, PSR)由以下三部分组成:
-
应用状态寄存器(Application PSR, APSR)
-
中断状态寄存器(Interrupt PSR, IPSR)
-
执行状态寄存器(Execution PSR, EPSR)

可通过MSR或MRS指令,以寄存器名称为参数单独或组合访问这些寄存器。例如:
-
使用MRS指令读取PSR,可同时访问APSR、EPSR和IPSR。
-
使用MSR指令写入APSR_nzcvq,可更新APSR的N、Z、C、V和Q标志位。
PSR的组合方式及属性如下:

-
处理器会忽略对IPSR位的写入操作。
-
读取EPSR位将返回零,且处理器会忽略对这些位的写入。
应用状态寄存器(APSR)
APSR存储了先前指令执行后的条件标志状态,

中断程序状态寄存器(IPSR)
IPSR包含当前中断服务程序(ISR)的异常类型编号

执行程序状态寄存器(EPSR)
EPSR包含Thumb状态位和执行状态位,用于以下两种情况:
1. If-Then(IT)条件执行指令
2. 被中断的多重加载(LDM)/存储(STM)指令的可中断-可继续指令(ICI)字段

应用程序通过MSR指令直接读取EPSR将始终返回零值,写入操作将被忽略。故障处理程序可通过检查堆栈中的PSR值来获取引发故障的操作状态
可中断-可继续指令(ICI)
当LDM、STM、PUSH、POP、VLDM、VSTM、VPUSH或VPOP指令执行期间发生中断时,处理器将:
-
暂停当前多重加载/存储指令的执行
-
将待操作的下一个寄存器编号存入EPSR的blist[15:12]位域
中断服务完成后,处理器会:
-
根据blist[15:12]定位寄存器
-
恢复多重加载/存储指令的执行
当EPSR保存ICI执行状态时,blist[26:25,11:10]位域为零。
IT条件执行块(IT)
IT指令构成的条件执行块最多包含4条后续指令,每条指令均可设置条件:
-
所有指令条件相同,或部分条件互为反相
-
详见第145页IT指令说明
Thumb执行状态
Cortex-M4处理器仅支持Thumb状态指令执行。以下情况会将T位清零:
-
执行BLX、BX及POP{PC}指令
-
异常返回时从堆栈恢复xPSR值
-
异常进入或复位时载入向量的bit[0]
若T位为0时执行指令,将触发故障或锁死。
异常屏蔽寄存器
异常屏蔽寄存器用于禁止处理器处理异常,可在时序关键任务中禁用异常响应。
要访问异常掩码寄存器,可使用MSR和MRS指令,或使用CPS指令修改PRIMASK或FAULTMASK的值。
优先级掩码寄存器(PRIMASK)
PRIMASK寄存器用于阻止所有具有可配置优先级的异常激活。

故障掩码寄存器(FAULTMASK)
FAULTMASK寄存器用于阻止除_不可屏蔽中断_(NMI)外的所有异常激活。

处理器在退出任何异常处理程序(NMI处理程序除外)时,会将FAULTMASK位清零。
基础优先级掩码寄存器(BASEPRI)
BASEPRI寄存器定义了异常处理的最低优先级。当BASEPRI设置为非零值时,它会阻止所有优先级等于或低于BASEPRI值的异常激活。

CONTROL寄存器
CONTROL寄存器用于控制处理器处于线程模式时使用的堆栈和软件执行的权限级别,并指示浮点单元(FPU)状态是否激活。其属性参见第18页的表3寄存器摘要。

处理模式(Handler mode)始终使用主堆栈指针(MSP)。因此,当处理器处于处理模式时,对CONTROL寄存器中当前堆栈指针位的显式写入将被忽略。异常进入和返回机制会自动更新CONTROL寄存器。
在操作系统环境中,建议:
-
线程模式(Thread mode)下运行的线程使用进程堆栈(PSP)
-
内核和异常处理程序使用主堆栈(MSP)
默认情况下,线程模式使用MSP。若需将线程模式的堆栈指针切换为PSP,可通过以下方式实现:
-
使用MSR指令将当前堆栈指针位置1;
-
通过异常返回机制,在返回线程模式时使用特定的EXC_RETURN值。
重要提示:
-
修改堆栈指针后,必须立即执行ISB指令,以确保后续指令使用新的堆栈指针。
2.1.4 异常和中断
Cortex-M4处理器支持中断和系统异常。处理器与嵌套向量中断控制器(NVIC)共同完成异常的优先级排序和处理。异常会改变软件控制流,处理器通过处理模式处理所有异常(复位除外)。
2.1.5 数据类型
处理器支持以下数据类型:
-
32位字(Word)
-
16位半字(Halfword)
-
8位字节(Byte)
所有内存访问均采用小端模式(Little-endian)
2.1.6 Cortex微控制器软件接口标准(CMSIS)
CMSIS为Cortex-M4微控制器系统定义了以下规范:
-
统一的外设访问方式:
-
外设寄存器访问
-
异常向量定义
-
-
核心外设寄存器与异常向量的命名规则
-
独立于设备的RTOS内核接口(含调试通道)
CMSIS(Cortex微控制器软件接口标准)为Cortex-M4处理器的核心外设提供了地址定义与数据结构支持。
2.2 存储器模型
本节描述处理器的内存映射、内存访问行为以及位带特性。该处理器采用固定内存映射,最多可寻址4GB内存空间。

-
位带操作:
-
SRAM和外设区域包含位带区,支持对位数据的原子操作。
-
-
保留区域:
-
私有外设总线(PPB)地址范围中部分区域预留给核心外设寄存器
-
2.2.1 存储器区域、类型和属性
存储器映射和MPU(内存保护单元)的编程将存储器空间划分为多个区域。每个区域都有定义的存储器类型,部分区域还具有额外的存储器属性。存储器类型和属性决定了访问该区域时的行为。
存储器类型:
-
普通存储器(Normal)
处理器可以为了效率重新排序事务,或执行预读操作。 -
设备存储器(Device)
处理器会保持相对于其他设备存储器或强序存储器事务的顺序。 -
强序存储器(Strongly-ordered)
处理器会保持相对于所有其他事务的顺序。
设备存储器和强序存储器的不同排序要求意味着:
-
存储器系统可以缓冲对设备存储器的写入
-
但绝不能缓冲对强序存储器的写入
附加存储器属性:
-
永不执行(XN)
表示处理器会阻止指令获取。任何尝试从XN区域获取指令的操作都会引发内存管理错误异常。
2.2.2 存储器的访问顺序
对于大多数由显式存储器访问指令引发的访问,存储器系统不保证访问完成的顺序与指令的程序顺序一致,只要这不影响指令序列的行为即可。通常,如果程序正确执行依赖于两次存储器访问按程序顺序完成,软件必须在存储器访问指令之间插入内存屏障指令。
然而,存储器系统确实保证对设备存储器和强序存储器的某些访问顺序。对于两条存储器访问指令A1和A2,如果A1在程序顺序上先于A2,则由这两条指令引发的存储器访问顺序如下

2.2.3 存储器访问行为
各存储器区域的访问行为如下:

-
代码区、SRAM区和外部RAM区均可存储程序,但建议程序始终存放在代码区。原因是处理器具有独立总线,可实现指令获取和数据访问的并行操作。
-
MPU(内存保护单元)可覆盖本节描述的默认访问行为。
指令预取与分支预测
Cortex-M4处理器具有以下特性:
-
执行前进行指令预取
-
对分支目标地址进行推测性预取
2.2.4 内存访问的软件排序
程序流中的指令顺序并不总能保证对应存储器事务的执行顺序,原因包括:
-
为提升效率可能重排部分存储器访问(不影响指令序列行为时)
-
处理器具有多总线接口
- 存储器映射中不同设备/存储器的等待状态不同
- 部分访问存在缓冲或预取行为
存储器系统保证特定情况下的访问顺序
关键顺序场景必须使用内存屏障指令,处理器提供三类屏障:
| 指令 | 全称 | 功能 | 参考章节 |
|---|---|---|---|
| DMB | 数据内存屏障 | 确保后续存储事务前完成当前未完成事务 | 第163页 |
| DSB | 数据同步屏障 | 确保后续指令执行前完成当前存储事务 | 第184页 |
| ISB | 指令同步屏障 | 确保后续指令能识别已完成存储事务的效果 | 第185页 |
典型应用场景
-
向量表更新
-
在更新向量表内容与启用异常间插入DMB
-
保证异常立即触发时使用新向量
-
-
自修改代码
-
代码修改后立即执行ISB
-
确保后续执行使用更新后的代码
-
-
存储器映射切换
-
切换映射后执行DSB
-
保证后续指令使用新映射(注:原文"USB"应为"DSB"笔误)
-
-
动态异常优先级调整
-
待处理/活跃异常的优先级修改后执行DSB
-
确保修改在DSB完成后生效
-
-
多主系统信号量
-
每个处理器在信号量操作后执行DMB
-
确保各主设备按执行顺序观测存储事务
-
特殊说明
-
强序存储器(如系统控制块)访问无需DMB
-
MPU编程需组合使用DSB+ISB(或异常返回)以确保新配置生效
2.2.5 位带
位带区域将位带别名区中的每个字映射到位带区中的单个位。位带区占据SRAM和外设内存区域最低的1MB空间。
内存映射包含两个32MB的别名区域,分别映射到两个1MB的位带区:
-
访问32MB SRAM别名区域将映射到1MB SRAM位带区,如表15所示。
-
访问32MB外设别名区域将映射到1MB外设位带区,如表16所示。

对SRAM或外设位带别名区的字访问将映射到SRAM或外设位带区中的单个位。
位带操作可使用字节、半字或字传输。位带传输大小与执行位带访问的指令传输大小相匹配。
以下公式展示了别名区如何映射到位带区:

其中:
-
bit_word_offset 表示目标位在位带内存区域中的位置
-
bit_word_addr 表示别名内存区域中映射到目标位的字地址
-
bit_band_base 是别名区域的起始地址
-
byte_offset 是位带区域中包含目标位的字节编号
-
bit_number 是目标位的位位置(0-7)
别名区访问特性
直接访问别名区域时:
-
向别名区的某个字写入数据会更新位带区中的单个位
-
写入别名区字数据的bit[0]决定位带区目标位的值:
-
当bit[0]=1时,位带区对应位被置1
-
当bit[0]=0时,位带区对应位被置0
-
-
别名区字数据的bit[31:1]对位带位没有影响
-
写入0x00000001与写入0xFF效果相同(均置1)
-
写入0x00000000与写入0x0E效果相同(均置0)
别名区读取操作
读取别名区字数据时:
-
返回0x00000000表示位带区目标位为0
-
返回0x00000001表示位带区目标位为1
2.2.6 存储器端模式
处理器将内存视为从零开始升序排列的线性字节集合。例如:
-
字节0-3存储第一个字
-
字节4-7存储第二个字
小端格式
在小端格式中:
-
字的最低有效字节存储在最低编号字节(小地址端)
-
字的最高有效字节存储在最高编号字节(大地址端)

2.2.7 同步原语
Cortex-M4指令集包含同步原语对,为线程/进程提供独占访问内存位置的机制,可用于:
-
确保原子性的"读-修改-写"操作序列
-
信号量实现
同步原语对组成
-
加载独占指令(LDREX)
-
读取内存位置值
-
标记对该地址请求独占访问
-
-
存储独占指令(STREX)
-
尝试向相同内存位置写入
-
向寄存器返回状态位:
-
0:成功获得独占访问,写入完成
-
1:未获得独占访问,不执行写入
-
独占加载与存储指令组成
包含三类指令对:
-
字操作指令:LDREX与STREX
-
半字操作指令:LDREXH与STREXH
-
字节操作指令:LDREXB与STREXB
原子操作实现流程
要确保内存位置的原子性"读-修改-写"操作,软件需执行以下步骤:
-
使用加载独占指令(LDREX/LDREXH/LDREXB)读取目标地址值
-
按需修改该值
-
使用存储独占指令(STREX/STREXH/STREXB)尝试将新值写回内存
-
检测返回状态位:
-
0:操作成功完成
-
1:写入未执行(表明步骤1读取的值可能已过期),需重试整个序列
-
信号量实现方案
通过同步原语实现信号量的流程:
-
用加载独占指令读取信号量地址,检查是否空闲
-
若空闲,用存储独占指令写入占用值
-
若存储独占返回状态位为0,则成功获取信号量;若为1,表明其他进程可能在步骤1后已抢先占用
独占访问监视机制
Cortex-M4内置独占访问监视器,会标记处理器执行过的加载独占指令。在多处理器系统中,系统还会全局标记各处理器独占访问的内存地址。
当出现以下情况时,处理器将移除其独占访问标记:
-
执行CLREX指令:强制清除独占状态
-
执行存储独占指令(无论写入操作是否成功)
-
发生异常:该机制使处理器能够解决不同线程间的信号量冲突
在多处理器架构中:
-
CLREX指令:仅清除当前处理器的本地独占访问标记
-
存储独占指令或异常:同时清除当前处理器的本地标记和全局独占访问标记
2.2.8 同步原语的编程指南
ISO/IEC C标准无法直接生成独占访问指令。CMSIS(Cortex微控制器软件接口标准)提供了以下内联函数来生成这些指令:

2.3 异常模型
2.3.1 异常状态
每个异常处于以下状态之一:
非活跃状态(Inactive)
异常未被激活且无挂起请求。
挂起状态(Pending)
异常等待被处理器响应。来自外设或软件的请求可使中断进入该状态。
活跃状态(Active)
异常正在被处理器处理但未完成。
注:一个异常可以抢占另一个异常的执行,此时两个异常均处于活跃状态。
活跃且挂起状态(Active and pending)
异常正在处理过程中,同时收到来自同一异常源的新的挂起请求。
2.3.2 异常类型
处理器支持的异常类型包括:
复位(Reset)
在上电或热复位时触发,被异常模型视为特殊形式的异常。复位信号有效时,处理器会立即停止当前指令执行;复位释放后,将从向量表复位入口地址以特权模式(Privileged Mode)在线程状态(Thread Mode)下恢复运行
不可屏蔽中断(NMI)
可由外设或软件触发,是优先级仅次于复制的异常(固定优先级-2)。不可屏蔽中断(NMI)具有以下不可覆盖的特性:
-
全局不可屏蔽性:任何其他异常均无法屏蔽或阻止其激活
-
最高抢占优先级:除复位(Reset)外,任何异常均不能抢占其执行
硬件错误(Hard fault)
硬件错误(Hard Fault)是指由于异常处理过程中发生错误,或无法通过其他异常机制处理的异常。该异常具有固定优先级-1,其优先级高于所有可配置优先级的异常
内存管理错误(Memory management fault)
内存管理错误(Memory Management Fault)是由内存保护相关故障引发的异常,由内存保护单元(MPU)或固定内存保护规则对指令和数据内存访问进行检测时触发。该异常机制会终止对"永不执行"(XN)内存区域的指令访问。
总线错误(Bus Fault)
总线错误是由于指令或数据内存访问相关的故障引发的异常,通常由内存系统中总线检测到的错误引起。
用法错误(Usage Fault)
用法错误是指令执行故障引发的异常,包括以下情况:
-
执行未定义指令
-
非对齐访问违规
-
指令执行时处于无效状态
-
异常返回错误
当处理器配置为报告以下情况时也会触发:
-
字/半字内存访问地址未对齐
-
除零操作
超级用户调用(SVCall)
通过SVC指令触发的异常。在操作系统环境中,应用程序通过SVC指令访问内核功能和设备驱动。
可挂起服务调用(PendSV)
系统级服务的中断驱动请求。在操作系统环境中,当无其他异常活跃时用于上下文切换。
系统节拍定时器(SysTick)
系统定时器归零时产生的异常,也可由软件触发。在操作系统中通常用作系统节拍。
中断请求(IRQ)
中断请求(IRQ)是由外设触发或通过软件请求产生的异常信号。所有中断均与指令执行异步发生,在系统中外设通过中断机制与处理器进行通信。


对于复位以外的异步异常,处理器在异常触发后到进入异常处理程序前可能会继续执行其他指令。
2.3.3 异常处理
处理器通过以下方式处理异常:
-
中断服务程序(ISR)
处理IRQ0至IRQ81中断请求 -
错误处理程序(Fault Handler)
处理硬件错误、内存管理错误、用法错误和总线错误等故障异常 -
系统处理程序(System Handler)
处理NMI、PendSV、SVCall、SysTick等系统异常以及各类错误异常
2.3.4 向量表
向量表包含栈指针的初始值以及所有异常处理程序的入口地址(又称异常向量)。图11展示了向量表中异常向量的排列顺序。每个向量的最低有效位必须为1,表示异常处理程序使用Thumb指令集。

系统复位时,向量表固定位于地址0x00000000。特权级软件可通过写VTOR寄存器将向量表重定位到0x00000080至0x3FFFFF80之间的其他内存地址。
2.3.5 异常优先级
如第38页表17所示,所有异常均有关联优先级,具体规则如下:
-
优先级数值越小,优先级越高
-
除复位、硬件错误和NMI外,其他异常优先级均可配置
若未配置优先级,所有可配置优先级的异常默认值为0。优先级配置方法参见:
-
第233页《系统处理程序优先级寄存器(SHPRx)》
-
第215页《中断优先级寄存器x(NVIC_IPRx)》
可配置优先级范围为0-15。复位、硬件错误和NMI的优先级为固定负值,始终高于其他异常。
示例:
-
若IRQ[0]优先级设为3,IRQ[1]设为1,则IRQ[1]优先级更高
-
当IRQ[0]和IRQ[1]同时触发时,IRQ[1]优先处理
同级优先级仲裁规则:
-
若多个挂起异常优先级相同,异常编号较小者优先处理
-
若正在处理异常时发生更高优先级异常,当前处理程序被抢占
-
若发生同级优先级异常,处理程序不被抢占,新异常转为挂起状态
2.3.6 中断优先级组
NVIC支持优先级分组以增强中断控制,将每个中断优先级寄存器分为两部分:
-
组优先级字段(高位):决定中断抢占权
-
仅当新中断组优先级高于当前处理中断时才会抢占
-
-
子优先级字段(低位):同组内的仲裁依据
-
若多个挂起中断组优先级相同,按子优先级顺序处理
-
若组优先级和子优先级均相同,则IRQ编号较小者优先
-
2.3.7 异常入口和返回
关于异常处理的描述使用以下术语:
抢占
当处理器正在执行异常处理程序时,如果一个异常的优先级高于当前正在处理的异常的优先级,则该异常可以抢占当前的异常处理程序。。
当一个异常抢占另一个异常时,这些异常称为嵌套异常。
返回
当异常处理程序完成且满足以下条件时,会发生返回:
-
没有足够优先级的待处理异常需要服务
-
已完成的异常处理程序并未处理一个晚到异常。
处理器将弹出堆栈并将处理器状态恢复到中断发生前的状态
尾链
此机制用于加速异常服务。在异常处理程序完成时,如果存在一个满足异常进入条件的待处理异常,则跳过堆栈弹出操作,直接跳转到新的异常处理程序。
晚到
此机制用于加速抢占。如果在保存前一个异常的状态期间发生了一个更高优先级的异常,处理器会切换到处理该更高优先级的异常,并启动该异常的向量获取。状态保存不受晚到异常的影响,因为两个异常保存的状态是相同的,因此状态保存会不间断地继续。处理器可以接受晚到异常,直到原始异常处理程序的第一条指令进入处理器的执行阶段。从晚到异常的处理程序返回时,适用正常的尾链规则。
异常进入
当存在一个具有足够优先级的待处理异常且满足以下任一条件时,会发生异常进入:
-
处理器处于线程模式
-
新异常的优先级高于当前正在处理的异常的优先级,此时新异常会抢占原始异常。
当一个异常抢占另一个异常时,这些异常是嵌套的。
足够优先级意味着该异常的优先级高于由掩码寄存器设置的任何限制。优先级低于此限制的异常会处于待处理状态,但不会被处理器处理。
当处理器处理异常时,除非该异常是尾链异常或晚到异常,否则处理器会将信息压入当前堆栈。此操作称为堆栈压入,其八个数据字的结构称为堆栈帧。
当使用浮点例程时,Cortex-M4处理器会在异常进入时自动将架构浮点状态压入堆栈。第43页的图12显示了当因中断或异常而在堆栈上保存浮点状态时,Cortex-M4的堆栈帧布局。如果未为浮点状态分配堆栈空间,则堆栈帧的结构与不带FPU的Armv7-M实现相同。

堆栈压入操作完成后,堆栈指针指向堆栈帧中的最低地址。堆栈帧的对齐由配置控制寄存器(CCR)的STKALIGN位控制。
堆栈帧中包含了返回地址,即被中断程序中下一条指令的地址。在异常返回时,该值会被恢复至PC寄存器,从而使被中断的程序继续执行。
在堆栈压入操作的同时,处理器会执行向量获取操作,从向量表中读取异常处理程序的起始地址。堆栈压入完成后,处理器开始执行异常处理程序。同时,处理器会将一个EXC_RETURN值写入LR寄存器。该值指示了堆栈帧对应的堆栈指针以及异常发生前处理器的操作模式。
如果在异常进入期间没有发生更高优先级的异常,处理器将开始执行异常处理程序,并自动将相应挂起中断的状态更改为活跃状态。
如果在异常进入期间发生了另一个更高优先级的异常,处理器将开始执行该异常的异常处理程序,且不会更改之前异常的挂起状态。这种情况即晚到异常。
异常返回
当处理器处于处理程序模式(Handler Mode)并执行以下任一指令将EXC_RETURN值加载到PC时,会触发异常返回:
-
加载PC的LDM或POP指令
-
目标为PC的LDR指令
-
使用任意寄存器的BX指令
EXC_RETURN是异常进入时加载到LR寄存器的值。异常机制依赖此值检测处理器是否已完成异常处理程序。其最低5位(bits[4:0])包含返回堆栈和处理器模式的信息。表18列出了EXC_RETURN值及其对应的异常返回行为描述。
所有EXC_RETURN值的[31:5]位均置1。当该值被加载到PC时,表明异常处理已完成,处理器将启动相应的异常返回序列。

表18. 异常返回行为
| EXC_RETURN[31:0] | 描述 |
|---|---|
| 0xFFFFFFF1 | 返回到处理程序模式,异常返回使用主堆栈指针(MSP)中的非浮点状态,返回后继续使用MSP执行。 |
| 0xFFFFFFF9 | 返回到线程模式,异常返回使用MSP中的非浮点状态,返回后继续使用MSP执行。 |
| 0xFFFFFFFD | 返回到线程模式,异常返回使用进程堆栈指针(PSP)中的非浮点状态,返回后继续使用PSP执行。 |
| 0xFFFFFFE1 | 返回到处理程序模式,异常返回使用MSP中的浮点状态,返回后继续使用MSP执行。 |
| 0xFFFFFFE9 | 返回到线程模式,异常返回使用MSP中的浮点状态,返回后继续使用MSP执行。 |
| 0xFFFFFFED | 返回到线程模式,异常返回使用PSP中的浮点状态,返回后继续使用PSP执行。 |
2.4 故障处理
错误(Fault)是异常的子集。以下情况会触发错误:
-
总线错误:
-
指令预取或向量表加载时
-
数据访问时
-
-
内部检测到的错误:如未定义指令
-
尝试执行标记为不可执行(XN)的内存区域中的指令
-
权限冲突或访问未管理区域导致的MPU错误
2.4.1 故障类型
表19列出了错误类型、对应的错误处理程序、相关错误状态寄存器以及指示错误发生的寄存器位。

表19. 错误类型
| 错误类型 | 处理程序 | 标志位名称 | 错误状态寄存器 |
|---|---|---|---|
| 向量读取时的总线错误 | 硬错误(Hard Fault) | VECTTBL FORCED | 第241页的硬错误状态寄存器(UFSR) |
| 错误升级为硬错误 | - | - | - |
| MPU或默认内存映射不匹配: | - | - | - |
| – 指令访问时 | 内存管理错误(MemManage) | IACCVIOL(1) | 内存管理错误地址寄存器(MMFAR) |
| – 数据访问时 | DACCVIOL | ||
| – 异常压栈时 | MSTKERR | ||
| – 异常弹栈时 | MUNSKERR | ||
| – 延迟浮点状态保存时 | MLSPERR | ||
| 总线错误: | - | - | - |
| – 异常压栈时 | 总线错误(Bus Fault) | STKERR | 第242页的总线错误地址寄存器(BFAR) |
| – 异常弹栈时 | UNSTKERR | ||
| – 指令预取时 | IBUSERR | ||
| – 延迟浮点状态保存时 | LSPERR | ||
| 精确数据总线错误 | PRECISERR | ||
| 非精确数据总线错误 | IMPRECISERR | ||
| 尝试访问协处理器 | 用法错误(Usage Fault) | NOCP | *第237页的可配置错误状态寄存器(CFSR;UFSR+BFSR+MMFSR)* |
| 未定义指令 | UNDEFINSTR | ||
| 尝试进入无效指令集状态(2) | INVSTATE | ||
| 无效的EXC_RETURN值 | INVPC | ||
| 非对齐的非法加载或存储 | UNALIGNED | ||
| 除零错误 | DIVBYZERO |
-
即使MPU被禁用,访问XN(不可执行)区域时也会触发此错误。
-
尝试使用非Thumb指令集,或返回到不支持ICI(中断继续指令)的非LDM/STM指令。
2.4.2 故障升级与硬故障
除硬错误(Hard Fault)外,所有错误异常均可配置优先级(详见第233页的系统处理程序优先级寄存器(SHPRx))。如第235页的系统处理程序控制与状态寄存器(SHCSR)所述,软件可禁用这些错误的处理程序执行。
通常,异常优先级与异常掩码寄存器的值共同决定了处理器是否进入错误处理程序,以及一个错误处理程序能否抢占另一个错误处理程序(参见第2.2节:第37页的异常模型)。
在某些情况下,具有可配置优先级的错误会被视为硬错误,称为优先级升级,此时错误被描述为升级为硬错误。以下情况会触发升级:
-
错误处理程序引发了与其正在处理的错误同类型的错误:由于处理程序无法以相同优先级抢占自身,导致升级。
-
错误处理程序引发了优先级不高于当前处理错误的另一个错误:新错误的处理程序无法抢占当前正在执行的错误处理程序。
-
异常处理程序引发的错误优先级不高于当前正在处理的异常。
-
错误发生时,其对应的处理程序未被启用。
特殊场景:
若在进入总线错误处理程序时的堆栈压入操作中发生总线错误,该错误不会升级为硬错误。这意味着即使堆栈损坏导致错误,处理程序仍会执行(尽管压栈失败)。此时处理程序可运行,但堆栈内容已损坏。
抢占规则:
只有复位(Reset)和不可屏蔽中断(NMI)能抢占固定优先级的硬错误。硬错误可抢占除复位、NMI或其他硬错误外的任何异常。
2.4.3 故障状态寄存器和故障地址寄存器
错误状态寄存器用于指示错误原因。对于总线错误和内存管理错误,错误地址寄存器会记录引发错误的操作所访问的地址,详见表20。

2.4.4 锁定
若在执行NMI或硬错误处理程序时发生硬错误,处理器将进入死锁状态。在此状态下,处理器不会执行任何指令,直到以下任一条件满足:
-
系统复位
-
发生NMI中断
-
调试器暂停处理器
注意:若死锁状态由NMI处理程序触发,后续的NMI中断无法使处理器退出死锁状态。
2.5 功耗管理
STM32和Cortex-M4处理器通过以下睡眠模式降低功耗:
-
睡眠模式:停止处理器时钟,其他系统和外设时钟仍可运行。
-
深度睡眠模式:停止大部分STM32系统和外设时钟。在具体产品中对应停止模式(Stop)或待机模式(Standby),详见STM32参考手册的"电源模式"章节。
SCR寄存器的SLEEPDEEP位用于选择睡眠模式。关于睡眠模式行为的更多信息,请参考STM32产品参考手册。
2.5.1 进入休眠
本节介绍软件使处理器进入睡眠模式的机制。
系统可能产生伪唤醒事件(如调试操作唤醒处理器),因此软件需能在事件发生后重新使处理器进入睡眠模式。例如,程序可通过空闲循环实现这一功能。
等待中断(WFI)
执行WFI指令会立即进入睡眠模式(除非满足唤醒条件,参见第48页的从WFI或睡眠返回唤醒)。处理器执行WFI指令后将停止执行指令并进入睡眠模式。
等待事件(WFE)
WFE指令根据1位事件寄存器的值决定是否进入睡眠模式:
-
事件寄存器为0:处理器停止执行指令并进入睡眠模式。
-
事件寄存器为1:处理器将寄存器清零并继续执行指令,不进入睡眠模式。
事件寄存器为1通常表示外部事件信号已触发,或系统中某处理器执行了SEV指令。软件无法直接访问该寄存器。
退出时睡眠(Sleep-on-exit)
若设置SCR寄存器的SLEEPONEXIT位为1,处理器完成异常处理程序后会立即返回线程模式并进入睡眠模式。此机制适用于仅需在异常发生时运行处理器的应用。
2.5.2 休眠唤醒
唤醒条件取决于进入睡眠模式的机制。
从WFI或睡眠返回唤醒
通常,处理器仅在检测到足够优先级的异常时才会唤醒。
某些嵌入式系统需在唤醒后、执行中断处理程序前完成系统恢复任务。为此,可设置:
-
PRIMASK=1
-
FAULTMASK=1
若此时出现已启用且优先级高于当前异常的中断,处理器会唤醒但暂不执行中断处理程序,直到PRIMASK清零。关于PRIMASK和FAULTMASK的更多信息,参见第23页的异常掩码寄存器。
从WFE唤醒
处理器在以下情况下会被唤醒:
-
检测到具有足够优先级的异常(需满足异常进入条件)
-
检测到外部事件信号(参见第2.5.3节:外部事件输入/扩展中断和事件输入)
-
在多处理器系统中,当系统内其他处理器执行了SEV指令
特别说明:若SCR寄存器中的SEVONPEND位设置为1,则任何新出现的挂起中断都会触发事件并唤醒处理器,即使该中断被禁用或优先级不足以致无法触发异常进入。更多关于SCR寄存器的信息,请参阅第230页的"系统控制寄存器(SCR)"。
2.5.3 外部事件输入/扩展中断和事件输入
处理器提供外部事件输入信号功能。
该信号由外部/扩展中断事件控制器(EXTI)在检测到异步事件时产生(可能来自外部输入引脚或异步外设事件)。
此信号可以:
-
将处理器从WFE状态唤醒
-
将内部WFE事件寄存器置1,使后续执行WFE指令时不会进入睡眠模式(详见第48页"等待事件"部分)
更多详细信息请参考STM32参考手册的低功耗模式章节。
2.5.4 功耗管理编程指南
ISO/IEC C标准不能直接生成WFI和WFE指令。CMSIS提供了以下函数来实现这些功能:

浙公网安备 33010602011771号