中断的概念
(就是假如你在学习,这个时候电话响了,这个时候你停下你学习的状态,接电话,接完电话之后回来继续学习。这就是中断的一个过程。)
中断:中断是指计算机在运行的过程中,出现某些意外的情况需要主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
中断源:意外情况(电话铃声响)
中断处理程序:处理新情况的程序(接电话这个动作)
中断请求:中断信号(电话铃声)
中断的过程
- 中断源发出中断请求
- 保存现场
- 执行具体的中断处理函数
- 从中断中返回
- 恢复现场
中断类型
可屏蔽中断(maskable interrupt):这是硬件中断的一类。可通过中断屏蔽寄存器中设定位掩码来实现。(理解:我么可以操作我们的中断寄存器,将我们的某一个IO口或者某一类中断进行屏蔽,当这个中断过来的时候,CPU不予理睬。)
非可屏蔽中断(non-maskable interrupt,NMT):这也是硬件中断的一类,无法通过在中断屏蔽寄存器中设定位掩码来关闭。(理解:就是这个中断是没有办法被屏蔽掉。典型的例子就是:时钟中断(一个硬件时钟以恒定的频率--如50hz--发出的中断。)
处理器间中断(interprocessor interrupt):一种特殊的硬件中断。由处理器发出,被其他处理器接收。仅见于多处理器系统,以便于处理器之间通讯或同步。
伪中断(spurious interrupt):一类不希望被产生的硬件中断。发生的原因有很多种,比如中断线路上信号异常,或是中断请求设备本身有问题。(可以理解为是硬件的一种BUG)
软件中断:是一条CPU指令,用于自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态的子例程,它常被用做实现系统调用。(也就是软件内的一些模拟中断,在程序中,一般中断函数是没有返回值也没有形参的。)
中断优先权
在某一时刻有几个中断源同时发出中断请求,处理器只会响应其中优先级最高的中断源。当一个处理一个终端服务函数期间,出现另一个中断源的请求时,如果后者优先级低于前者,处理器不理睬。反之,处理机立即响应后者,进入所谓的嵌套中断
。
中断向量
对应每一个中断源会设置一个向量,这些向量的顺序存储于主存储器的特定存储区。向量的内容是相应的中断服务函数的起始地址和处理机状态字。在响应中断时,由中断系统硬件提供向量地址,处理机根据该地址取得向量,并转入相应的中断服务函数。
STM32F4XX中断
接下来以STM32F4系列芯片理解中断:
NVIC:
嵌套向量中断控制器,控制着整个芯片中断的相关功能,它跟内核是紧密耦合的。STM32的每一个IO口都可以作为外部中断的中断输入口
。STM407的中断控制器支持22个外部中断/事件请求,每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
NVIC_InitTypeDef
结构体
typedef struct
{
uint8_t NVIC_IRQChannel; // 设置中断源,不同的中断源不一样
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
uint8_t NVIC_IRQChannelSubPriority; // 子优先级
FunctionalState NVIC_IRQChannelCmd; // 中断使能
} NVIC_InitTypeDef;
EXTI
外部中断/事件控制器
STM32F4 IO
口都可以作为外部中断的中断输入口。STM32F4的中断控制器支持23个外部中断/事件请求的边沿检测器。每根输入线都可单独进行配置,以选择类型(中断或者事件)和相应的触发事件(上升沿触发、下降沿触发或者边沿触发)。每根输入线还可单独屏蔽。挂起寄存器用于保持中断请求的状态线。
1.编号1是输入线,EXTI控制器有23个中断/事件输入线,这些输入可以通过寄存器设置为任意一个GPIO,也可以是一些外设事件,输入线一般是存在点平变化的信号。
2.边缘检测电路,它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应的设置来控制信号的触发,边缘检测电路以输入线作为作为信号的输入端,如果检测到信号的跳变就输入有效信号1给编号3电路,否则输出无效信号0.
3.编号4电路是一个与门电路,它的一个输入为编号3电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。与门电路要求输入都为1才输出1,导致的结果如果EXTI_IMR设置为0时,不管编号3电路的输出信号是1还是0,最终编号4电路输出的信号都为0;如果EXTI_IMR设置为1时,最终编号4电路输出的信号才由编号3电路的输出信号决定,这样我们就可以简单控制EXTI_IMR来实现是否产生中断的目的。编号4电路输出的信号会被保存到挂起寄存器中(EXTI_PR)内,如果确定编号4电路输出为1就会把EXTI_PR对应位置1.
编号5是将EXTI_PR寄存器内容输出到NVIC内,从而实现系统中断事件控制。
4.编号5是将EXTI_PR寄存器内容输出到NVIC内,从而实现系统中断事件控制。
产生中断线路目的是把输入信号输入到NVIC,进一步会运行中断服务函数,实现功能,这是软件级的。
typedef struct
{
uint32_t EXTI_Line; // EXTI_Line:EXTI中断/事件线选择,可选EXTI0或EXTI22
EXTIMode_TypeDef EXTI_Mode; // EXTI_Mode:EXTI模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)
EXTIMode_TypeDef EXTI_Mode; // EXTI边沿触发事件,可选上升沿(EXTI_Trigger_Rising)、下降沿触发(EXTI_Trigger_Falling)或者上升沿和下降沿都触发(EXTI_Trigger_Rising_Falling)
FunctionalState EXTI_LineCmd; // 控制是否使能EXTI线,可选使能EXTI线(ENABLE)或禁用(DISABLE)
}EXTI_InitTypeDef;
总结:可以这么理解,外部中断作用于外设,外设产生中断信号的机制就是外部中断,最终输入的外部中断信号给了NVIC;而NVIC是STM32的内部中断外设,是STM32的内部中断机制,NVIC的输入是外部中断等一系列中断信号,NVIC主要就是在接收到这些外部中断信号之后,反馈输出,对中断信号进行处理。