Day07_STM32 单片机 - 中断
一、处理器的工作模式
1.1 Cortex-M 核工作模式
1.异常模式
2.线程模式
1.2 Cortex-A 核工作模式
ARM-v7架构:1.非特权模式:User模式2.特权模式:2.1 非异常模式:Sys模式2.2 异常模式:IRQ模式 - 普通中断异常模式FIQ模式 - 快速中断异常模式SVC模式 - 超级管理异常模式ABT模式 - 中止访问异常模式UDF模式 - 未定义异常模式
ARM-v8架构:多两种:MON模式 - 安全监管模式、HYP模式 - 虚拟化技术模式
二、异常处理流程
图 1 异常处理流程图
2.1 异常源
异常源:触发处理器执行异常事件对应的处理逻辑的源头(集合);
异常源支持很多异常事件。
=================================================================
- 5 种异常模式对应 7 种异常源;
- 每种异常源存在很多异常事件 - 异常源就是异常事件的集合;
- SVC 模式下的复位异常源优先等级最高,处理器优先处理。
2.2 自动保护现场 - CPU 自动完成
自动保护现场需要做 4 件事:
1.将 CPSR 寄存器中的值保存到 SPSR_<MODE> 寄存器中
2.修改 CPSR 寄存器中的位:
2.1 修改 CPSR 寄存器中的 I / F 位(是否屏蔽 IRQ / FIQ 模式);
2.2 修改 CPSR 寄存器中的 T 位(是否使用 ARM / Thumb 汇编指令集);
2.3 修改 CPSR 寄存器中的 M 位(进入对应的异常模式)。
3.将函数的返回地址保存到 LR 寄存器中;
4.PC 寄存器指向异常向量表。
2.3 手动恢复现场 - 程序员手动完成
- 将 SPSR_<MODE> 寄存器中的值恢复到 CPSR 寄存器中;
- 将 LR 寄存器中的值赋值给 PC 寄存器。
2.4 异常向量表
地址 异常类型
0x1C FIQ
0x18 IRQ
0x14 (Reserved)
0x10 Data Abort
0x0C Prefetch Abort
0x08 Software Interrupt
0x04 Undefined Instruction
0x00 Reset
异常向量表:异常源的集合
当发生异常事件后,处理器检测当前异常事件所属异常源,就需要给各个异常源分配不同的内存空间地址,处理器去寻址查找。
异常向量表占内存空间的 32 个字节,每个异常源占 4 个字节空间,同时有 4 个字节的空间保留。
图 2 异常处理的流程
为什么引入异常向量表:
在异常出发后,最后是需要执行异常处理的函数;
而在开发板 / 系统上电复位后,函数的地址、参数的地址、变量的地址可能发生改变,对于 CPU 无从知晓变化后的地址,所以可以固定一片内存空间地址,引导 CPU 找到异常处理函数。
ARM 公司在开发并生产内核时,固定一片 32 个字节的地址空间,存放各个异常源的地址,称为异常向量表。
2.5 汇编代码模拟异常处理流程
.text .global _start _start: @ 构建异常向量表b reset_handlerb undefined_handlerb swi_handlerb prefetch_handlerb data_handlerb . @ 占4个字节空间操作b irq_handlerb fiq_handlerreset_handler:@ 为SVC模式下的SP寄存器给定一个内存空间地址ldr sp, =0x40000820@ 从SVC模式切换到User模式下,执行用户代码msr cpsr, #0xD0@ 用户代码,以下相当于main函数mov r0, #0x1mov r1, #0x2@ 软中断异常事件触发@ swi 2这条汇编指令执行完毕后,需要看到的效果@ 1、CPSR寄存器中的值是否被保存到SPSR寄存器中@ 2、CPSR寄存器中的值是否被改变(IFTM位)@ 3、LR寄存器中是否保存函数的返回地址@ 4、PC是否指向异常向量表中软中断异常源的地址swi 2add r2, r1, r0undefined_handler:swi_handler:@ 压栈保存现场,保存局部变量和函数返回地址stmfd sp!, {r0-r1, lr}@ 软中断异常源下第一个异常事件的处理函数mov r0, #0xffmov r1, #0xeeadd r2, r1, r0@ 出栈恢复现场,恢复局部变量和函数返回地址@ 还需要恢复SPSR寄存器中的值给到CPSR寄存器@ ^的作用:用于将SPSR寄存器中的值赋值给CPSR寄存器ldmfd sp!, {r0-r1, pc}^prefetch_handler:data_handler:irq_handler:fiq_handler:stop: b stop
.end
当异常发生时,CPU 根据异常的类型,找到异常向量表中对应异常源的固定地址,随后跳转到改地址去执行相应的异常处理函数,这和异常源的名字无关,名字只是帮助开发者理解的符号。
三、分析按键的电路图
KEY1 - PC9
KEY2 - PC8
KEY3 - PC5
图 3 按键抖动示意图
GPIO 检测按键的抬起和按下(高 / 低电平),中断检测按键抬起 / 按下的时机(上升沿 / 下降沿)。
四、分析芯片手册
图 4 NVIC 和 EXTI
EXTI:外部中断和事件控制器
NVIC:嵌套向量中断控制器
嵌套:中断的嵌套,指的是中断具备优先级等级,高优先级等级的中断信号可以打断低优先级的中断信号。
向量:所有异常中断统一由向量表进行管理。
在使用 Cortex-M 核(MCU),中断处理一般使用 EXTI + NVIC 来实现
在使用 Cortex-A 核(MPU),中断处理一般使用 EXTI + GIC(GICC+CPID) 来实现
4.1 EXTI 介绍
1)介绍
图 5 EXTI 介绍
外部中断和事件控制器(EXTI)通过可配置的事件输入来管理各个 CPU 和系统唤醒。它向电源控制提供唤醒请求,并向 CPU NVIC 生成中断请求以及向 CPU 事件输入生成事件。对于 CPU,需要额外的事件生成模块(EVG)来生成CPU事件信号。
2)主要特性
图 6 EXTI 主要特性
- 支持 26 个输入事件编号;
- 可选择的边沿触发方式 - 上升沿触发、下降沿触发、上升沿下降沿都触发;
- 中断挂起状态标志位 - 上升沿和下降沿的中断状态在硬件层面被分开记录和处理;
- 支持中断信号和输入事件的屏蔽功能;
- 支持多个 GPIO 端口的选择。
4.2 输入事件编号
图 7 输入事件编号列表
输入事件编号(Event Input Number)是硬件层用于唯一标识外部中断/事件(EXTI)源的数字ID,每个编号对应一条独立的EXTI线(如编号0对应
EXTI[0]
)。其核心作用是通过数字映射将物理引脚的电平变化与系统中断/事件处理逻辑精准关联。
4.3 EXTI 内部框图
图 8 EXTI 内部框图
图 10 EXTI 内部框图描述
EXTI 外设控制器中有一个寄存器块,这个寄存器块被连接在 AHB3 总线上(EXTI 被连接在 AHB3 总线上)。
输入事件触发块用于提供输入事件边沿触发的逻辑,也就是需要设置输入事件的触发方式为上升沿触发 / 下降沿触发 / 双边沿触发。
输入事件屏蔽块用于提供输入事件的分配(可以分配给 PWR 用于系统唤醒、可以分配给 CPU 下的 NVIC 用于中断控制、也可以分配给 EVG 用于事件输出、还可以把上述操作屏蔽掉)。
IO 端口选择块提供了 GPIO 端口选择的功能(也就是让 EXTI 知道是哪个 GPIO 端口产生了中断信号)。
4.4 寄存器功能分析
图 11 EXTI 功能描述
中断的挂起:中断信号到达,等待被处理,需要执行这个中断信号对应的逻辑代码。也就是执行中断信号对应逻辑代码前,需要判断这个中断信号是否发生,即这个中断是否被挂起。
4.5 GPIO 端口选择
图 12 EXTI 多路选择(GPIO 端口选择)
4.6 寄存器分析
1)EXTI_FTSR1 寄存器
图 13 EXTI_FTSR1
下降沿触发选择寄存器
写入 0:PC9 引脚下降沿触发不使能
写入 1:PC9 引脚下降沿触发使能
2)EXTI_FPR1 寄存器
图 14 EXTI_FPR1
图 15
下降沿触发挂起寄存器
rc_w1权限:
r c_w1
写入0:
没有影响
写入1:人为清除对应的值-----------------------------------------------------
读 0:没有下降沿触发请求存在
也就是下降沿没有触发,中断没有挂起
读 1:下降沿触发请求存在
也就是下降沿触发,中断被挂起
当我们检测按键是否按下时,也就是检测中断是否被挂起,也就是读取这个寄存器对应位是否为 1:
读取到 1:就代表中断被挂起,可以执行处理逻辑;
读到到 0:就代表中断没有被挂起,不需要执行处理逻辑;
当我们读取到中断被挂起后,为了让中断不一直处于被挂起状态,需要人为手动解除中断的挂起。
3)EXTI_EXTICRm 寄存器
图 16 EXTI_EXTICRm
图 17 GPIO 端口的选择