目录
基本概念
在处理器中,中断相当于是对于突发事件的处理过程。当遇到内部/外部的紧急事件需要处理时,暂停中止当前程序,转而去处理紧急的事件,处理完毕后再返回被打断的程序继续向下运行。
暂停:保护现场
继续:恢复现场
中断的意义
中断能够对突发事件进行及时处理,实现程序的并行化(时间片),进而提高CPU的工作效率,当发生突发事件时,比如外部触发的输入信号、定时器溢出等,中断会立即打断正在执行的过程,转而执行终端服务函数(ISR)来处理该事件。
并行化
在STM32中,程序的并行化是指通过使用中断机制,使得当发生突发事件时,可以立即处理该事件,而不需要等待当前正在执行的程序完成。传统的程序执行方式是顺序执行,即按照代码的顺序逐行执行,这种方式存在一个问题,即当程序执行某个任务时,如果发生了突发事件,程序需要等待当前任务执行完毕才能响应事件,这样有可能会导致事件处理延时,从而影响系统的响应速度。但是使用中断机制可以解决这个问题,当突发事件发生时(例如外部输入信号的中断),系统会立即打断当前正在执行的程序,转而执行于该事件相关的中断服务程序,中断服务程序可以快速响应事件并处理相应的逻辑,而无需等待当前任务完成。通过这种方法,程序的执行可以在某个任务被打断的同时,立即响应其他突发事件,这样就实现了程序的并行化处理,提高了系统的响应速度和效率。
为什么要提高系统效率?
因为CPU对于没有发生的事情是在不停轮询(即一直询问事件有没有发生),中断能够提高CPU的效率,同时能够对突发事件做出实时处理,从而实现程序的并行化以及嵌入式系统进程间的切换。
中断处理过程
中断处理过程
过程分为进入中断和退出中断。
进入中断
- 处理器自动保存现场的数据到堆栈里(堆栈——内存)
- {PC,xPSR,R0-R-R2,LR}
- 一旦入栈结束,ISR便可开始执行中断服务程序
退出中断
- 中断前的现场被自动从堆栈区中恢复
- 一旦出栈完成就继续执行被中断打断的指令
- 出栈的过程也可以被打断,使得随时可以响应新的中断而停止出栈并保存现场
R0-R12
R13(栈指针SP):指向栈顶地址
R14(链接寄存器LR):存放返回地址
R15(程序计数器PC):保存要执行的指令指针
例如:
老师正在讲课 (正在执行的主程序)
老师被通知去开会 (产生一个外部中断信号)
暂停讲课 (压栈,保护现场)
根据会议室的门牌号找到会议室 (根据中断向量表跳转到中断服务程序)
开会 (执行中断服务程序)
回到教室继续执行上课 (回复现场,继续执行主程序)
中断体系结构
中断和异常的区别
中断是微处理器外部发送的,通过中断通道送入处理器内部,一般是硬件引起的(例如按键中断、串口、串口接收中断),而异常处理通常是位处理器内部发生的,大多是软件引起的(例如除法出错异常、特权调用异常等)。无论是中断还是异常,微处理器通畅都有相应的中断/异常服务程序。
NVIC(嵌套向量中断控制器)
中文参考手册155页
NVIC主要功能
负责管理中断(相当于CPU的小助理):中断管理、支持异常及中断向量化处理、支持嵌套中断。
管理中断事件
每一个中断事件都有执行或禁止两种状态,由NVIC负责将中断事件标记为清除和挂起两种状态。处理器的中断可以以电平的形式,也可以以脉冲的形式,这样中断控制器就可以处理任何中断源。当中断执行完成时,NVIC会将中断事件置为清除状态。
支持中断向量化处理
当中断事件发生时,处理器会将PC(程序计数器PC:保存要执行的指令地址)设置为一个特定地址(中断事件入口函数的地址),进而跳转到中断服务程序去执行,这就是一个中断异常向量,因为每个异常源或者中断事件都会对应一个服务程序的入口地址,将这些地址按照优先级进行排布后组成的一张表就称为中断异常向量表。
Cortex-M0内核可以处理15个内部异常和32个外部中断,STM32G030只使用了6个内部异常和28个外部中断。
向量化处理中断的好处
传统的处理方式需要软件去完成。采用向量表处理异常,M0处理器会从存储器的向量表中自动定位异常的程序入口。从发生异常到异常的处理中间的时间被缩短。
支持中断嵌套
要启用中断嵌套,首先需要在NVIC模块中配置中断优先级,每个中断都有一个相应的优先级,中断嵌套使得某个中断能够打断正在执行的较低优先级中断,从而及时响应更高优先级的中断请求。
三个固定的优先级,都是负值,不能够改变。
四个可编程优先级,用两个bit位表示:00 01 10 11(0、1、2、3)
优先级数值越小,优先级等级越高。
注意!
不同优先级的中断同时发生,优先处理优先级编号较小的那个(中断优先级)
同一优先级的中断同时发生,中断向量号较小的那个优先响应(响应优先级)
EXIT
外部中断控制器
主要功能
产生中断、事件
产生中断的目的
将信号送入NVIC,进而运行中断服务程序,实现对应功能,是软件级的。
产生事件的目的
将采集到的一个脉冲信号送到某个外设,进而驱动某些设备做出动作,是电路级别的传输,是硬件级的。
在STM32G030中,共有最多238个中断/事件线可用,其中GPIO口连接到16个外部中断/事件线。
中文参考手册161页
编号1 是信号输入线,EXIT支持产生多达28个外部事件/中断请求。
编号2是边沿检测电路,用于检测上升沿或者下降沿信号,它会根据上升沿触发选择寄存器(EXIT_RTSR)和下降沿触发选择寄存器(EXIT_FTSR)对应位的设置来控制信号触发。边沿检测电路是以输入线作为信号输入端,检测是否有边沿跳变,检测到有边沿跳变输出有效信号 1 给编号3电路,否则输出无效信号 0 .
编号3是一个或门电路,信号来源是外部事件或软中断/事件寄存器产生,能够允许我们通过程序控制EXIT_SWIER就可以启动中断/事件线。
编号4是一个与门电路,信号来源是编号3送来的信号和中断屏蔽寄存器的值,如果中断屏蔽寄存器为0就不会将信号送到NVIC,只有编号3送来了中断信号且中断屏蔽寄存器允许产生中断,才会将中断信号送到NVIC。
编号5是一个与门电路,信号来源是编号3送来的信号和事件屏蔽寄存器的值,如果事件屏蔽寄存器为0,则不会将信号送到脉冲发生器,只有编号3送来了信号且事件屏蔽寄存器允许产生事件,才会将信号送入到脉冲发生器(编号6),进而产生脉冲来控制外部设备做出动作。
红色虚线指示的电路流程是一个产生事件的线路,最终输出一个脉冲信号,产生事件线路是在编号3电路之后与终端线路有所不同,之前的电路都是共用的。
按键中断实验(外部中断)
实验要求
STM32正常执行LED灯闪烁主程序,当检测到按键按下时处理中断事件,通过串口打印 “hello world” 。
实验步骤分析
- 使能相应的时钟
- 配置GPIO管脚为中断功能
- 设置中断优先级
- 使能相应的中断
- 实现中断服务程序
__weak void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Rising_Callback could be implemented in the user file
*/
}
WEAK弱符号
如果在函数名称前面加上__weak修饰符就会称这个函数为 “弱函数” ,加上了__weak修饰的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak修饰的函数,并且编译器不会报错。
串口中断实验
实验要求
主程序发送一串字符串 “HelloWorld” ,当字符串发送完成时触发中断事件,调用中断服务程序发送 “hello”
实验步骤分析
- 使能相应的时钟
- 配置GPIO管脚为串口功能
- 设置中断优先级
- 使能相应的中断
- 实现中断服务程序
主程序实现发送
找发送结束的回调函数
重写回调函数
练习
要求
实现接收完成中断,当接收到第四个字符时,产生接收完成中断事件,并在服务程序中输出 “Very OK!”
代码
练习
要求
显示屏显示计时时间,格式为00:00:00,时间以秒为单位自加,当检测到按键按下这个中断事件发生后,时间归零,继续从零开始。