RTOS系列文章(8):深入分析中断处理过程

本文详细剖析了ARM Cortex-M3/4处理器中中断处理的完整流程,重点讲解了FreeRTOS任务调度依赖的SysTick和PendSV中断,以及中断上下文切换原理。深入理解了中断处理对RTOS设计的重要性,涵盖了自动压栈、中断向量表查找、现场恢复等核心概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在上一篇文章中,我们深入分析了函数调用返回、中断调用返回使用的LR和EXC_TURN,也简单说明了函数调用流程、中断调用流程。在FreeRTOS中,任务的调度是通过SysTick + PendSV 中断来实现的,尤其在PenSV中断中进行任务上下文切换原理,是理解FreeRTOS任务调度原理的重中之重。而SysTick和PendSV都是中断,所以我们有必要深入分析一下在ARM CM3/4中中断的完整处理流程。

中断处理完整流程概述

在这里插入图片描述

整体流程如下:

  1. 主程序或应用程序正在运行过程中,中断发生。
  2. CPU自动保存现场寄存器,包括R0~R3, R12, R14(LR), 返回地址(PC), xPSR ,将这8个寄存器值存放到堆栈中,具体是任务堆栈,还是主堆栈,取决于发生中断前正在使用的是MSP还是PSP。
    (1) 假如发生中断前,正在运行OS的某个任务,即此时使用的是PSP,则将现场的这8个寄存器值使用PSP存储到线程的堆栈中。
    (2)假如发生中断前,正在使用MSP(裸机程序或中断嵌套),则将现场的8个寄存器值使用MSP存放到主堆栈中。
    注:这些工作都是CPU自动完成的,硬件实现,不需要程序员实现。这8个寄存器的值就是栈帧
  3. CPU根据发生中断前的状态,比如正在使用MSP或PSP,当前模式是线程模式或handler模式等,计算查表获取EXC_RETURN值。然后将EXC_RETURN值赋值给LR,这里注意,步骤2中保存的是LR的值,这里是将EXC_RETURN的值更新到LR寄存器,不要混淆。
    注:这些工作是CPU自动完成的,硬件实现,不需要程序员实现。步骤2和3都是进入中断前的准备工作,也就是stacking阶段。
  4. 进入中断服务程序,此时假如步骤2和3中使用的是PSP,则CPU会自动切换使用MSP,因为一旦进入中断,CPU的工作模式就变成了Handler模式,而Handler模式默认是使用MSP的。
  5. 将LR寄存器和其他高级寄存器(R4~R11根据需要选择)压栈。
    注:该步骤必须由程序员来实现,当然了,IDE或交叉编译器会帮我们实现。我们必须要将LR压栈,因为返回的时候需要LR的值EXC_RETURN.
  6. 执行中断服务程序。
  7. 中断服务程序执行完毕后,调用pop {r4, PC}, 由于步骤4中,是将r4和LR压栈,本步骤出栈,则是将LR的值(EXC_RETURN)赋值给了PC。
  8. CPU判断PC的值,发现PC的值在EXC_RETURN值范围,该范围本身在CPU的地址架构中定义就是“non-excutable”,所以CPU就知道了,原来这是中断要退出的信号,同时会更新SP,变成步骤2中使用的SP,比如由MSP切换到PSP。
  9. 执行步骤2的反操作,即将进入中断前存储的现场R0~R3, R12, R14, 返回地址(PC)、xPSR 恢复现场,此时PC就被赋值为了真正的返回地址
    注:该步骤和步骤7中,出现了2次赋值给PC,但是第一次只是通知CPU,让CPU知道要中断执行完毕,需要退出,然后让CPU自动执行步骤8和9. 这样设计的目的是与函数调用流程一致,但是又能让CPU能够区分函数返回和中断返回。
  10. 由于步骤9中已经实现了恢复现场的效果,所以应用程序继续执行。

附录引用:中断处理流程详解

接下来我们直接引用《The definitive guide to ARM Cortex-M3/4》第8章节关于中断处理详情的介绍的几个经典流程图

1. 中断发生时,CPU自动压栈帧+中断向量表查找时序图

在这里插入图片描述

2. 中断发生时,CPU自动压栈栈帧顺序图

在这里插入图片描述
在这里插入图片描述

3.1 中断发生时,CPU使用MSP自动压栈图

在这里插入图片描述
这种情况,一般对应于裸机程序或正在处理中断1的时候,又有高优先级中断2发生了,所以使用MSP进行压栈。
上图中的Stacking就是指自动压栈,这个图画的非常好,stacking是上升沿,在应用程序之后,在中断服务程序之前,是两个阶段的过渡,CPU自动执行。

3.2 中断发生时,CPU使用PSP自动压栈图

在这里插入图片描述
这种情况,一般对应于:发生中断前正在执行OS的某个任务,正在使用PSP,发生中断后,CPU就会使用PSP自动压栈帧。
上图中,还包括了,在处理中断1的时候,又有高优先级中断2触发,这个时候,就出现了中断嵌套,则中断2中,CPU会继续使用中断1运行过程中使用的MSP压栈帧。
上图中的Stacking就是指自动压栈,stacking是上升沿,是两个阶段的过渡,CPU自动执行。

4.1 线程模式下(使用MSP)发生中断,然后中断退出全流程

在这里插入图片描述
上述流程,对应的是裸机程序下,发生中断嵌套的全流程处理过程。
上图中的Stacking就是指自动压栈,stacking是上升沿,是两个阶段的过渡,CPU自动执行。

4.2 线程模式下(OS系统使用PSP)发生中断,然后中断退出全流程。

在这里插入图片描述
上述流程,对应的就是含有RTOS系统的程序,发生中断前正在执行某个task,然后发生了中断嵌套的全流程处理过程。
上图中的Stacking就是指自动压栈,stacking是上升沿,是两个阶段的过渡,CPU自动执行。

5. 中断退出,CPU根据EXC_RETURN自动出栈恢复现场流程

在这里插入图片描述
上述流程,主要是通过对EXC_RETURN的分析,中断退出是,到底是使用PSP还是MSP来进行出栈,恢复现场。

小结

中断处理的全流程,涉及了很多细节知识点,这些知识点对于纯应用开发者来说,基本上不需要关注,因为IDE或交叉编译器已经帮我们自动实现了,尤其CPU的中断机制巧妙的让我们可以直接使用C语言来写中断服务程序了。但是对于想要深刻理解嵌入式RTOS的人来说,中断处理的全流程知识点,就必须要掌握了,因为RTOS最核心的任务调度、上下文切换都是基于中断细节实现的。后续我们会基于这些知识点来分析RTOS底层的调度原理、上下文切换原理。

<think>我们正在讨论STM32G474微控制器的XPSR寄存器。XPSR是Cortex-M4内核中的一个重要寄存器,全称为Execution Program Status Register(执行程序状态寄存器)。它结合了三个状态寄存器:应用程序状态寄存器(APSR)、中断状态寄存器(IPSR)和执行状态寄存器(EPSR)的功能。在STM32G474中,由于它使用了Cortex-M4内核,因此XPSR寄存器的描述与Cortex-M4架构一致。 XPSR寄存器是一个32位寄存器,其位域定义如下: - 位[31:27]:N(负标志)、Z(零标志)、C(进位标志)、V(溢出标志)、Q(饱和标志)——这些标志位属于APSR部分。 - 位[26:24]:保留。 - 位[23:16]:保留(在Cortex-M4中,这些位用于异常号,但仅当IPSR有效时)。 - 位[15:10]:保留。 - 位[9]:ICI/IT(中断继续指令/If-Then标志)——属于EPSR部分。 - 位[8:0]:ISR_NUMBER(中断服务例程编号)——属于IPSR部分,当处理器处于异常处理时,此字段表示当前正在处理的异常号。 具体作用如下: 1. **APSR部分**:记录算术和逻辑运算的结果标志,用于条件分支判断。 - N:结果为负时置1 - Z:结果为零时置1 - C:进位或借位时置1(无符号溢出) - V:有符号溢出时置1 - Q:在饱和运算中发生饱和时置1,需要手动清除 2. **IPSR部分**:指示当前正在处理的中断或异常号。当处理器处于异常处理(包括中断)时,该字段不为0;在Thread模式下,该字段为0。 3. **EPSR部分**:包含执行状态信息,主要与中断继续指令(ICI)和If-Then(IT)指令块相关。 - ICI位:当打断一个多寄存器加载/存储指令(LDM/STM)时,处理器使用ICI位来保存被打断的指令的寄存器列表信息,以便在中断返回后继续执行。 - IT位:用于条件执行指令(IT指令块)的状态跟踪。 在STM32G474的编程中,XPSR寄存器通常由编译器自动管理,但在进行底层编程(如启动文件、中断处理、操作系统移植)时,可能需要直接操作或读取该寄存器。例如,在异常处理中,可以通过读取XPSR的IPSR部分来获取当前异常号。 需要注意的是,XPSR寄存器不能直接使用MOV指令访问,而是需要使用MRS(读)和MSR(写)指令。例如: ```assembly MRS R0, XPSR ; 将XPSR的值读入R0 MSR XPSR, R0 ; 将R0的值写入XPSR ``` 在C语言中,可以通过内联汇编或者CMSIS-Core提供的函数来访问。CMSIS-Core提供了以下函数来访问PSR寄存器: ```c uint32_t __get_xPSR(void); // 读取XPSR寄存器的值 void __set_xPSR(uint32_t xpsr); // 写入XPSR寄存器 ``` 但是,由于XPSR寄存器中有些位是只读的(如IPSR部分),因此写入操作需要谨慎。 另外,在异常处理中,XPSR寄存器会被自动压入栈中(与其他寄存器一起),形成异常栈帧。在异常返回时,处理器会从栈中恢复这些寄存器的值。 总结:XPSR寄存器是Cortex-M4内核中非常重要的状态寄存器,它集成了多个状态信息,包括算术标志、当前异常号和执行状态信息。理解XPSR对于深入理解STM32G474的中断处理、条件执行和异常恢复机制至关重要。 相关问题: 1. STM32G474中如何通过XPSR寄存器判断当前是否处于中断上下文? 2. 在STM32G474的异常处理中,XPSR寄存器是如何被保存和恢复的? 3. 如何利用XPSR寄存器中的条件标志位(N、Z、C、V)进行条件分支?</think>### STM32G474 XPSR寄存器详解 XPSR(Execution Program Status Register)是ARM Cortex-M4内核中的**执行程序状态寄存器**,在STM32G474微控制器中起着关键作用。它结合了三个状态寄存器的功能,用于记录处理器核心的运行状态和异常信息。 #### 1. XPSR寄存器结构 XPSR是一个32位寄存器,其位域结构如下: $$ \begin{array}{|c|c|c|c|} \hline \text{位域} & \text{名称} & \text{大小} & \text{描述} \\ \hline 31:27 & \text{APSR} & 5\text{位} & \text{应用程序状态标志} \\ 26:24 & \text{保留} & 3\text{位} & - \\ 23:16 & \text{IPSR} & 8\text{位} & \text{中断/异常编号} \\ 15:10 & \text{保留} & 6\text{位} & - \\ 9 & \text{ICI/IT} & 1\text{位} & \text{中断继续指令标志} \\ 8:0 & \text{EPSR} & 9\text{位} & \text{执行状态标志} \\ \hline \end{array} $$ #### 2. 核心功能 - **APSR(应用程序状态)** 包含算术运算标志位: - $N$ (位31):负标志(结果为负时置1) - $Z$ (位30):零标志(结果为零时置1) - $C$ (位29):进位标志(无符号溢出) - $V$ (位28):溢出标志(有符号溢出) - $Q$ (位27):饱和标志(SSAT/USAT指令触发) - **IPSR(中断状态)** 记录当前中断/异常编号(0表示无异常): - $0$ = 线程模式 - $1-15$ = 系统异常(如HardFault=3) - $\geq 16$ = 外部中断(如IRQ0=16) - **EPSR(执行状态)** 包含: - $ICI$ (位25:10):中断继续指令位置(LDM/STM中断恢复) - $IT$ (位26:10):IF-THEN指令块状态 - $T$ (位24):Thumb状态标志(必须为1) #### 3. 典型应用场景 1. **异常处理** 进入中断时自动保存XPSR到栈帧,恢复时通过`BX LR`指令自动还原: ```assembly ISR_Handler: PUSH {R0-R3, LR} ; 自动保存XPSR到栈中 ... ; 中断服务程序 POP {R0-R3, PC} ; 自动恢复XPSR ``` 2. **条件执行** 通过APSR标志实现条件分支: ```c if (xpsr & 0x80000000) { // 检查N标志 // 负数处理 } ``` 3. **调试诊断** 当发生HardFault时,通过读取XPSR定位异常源: ```c void HardFault_Handler(void) { uint32_t xpsr = __get_xPSR(); uint8_t exception_num = (xpsr >> 16) & 0xFF; // 提取IPSR LOG("Exception %d occurred", exception_num); } ``` #### 4. 访问方式 - **汇编访问**: ```assembly MRS R0, XPSR ; 读取XPSR到R0 MSR XPSR, R1 ; 将R1值写入XPSR ``` - **C语言访问**(使用CMSIS): ```c #include "core_cm4.h" uint32_t xpsr = __get_xPSR(); // 读取寄存器 __set_xPSR(0x10000000); // 设置Q标志 ``` > ⚠️ 注意:直接修改XPSR可能破坏处理器状态,通常仅由编译器或OS内核操作[^1]。 #### 5. 与其他寄存器关系 - 与**CONTROL寄存器**协同管理特权级别 - 与**PRIMASK/FAULTMASK**配合实现中断嵌套控制 - 异常返回时与**EXC_RETURN**值共同决定栈帧恢复方式
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值