STM32开发(中断模式:外部中断)
一、处理器的工作模式
Cortex-M核的工作模式:异常模式 线程模式Cortex-A核的工作模式:ARM-v7架构设计的A核的工作模式:非特权模式: User(用户模式)特权模式: 1.非异常模式:Sys2.异常模式IRQ模式(普通中断模式)FIQ模式(快速中断模式)SVC模式(超级管理员模式)ABT模式(中止访问模式)UDF模式(未定义异常模式)ARM-v8架构设计的A核的工作模式:在v7架构的基础上多以下两个工作模式:MON(电源管理模式)HYP(虚拟化技术模式)
1、异常源
异常源是指触发处理器执行异常事件对应的处理逻辑的源头
异常源是异常事件的集合
异常源下支持很多异常事件
异常模式 | 异常源 | 异常源下的异常事件 |
IRQ模式 | 一系列触发处理器进入IRQ模式的异常源 | 普通中断,定时器中断 |
FIQ模式 | 一系列触发处理器进入FIQ模式的异常源 | 内核中断,高优先级中断 |
SVC模式 | 复位异常源 | 上电复位,按键复位 |
软中断异常源 | swi执行软中断指令 | |
ABT模式 | 数据终止访问异常源 | 非法访问或使用没有权限的数据(段错误) |
指令终止访问异常源 | 汇编指令格式错误、 汇编指令访问没有权限的空间 | |
UDF模式 | 未定义异常源 | 指令/变量未被定义过 |
1、5种异常模式对应七种异常源
2、每种异常源下存在很多的异常事件
3、SVC模式下的复位异常源的优先级等级最高,处理器优先处理
2、异常向量表
异常向量表:就是异常源的集合
当产生异常事件后,处理器会检测当前这个异常事件属于哪个异常源
此时处理器会根据异常源去异常向量表中对应的地址,查找对应的异常源中对应的异常事件注意:1、处理器只会根据异常向量表中固定的地址查找异常源,异常源地址是不能随意变化的2、异常向量表共占内存空间32字节,每个异常源占用4字节存放异常源地址,保留了4字节作为预留空间
为什么需要引入异常向量表?
由于异常触发后,最终需要执行异常处理函数
而对于函数而言,当开发板/系统上电复位后,函数的地址、参数的地址、变量的地址可能都会发生改变,
对于CPU而言,他无法知道变化后的地址
此时,就需要固定一片内存空间地址,用于引导CPU找到最后的异常处理函数
所以,ARM公司开发并生产内核时,固定了一片32个字节的地址空间,
专门用于存放各个异常源的地址,他就是异常向量表
二、异常处理流程
1、自动保存现场(CPU自动完成)
自动保存现场需要做四件事:
1、将CPSR寄存器内的值保存到SPSR_<MODE>寄存器中
2、修改CPSR寄存器中的位:1.修改CPSR寄存器中的I位和F位(选择是否屏蔽IRQ模式和FIQ模式)2.修改CPSR寄存器中的T位(选择使用ARM汇编指令集/Thumb汇编指令集)3.修改CPSR寄存器中的M位(选择需要进入的异常模式)
3、将函数返回地址保存到LR链接寄存器中
4、将PC计数寄存器指向异常向量表
2、手动返回现场(程序员手动完成)
1、将SPSR_<MODE>寄存器中的值赋值给CPSR寄存器
2、将LR链接寄存器中的值赋值给PC计数寄存器
3、ARM汇编代码模拟异常事件处理流程
.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
三、分析芯片手册(EXTI、NVIC)
NVIC:嵌套向量中断控制器
EXTI:外部中断和事件控制器嵌套:中断的嵌套,指的是中断具备优先级等级,高优先级等级的中断信号可以打断低优先级的中断信号向量:所有异常中断都由异常向量表统一管理在Cortex-M核中,中断处理一般使用 EXTI 和 NVIC 这两个寄存器实现
在Cortex-A核中,中断处理一般使用 EXTI 和 GIC(GICC+CPID) 这两个寄存器实现
1、外部中断章节介绍(EXTI)
1)输入事件编号
2)EXTI的主要特点
3)EXTI框图分析
4)寄存器功能分析
中断挂起:是指中断信号到达,等待被处理,需要执行这个中断信号对应的逻辑代码
中断挂起标志位:是表示当前中断信号到达等待处理的标志位
中断:就是判断中断标志位是否被挂起,挂起后执行中断信号对应的异常事件处理代码
5)GPIO端口选择
6)寄存器分析
以KEY1 - PC9为例,需要实现
KEY1按下(产生下降沿信号)时,LED灯点亮对EXTI外设控制器中控制PC9引脚的寄存器做出处理:1、需要找到PC9接入到EXTI外设控制器的IO端口选择寄存器(找这个寄存器中用于代表PC9引脚的位)2、将PC9配置为下降沿触发方式3、设置不屏蔽PC9引脚产生的中断信号4、检测PC9引脚是否触发中断,也就是PC9引脚产生的下降沿信号是否被硬件挂起
(1)EXTI_FTSR1寄存器(下降沿触发寄存器)
(2)EXTI_FPR1寄存器(下降沿触发标志寄存器)
当我们检测按键是否按下时,也就是检测中断是否被挂起,也就是读取这个寄存器对应位是否为1
读取到1:就代表中断被挂起,可以执行处理逻辑
读到到0:就代表中断没有被挂起,不需要执行处理逻辑当我们读取到中断被挂起后,为了让中断不一直处于被挂起状态,需要人为手动解除中断的挂起
(3)EXTI_EXTICRm寄存器(GPIO端口引脚选择寄存器)
(4)EXTI_IMR1寄存器(输入事件频闭寄存器)
2、中断嵌套向量章节介绍(NVIC)
1)NVIC的主要特点
2)中断号
四、标准库配置外部中断
五、HAL库配置外部中断
1、STM32CudeMX配置初始化
1)配置为外部中断触发
外部中断是GPIO输入模式中的一种,并不属于复用模式,配置为双边沿触发
2)使能NVIC下的EXTI的中断信号
3)配置中断触发的优先级
不要配置外部中断的优先级和系统自带中断的优先级同级,这会影响系统的绝对优先,这里优先级设置成 1 即可