在处理器中,中断是一个过程,即CPU在正常执行程序的过程中,遇到外部/内部的紧急时间需要处理,暂时中止当前程序的执行,转而去处理紧急的时间,等待紧急事件处理完毕后再返回被打断的程序处继续往下执行。
举例来说就是,当你在看电视的时候,电话突然响了,那么你就会暂停看电视这一行为,转而去接电话,而接电话这一行为就是我们日常生活中的中断现象。
中断可以提高CPU的效率,同时对突发事件做出实时处理。实现程序的并行化,实现嵌入式系统进程之间的切换。
中断的处理过程包括进入中断和退出中断
进入中断过程中,处理器会自动保护现场,将进入中断前的各个寄存器的数值压入栈中,进行现场保护;处理器完成中断程序以后,会返回主程序的运行中,处理器会从栈中将保护的数值重新拿出,执行出栈操作,从而回到正常的处理器执行过程中。
上图即为stm32f1系列中断体系结构,其中NVIC为嵌套向量中断控制器,位于cortex-M3内核之中,是arm公司设计的,专门用于管理中断的控制器,对于所有的内核中断,包括复位、总线错误、滴答定时器等,以及所有的外部中断,包括EXTI外部中断、串口中断、定时器中断等等都是通过NVIC来进行控制的。我们第二节来详细介绍NVIC嵌套向量中断控制器。
NVIC主要有以下三个功能
cortex-M3支持256个中断(通过8个寄存器来控制,每个寄存器32位。刚好支持256个中断)。其中包括16个内核中断和240个外部中断。但是stm32f1并没有使用cortex-M3的所有中断,而是只使用了一部分,另外的部分进行保留。
在cortex-M3处理器中,每个外部中断都能够被使能或者禁止,并且可以被设置为挂起状态或者清除状态。
CM3内核支持256级中断,stm32f1虽然没用这么多中断,但是stm32f1中的中断也有很多。当中断发生时,如何快速相应中断就成为了一件非常重要的事情。
我们知道,CPU的程序运行到哪个地方,都是通过指令地址计数器PC控制的,当PC指向哪个地方,哪个地方的程序就会进行运行。所以这样就为中断的响应提供了一个思路。
所以每当异常或者中断放生时,处理器会把PC设置为一个特定地址,这一地址就称为异常向量。每一类异常源都有对应一个特定的入口地址,这些地址按照优先级排列以后就组成一张异常向量表,每次异常出现时,CPU都会快速进行异常向量表的定位,从而进行中断的快速相应。
上图为中断及异常向量表的部分截图。
注:异常一般是指内核中断,中断一般是指外部中断
中断嵌套是指,当一个中断程序正在运行时,又有新的更高级的优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次返回。
如果要介绍中断嵌套,那么就要提到中断优先级,其中中断优先级包括抢占优先级和响应优先级,抢占优先级在前,响应优先级在后。在NVIC中有一个专门的寄存器:中断优先级寄存器NVIC_IPRx用来配置外部中断的优先级,IPR的宽度为8位,原则上可以可配置255级优先级,但是,CM3芯片都会精简设计,只使用IPRx中的高4位。
在IPR中的4位,又分为抢占优先级和响应优先级,这两个优先级各占及各位又要根据SCB->AIRCR中的中断分组设置来决定,在一个项目中,当优先级分组确定以后,整个工程项目都要使用这个优先级分组,不再改变。
中断优先级总结
stm32有很多的外部中断,我们以GPIO的外部中断(EXTI)为例,EXTI一般用于控制由GPIO口高低电平变化而引发的外部中断。
每个GPIO都有16根数据线连接出来,但是,不可能每个GPIO口都要接入到EXTI控制器中,所以会经过AFIO的中断引脚选择,这个AFIO我们后续再继续说,所以通过这个中断引脚选择,以后,就可以将每个GPIO组选择到的信号线连接到EXTI中,并且加上PVD、RTC、USB、ETH这四个信号线就组成EXTI的20个输入信号。这20个输入信号经过EXTI以后就可以分成两个部分,一部分通向NVIC用于引发中断,另一部分可以通过20根数据线进入其他外设来引发触发事件响应。
由于不可能每个GPIO口都接入到EXTI控制器中,所以会经过AFIO中断引脚选择,这个AFIO主要是用于引脚复用功能的选择和重定义。在stm32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择。
下面是AFIO的基本结构:
从图中我们可以看到,每个GPIO组的相同编号的IO口是无法实现同时中断的,所以我们上面说所有的GPIO口,相同的Pin无法同时触发中断,这一点编程的时候要注意。
cubemx的配置和原来GPIO的配置是相同的,不同之处在于引脚的配置和中断的配置,具体不同点如下:
以上就是通过PA2口的外部中断来实现PA1口LED灯亮灭的具体函数,可以动手来试一试。
和EXTI有关的寄存器主要有以下几个寄存器
中断屏蔽寄存器主要是用来屏蔽来自线x上的中断请求的。
如果将中断屏蔽寄存器上的对应位置0,则该位上的中断请求就会被屏蔽,那么中断请求就无法输送到NVIC。
事件屏蔽寄存器的作用和中断屏蔽寄存器的作用相似,都是用来屏蔽中断的,但是事件屏蔽寄存器是用来屏蔽线x上的事件的。同样,置0则屏蔽中断。
这两个寄存器主要是用来进行外部边沿唤醒中断使用的,当选择下降沿或者上升沿触发外部中断的时候,这两个寄存器就会进行配置。
软件中断事件寄存器主要是和软件中断事件有关的寄存器,我们平常不太使用这一寄存器,了解即可。
挂起寄存器主要是用来进行中断挂起的,我们前面提到过,如果优先级高的中断正在执行,当优先级较低的中断发出信号的时候,是无法打断高优先级的中断的,因此需要将此中断暂时进行挂起,这个中断挂起寄存器就是用来进行中断挂起的。
以上就是关于中断的相关知识点,欢迎大家批评指正并进行补充。