学习或者了解过ARM的朋友应该都会知道NVIC这么个东西,这个东西也是ARM中非常重要的东西,它是ARM不可分离的部分,搭配着内核共同完成着对中断的响应。

1、那到底NVIC是个啥东西呢?

NVIC:简称嵌套向量中断控制器。它管理着包括内核、外部异常等的所有中断的响应和处理。

为了可以方便说明NVIC的原理和使用方法,本文以STM32F103作为参照说明NVIC的基本组成和使用原理。

STM32F103的内核使用的是Cortex-M3,是32bit的微处理器。它有专门的异常响应系统(NVIC)用于支持系统异常和外部异常中断。

Cortex-M3的异常响应系统支持16个系统异常、240个外部异常中断,总共256个异常响应,可以支持的异常数量可谓是很多了。

内核中对每种异常都有一个编号用于表示对应的中断,其中编号0-15表示系统异常,这部分属于内核的,不可更改,另外的16之后的是外部中断,除了少数不支持编程外,其他的都支持编程控制。

在 Cortex-M3 中有3个系统异常是固定优先级的,它们高于其他所有的异常,以确保它们能及时得到响应。

系统异常编号如下所示:

image.png

注意:上图的系统异常的编号,0是不存在的,不是异常。

外部异常的编号如下所示:

image.png

2、ARM Cortex-M 的优先级的定义

NVIC可以支持240个外部中断,也就是说最多有240个中断优先级。

虽然外部可以支持的中断异常可以高达240个,但是往往在设计芯片的时候都会做精简,不会完全用上,这个主要跟芯片设计时所考虑的应用场景有关吧。比如说有些芯片所支持的优先级数有可能是8级、16级、32级、48级等等的。

ARM公司对于中断优先级的管理提供了8个位给芯片厂商设置中断的优先级,芯片厂商可以根据需要自己裁剪,达到最终到底使用级优先级的目的。

但是,芯片厂商不一定都完全使用这8个位,可能只使用几个位。

STM32F103是ST公司开发的,中断优先级就只使用了这8个位中的高4位 ,所以最多可设置16个中断优先级。

这个是怎么理解呢?

假如我现在有一款芯片,它是用4个位表达优先级的,那么优先级配置寄存器的划分如下图:

image.png

[0:3]没有被使用到,你去读它们也是返回零,写它们就直接忽略写入的值。所以3个位的情况下,能够使用的 16 个优先级为:0x00(最高) ~ 0xE0。

注意:中断优先级使用数值来表示。数值越小,优先级越高。


3、抢占优先级 & 响应优先级

Cortex-M3 支持中断嵌套,可以让优先级高的中断抢占优先级低的中断,从而确保高优先级的中断异常能及时得到响应,而被打断了的低优先级中断异常先进入等待,等待高优先级的中断执行完毕之后再执行。

在NVIC中有一个寄存器:应用程序中断及复位控制寄存器(AIRCR),它里面有 一个位段名为“优先级组”,如下:

image.png

这个优先级组的作用是很大的,它将每个优先级可配置的异常中断都能进行分组配置,意思就是可以将一个中断进行设置,分为抢占优先级和响应优先级。

首先,我们要知道,每一个外部中断它都有一个相对应的优先级寄存器,这个寄存器也是8Bit的长度,同样是使用高四位表示中断的优先级的。然后在这四位中再继续进行划分,分出了用多少个Bit表示抢占优先级和多少个Bit表示响应优先级。

根据这4个Bit的划分,抢占优先级和响应优先级(子优先级、亚优先级)的组合可以有如下的结果:

image.png


抢占优先级和响应优先级怎么理解呢?

简单来说就是,当一个系统中有很多的外部中断时,假如某些中断同时发生,那到底应该先响应哪个呢?如果设置了抢占优先级和响应优先级,那就会先比较抢占优先级,谁高就先执行谁;如果抢占优先级一样,就比较响应优先级,谁高就先执行谁;如果没有设置抢占优先级,而响应优先级又是一样,那就按照系统默认的中断优先级,谁高先响应谁。


4、中断优先级分组的寄存器设置

前面介绍NVIC、中断优先级的一些基本特性,对NVIC应该有一定的认识了。那怎么去配置中断的优先级呢?

首先,通过应用程序中断及复位控制寄存器AIRCR 的第8位至第10位设置优先级的分组,寄存器如下图:

image.png

特别注意:想要直接使用位操作更改10:8位是无效的!!!

比如:

AIRCR |= 5<<8; //这么写是无效。

直接位操作对这个寄存器的内容更改是不生效的,如果想要修改这个寄存器需要同时操作31:16位才能生效。在寄存器中是有相关的说明的,如下:


image.png