由于之前一直使用PIC和51的芯片,从没接触过STM32系列的芯片,近期着手学习STM32F10x的芯片,通过学习后发现STM32的中断系统比较特殊(与PIC和51相比较........),有着不同的响应方式,看了几遍相关的手册和视频资料,还是有些稀里糊涂,通过实际写代码配置芯片后,逐渐有点眉目了,因此想记录下来,算是总结笔记。当然文章中有存在描述错误和不足的地方,还请大家指正。(可能有些地方理解的方式存在问题,望指教。)
STM32采用了ARM Cortex_M3内核,而Cortex_M3内核具有256个中断源,其中内核自己的有16个中断源和外部设备的(最多)240个中断源,每个中断源都具有自己独立的中断优先级控制寄存器,该中断优先级寄存器是一个8位的寄存器。因此,一个完整的Cortex_M3内核的每一个中断源具有256级的中断优先级范围,但这是一个完整Cortex_M3内核的中断结构。
在STM32芯片中,并没有这么多的中断源和中断优先级,在我们的STM32中有内核的16个中断源和外部设备的68个中断源。既然STM32没有使用Cortex_M3全部的中断源,那么STM32也没有256级的中断优先级编程范围。STM32的各个中断源的中断优先级设置寄存器也并没有8位全部使用,而是只使用了高4位。详情如下图所示:↓
※ 注:对于STM32的各个中断源的中断优先级设置寄存器中的这4位,我们还要进行分组后才能使用,我们将这4位分为2组。第一组高位部分我们分为“抢占优先级”,第二组低位部分我们分为“响应优先级”。在Cortex-M3中对于中断的分组模式使用了一个特定的寄存器“应用程序中断及复位控制寄存器(AIRCR)”进行设置与保存。AIRCR这个寄存器是一个32位的寄存器,我们使用这个寄存器中的三位[第10、9、8位]用于设置与保存中断分组状态,这三个位具有特定的名称“PRIGROUP”。通过设置PRIGROUP的数值,规定和设置了 整个系统中每一个中断源的 优先级格式,具体分组详情如下↓。
中断优先级分组说明:通过以上表格我们可以看到,划分的5种中断分组与中断优先级之间的关系。比如我们现在将我们的芯片中断系统设置为 第2组( PRIGROUP 的值 =101),此时我们芯片上所有各个中断源的抢占优先级在中断优先级寄存器中占用2位(取值范围0~3),所有各个中断源的响应优先级在中断优先级寄存器中也是占用2位(取值范围0~3)。这里的抢占优先级和响应优先级的取值大小决定了优先级的高低, 取值越小所代表的优先级就越高 。
★ 注意 ★ :Cortex-M3内核规定,不管是使用了多少位的优先级表达方式,被裁减掉的始终是优先级寄存器中的“低位”,而不是高位,优先级寄存器是遵循高位对齐的原则。Cortex-M3内核的中断优先级寄存器,在分组的时候做出了规定,“响应优先级至少是1位(也就是说用于表示响应优先级的位数在分组的时候必须最少要有1位)”因此,完整的Cortex-M3内核的中断优先级中抢占优先级最多是7位。但是
Cortex-M3内核允许中断优先级寄存器分组为:所有位都是用于表达响应优先级,即没有抢占优先级。此时各个中断源之间就没有了中断嵌套。但是在我们的 STM32的中断优先级寄存器中,只是用了高4位用于表达优先级,但是在中断优先级分组时,被裁减掉的低4位还是可以参与分组,因此就出现了中断分组中的第4组:4位是抢占优先级,没有响应优先级的现象。
“抢占优先级”与“响应优先级”之间的区别是:如果两个(或多个)中断事件发生时,CUP首先会去处理抢占优先级高的中断源,如果此时又发生了一个 更高抢占优先级的事件时,则CPU会暂停当前程序,而 转向更高抢占优先级的中断处理程序,等该程序处理完毕后,返回原来被打断的中断处理程序中,继续执行未完成的任务,这样就形成了 中断嵌套。
Cortex_M3内核和STM32规定:【只能高抢占优先级中断事件,可以打断低抢占优先级中断事件,形成 中断嵌套】【两个(或多个)相同抢占优先级中断事件同时发生时, 无法形成中断嵌套 , 只能是逐个去响应处理。此时STM32会根据各个中断事件的“响应优先级”进行响应处理程序,这个时候“响应优先级”较低的中断事件将被 排队等待】【如果两个(或多个) 相同抢占优先级和 相同响应优先级的中断事件同时发生时,STM32将会首先响应中断入口所对应的中断向量地址较低的中断事件】
STM32的中断“挂起”与“解挂”。挂起:如果某个中断源发生中断请求时,系统正在处理相同抢占优先级的中断程序或者正在处理更高级别的中断程序时,此时这个后来的中断就不能被立即执行,就被处于挂起状态。被挂起的中断源,如果不被解挂,中断系统将会在合理的情况(符合该中断优先级的情况)下,去响应该中断。中断的挂起还可以通过中断设置寄存器结构体中的 ISPR[2]寄存器进行手动设置(该寄存器写0无效),可以将某一个中断源手动挂起。挂起后的中断,在合适的情况下,会被CPU响应。解挂:解挂和挂起刚好是相反的,如果一个中断源处于挂起状态时,可以操作中断设置寄存器结构体中的 ICPR[2]寄存器,进行手动解除挂起状态(该寄存器写0无效)。解除挂起后,该中断源将不被响应。
到此,总结完毕,由于个人能力有限,再加上初次接触STM32的芯片,可能文中有错误的地方。