STM32嵌套中断向量控制器(NVIC)详解

一、嵌套终端向量控制器NVIC

1.1NVIC介绍

NVIC(Nest Vector Interrupt Controller),嵌套中断向量控制器,作用是管理中断嵌套 先级。 核心任务是管理中断优

管理中断嵌套:我们在处理某个中断的过程中还没处理完这个中断,又来了一个中断,是否可以打断这个中断,不能就存在中断嵌套

特点:

68个可屏蔽中断通道(不包含16个Cortex-M3的中断线)

16个可编程的优先等级(使用了4位中断优先级)

低延迟的异常和中断处理

电源管理控制

系统控制寄存器的实现

12.优先级

抢占优先级和响应优先级

拥有较高抢占优先级的中断可以打断抢占优先级较低的中断 

若两个抢占优先级的中断同时挂起,则优先执行响应优先级较高的中断

若两个挂起的中断优先级都一致,则优先执行位于中断向量表中位置较高的中断

响应优先级不会造成中断嵌套,也就是说中断嵌套是由抢占优先级决定的(抢占优先级数字越小,优先级越高)

8种分配方式:

所有8位全部用于指定响应优先级

第7位用于指定抢占式优先级,0-6位用于指定响应优先级

6-7位用于指定抢占式优先级,0-5位用于指定响应优先级

5-7位用于指定抢占式优先级,0-4位用于指定响应优先级

4-7位用于指定抢占式优先级,0-3位用于指定响应优先级

3-7位用于指定抢占式优先级,0-2位用于指定响应优先级

2-7位用于指定抢占式优先级,0-1位用于指定响应优先级

1-8位田干指定给上式优牛级 0位田干指定响应伏牛级

Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32中断优先级的寄存器位只 用到AIRCR高四位,共有以下几种组合:

第0组:所有4位用于指定响应优先级

第1组:第7位用于指定抢占式优先级, 4-6位用于指定响应优先级 '

第2组:第6-7位用于指定抢占式优先级, 4-5位用于指定响应优先级

第3组:第5-7位用于指定抢占式优先级,第4位用于指定响应优先级 第4组:

所有4位用于指定抢占式优先级

使用固件库函数配置中断优先级得方法(misc.c中定义):

1
/**

2
*
@brief Configures the priority grouping
:
pre

emption priority and

3
*
subpriority
.

4
*
@param NVIC_PriorityGroup
:
specifies the priority grouping bits
5
*
length
.

6
*
This parameter can be one
of
the following values
:

7
*
@arg NVIC_PriorityGroup_0
:
0
bits
for
pre

emption priority

8
*
4
bits
for
subpriority

9
*
@arg NVIC_PriorityGroup_1
:
1
bits
for
pre

emption priority

10
*
3
bits
for
subpriority

11
*
@arg NVIC_PriorityGroup_2
:
2
bits
for
pre

emption priority

12
*
2
bits
for
subpriority

13
*
@arg NVIC_PriorityGroup_3
:
3
bits
for
pre

emption priority

14
*
1
bits
for
subpriority

15
*
@arg NVIC_PriorityGroup_4
:
4
bits
for
pre

emption priority

16
*
0
bits
for
subpriority

17
*
@retval None

18
*/

19
void
NVIC_PriorityGroupConfig
(
uint32_t NVIC_PriorityGroup
)

优先级组确定后,可以根据优先级组来配置对应IRQ的抢占优先级和响应优先级

1.3NVIC初始化

每个外部中断都由NVIC统一进行管理,所以NVIC包含了中断功能的使能和失能,优先级的

配置等功能。

固件库中关于NVIC的初始化函数

1
/**

2
*
@brief Initializes the
NVIC
peripheral according to the specified

3
*
parameters
in
the NVIC_InitStruct
.

4
*
@param NVIC_InitStruct
:
pointer to a NVIC_InitTypeDef structure

5
*
that contains

6
*
the configuration information
for
the specified
NVIC

7
*
peripheral
.

8
*
@retval None

9
*/

10
void
NVIC_Init
(
NVIC_InitTypeDef
*
NVIC_InitStruct
)

11

形参变量说明:

1
typedef struct

2
{

3
uint8_t NVIC_IRQChannel
;

4
uint8_t NVIC_IRQChannelPreemptionPriority
;
5
uint8_t NVIC_IRQChannelSubPriority
;

6
FunctionalState NVIC_IRQChannelCmd
;

7
}

1.NVIC_IRQChannel:外部中断通道(在stm32f10x.h中定义)

1
typedef
enum
IRQn

2
{

3
NonMaskableInt_IRQn
= ‐
14
,
/*!< 2 Non Maskable Interrupt*/

4
MemoryManagement_IRQn
= ‐
12
,
/*!< 4 Cortex‐M3 Memory Management Interrup

t*/

5
BusFault_IRQn
= ‐
11
,
/*!< 5 Cortex‐M3 Bus Fault Interrupt*/

6
UsageFault_IRQn
= ‐
10
,
/*!< 6 Cortex‐M3 Usage Fault Interrupt*/

7
SVCall_IRQn
= ‐
5
,
/*!< 11 Cortex‐M3 SV Call Interrupt*/

8
DebugMonitor_IRQn
= ‐
4
,
/*!< 12 Cortex‐M3 Debug Monitor Interrupt*/

9
PendSV_IRQn
= ‐
2
,
/*!< 14 Cortex‐M3 Pend SV Interrupt*/

10
SysTick_IRQn
= ‐
1
,
/*!< 15 Cortex‐M3 System Tick Interrupt*/

11

12
WWDG_IRQn
=
0
,
/*!< Window WatchDog Interrupt*/

13
PVD_IRQn
=
1
,
/*!< PVD through EXTI Line detection Interrupt*/

14
TAMPER_IRQn
=
2
,
/*!< Tamper Interrupt*/

15
RTC_IRQn
=
3
,
/*!< RTC global Interrupt*/

16
FLASH_IRQn
=
4
,
/*!< FLASH global Interrupt*/

17
RCC_IRQn
=
5
,
/*!< RCC global Interrupt*/

18
EXTI0_IRQn
=
6
,
/*!< EXTI Line0 Interrupt*/

19
EXTI1_IRQn
=
7
,
/*!< EXTI Line1 Interrupt*/

20
EXTI2_IRQn
=
8
,
/*!< EXTI Line2 Interrupt*/

21
EXTI3_IRQn
=
9
,
/*!< EXTI Line3 Interrupt*/

22
EXTI4_IRQn
=
10
,
/*!< EXTI Line4 Interrupt*/

23
DMA1_Channel1_IRQn
=
11
,
/*!< DMA1 Channel 1 global Interrupt*/

24
DMA1_Channel2_IRQn
=
12
,
/*!< DMA1 Channel 2 global Interrupt*/

25
DMA1_Channel3_IRQn
=
13
,
/*!< DMA1 Channel 3 global Interrupt*/

26
DMA1_Channel4_IRQn
=
14
,
/*!< DMA1 Channel 4 global Interrupt*/

27
DMA1_Channel5_IRQn
=
15
,
/*!< DMA1 Channel 5 global Interrupt*/

28
DMA1_Channel6_IRQn
=
16
,
/*!< DMA1 Channel 6 global Interrupt*/

29
DMA1_Channel7_IRQn
=
17
,
/*!< DMA1 Channel 7 global Interrupt*/

30

31
}

2.NVIC_IRQChannelPreemptionPriority:抢占优先级(最大取值15)

3.NVIC_IRQChannelSubPriority:响应优先级(最大取值15)
4.NVIC_IRQChannelCmd:(ENABLE/DISABLE)

使能/失能对应的中断通道

GPIO的外部中断触发方式为高电平触发上升沿触发,上升沿触发一个中断交由EXTI中断控制器进行管理,再往上给到nvic,你想由cpu响应中断,首先由nvic管理,nvic给没个中断一个管理开关,没有nvic的管理就没有cpu对于中断的响应

1.4中断的具体行为

当CM3开始响应一个中断时,会做如下动作:

入栈: 把8个寄存器的值压入栈

取向量:从向量表中找出对应的服务程序入口地址

选择堆栈指针MSP(主堆栈)/PSP(进程堆栈),更新堆栈指针SP,更新链接寄存器

LR,更新程序计数器PC

1.4.1、入栈

响应异常的第一个动作,就是自动保存现场,依次把xPSR、PC, LR, R12以及R3-R0由

件寄存器自动压入适当的堆栈中。

1.4.2、取向量

数据总线(系统总线)在执行入栈的时候,指令总线从向量表中找出正确的异常向量,

然后在服务程序的入口处预取指。

(由此可以看到各自都有专用总线的好处:入栈与取指这两个工作能同时进行)

1.4.3、更新寄存器

在入栈和取向量操作完成之后,执行服务例程之前,还要更新一系列的寄存器.

SP:在入栈后会把堆栈指针更新到新的位置。在执行服务例程时,将由MSP负

责对堆栈的

访问。

PSR:更新IPSR位段的值为新响应的异常编号。

PC:在取向量完成后,PC将指向服务例程的入口地址,

LR:在出入ISR(Interrupt Service Routines)中断服务程序的时候,LR的值

将得到更新

(在异常进入时由系统计算并赋给LR,并在异常返回时使用它

1.5、异常/中断返回

当异常服务例程执行完毕后,需要恢复先前的系统状态,才能使被中断的程序得以继续执

行。

异常/中断处理完成后,执行如下处理:

出栈:恢复先前压入栈中的寄存器,堆栈指针的值也改回先前的值
更新NVIC寄存器:伴随着异常的返回,它的活动位也被硬件清除

二、外部中断

对于互联型产品,外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成,

对于其它

产品,则有19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型

和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。

挂起寄存器保持着状态线的中断请求

EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件:

中断:

信号从输入线输入,经过边沿检测电路来控制信号触发(根据上升沿下降沿触发选择寄

存器的设置来控制),如果检测到有效信号后,将该有效信号输出到或门电路,由红色箭头

方向经过请求挂起寄存器和中断屏蔽寄存器,到达与门电路,条件满足送至NVIC

事件:

信号从输入线输入,经过边沿检测电路来控制信号触发(根据上升沿下降沿触发选择寄存器

的设置来控制),如果检测到有效信号后,将该有效信号输出到或门电路,由蓝色箭头方向

经过与门电路,送至买脉冲发生器,产生脉冲。这个脉冲信号可以给其他外设电路使用,比

如定时器 TIM、模拟数字转换器 ADC等等,这样的脉冲信号一般用来触发 TIM 或者 ADC

开始转换。

事件和中断的区别:
产生中断线路目的是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这

样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级

别的信号传输,属于硬件级的。

2.1、主要特性

每个中断/事件都有独立的触发和屏蔽

每个中断线都有专用的状态位

支持多达20个软件的中断/事件请求

检测脉冲宽度低于APB2时钟宽度的外部信号

2.2、外部中断/事件线路映像

通用I/O端口以下图的方式连接到16个外部中断/事件线上

另外四个EXTI线的连接方式如下:

● EXTI线16连接到PVD输出

● EXTI线17连接到RTC闹钟事件

● EXTI线18连接到USB唤醒事件

● EXTI线19连接到以太网唤醒事件(只适用于互联型产品)

2.1、主要特性

每个中断/事件都有独立的触发和屏蔽

每个中断线都有专用的状态位

支持多达20个软件的中断/事件请求

检测脉冲宽度低于APB2时钟宽度的外部信号

2.2、外部中断/事件线路映像

通用I/O端口以下图的方式连接到16个外部中断/事件线上

另外四个EXTI线的连接方式如下:

● EXTI线16连接到PVD输出

● EXTI线17连接到RTC闹钟事件

● EXTI线18连接到USB唤醒事件

● EXTI线19连接到以太网唤醒事件(只适用于互联型产品

2.3、EXTI相关数据结构与函数说明
2.3.1、初始化函数

1
void
EXTI_Init
(
EXTI_InitTypeDef
*
EXTI_InitStruct
)

参数:EXTI_InitStruct

1
typedef struct

2
{

3
uint32_t EXTI_Line
;
//
中断线

4
EXTIMode_TypeDef EXTI_Mode
;
//
中断模式

5
EXTITrigger_TypeDef EXTI_Trigger
;
//
中断触发方式

6
FunctionalState EXTI_LineCmd
;
//
中断功能使能

7
}

@EXTI_Line

1
#define
EXTI_Line0
((
uint32_t
)
0x00001
)
/*!< External interrupt line 0 */

2
#define
EXTI_Line1
((
uint32_t
)
0x00002
)
/*!< External interrupt line 1 */

3
#define
EXTI_Line2
((
uint32_t
)
0x00004
)
/*!< External interrupt line 2 */

4
#define
EXTI_Line3
((
uint32_t
)
0x00008
)
/*!< External interrupt line 3 */

5
#define
EXTI_Line4
((
uint32_t
)
0x00010
)
/*!< External interrupt line 4 */

6
#define
EXTI_Line5
((
uint32_t
)
0x00020
)
/*!< External interrupt line 5 */

7
#define
EXTI_Line6
((
uint32_t
)
0x00040
)
/*!< External interrupt line 6 */

8
#define
EXTI_Line7
((
uint32_t
)
0x00080
)
/*!< External interrupt line 7 */

9
#define
EXTI_Line8
((
uint32_t
)
0x00100
)
/*!< External interrupt line 8 */

10
#define
EXTI_Line9
((
uint32_t
)
0x00200
)
/*!< External interrupt line 9 */

11
#define
EXTI_Line10
((
uint32_t
)
0x00400
)
/*!< External interrupt line 10

*/

12
#define
EXTI_Line11
((
uint32_t
)
0x00800
)
/*!< External interrupt line 11

*/

13
#define
EXTI_Line12
((
uint32_t
)
0x01000
)
/*!< External interrupt line 12

*/

14
#define
EXTI_Line13
((
uint32_t
)
0x02000
)
/*!< External interrupt line 13

*/

15
#define
EXTI_Line14
((
uint32_t
)
0x04000
)
/*!< External interrupt line 14

*/

16
#define
EXTI_Line15
((
uint32_t
)
0x08000
)
/*!< External interrupt line 15

*/

17
#define
EXTI_Line16
((
uint32_t
)
0x10000
)
/*!< External interrupt line 16

Connected to the PVD Output */

18
#define
EXTI_Line17
((
uint32_t
)
0x20000
)
/*!< External interrupt line 17

Connected to the RTC Alarm event */

19
#define
EXTI_Line18
((
uint32_t
)
0x40000
)
/*!< External interrupt line 18

Connected to the USB Device/USB OTG FS
20
Wakeup
from
suspend event
*/

21
#define
EXTI_Line19
((
uint32_t
)
0x80000
)
/*!< External interrupt line 19

Connected to the Ethernet Wakeup event */

@EXTI_Mode

1
typedef
enum

2
{

3
EXTI_Mode_Interrupt
=
0x00
,
//
中断模式

4
EXTI_Mode_Event
=
0x04
//
事件模式

5
}
EXTIMode_TypeDef
;

@EXTI_Trigger

1
typedef
enum

2
{

3
EXTI_Trigger_Rising
=
0x08
,
//
上升沿触发

4
EXTI_Trigger_Falling
=
0x0C
,
//
下降沿触发

5
EXTI_Trigger_Rising_Falling
=
0x10
//
双边沿触发

6
}
EXTITrigger_TypeDef
;

@EXTI_LineCmd

1
ENABLE

2
DISABLE

2.3.2、获取中断状态

1
//
参数:中断线

2
ITStatus
EXTI_GetITStatus
(
uint32_t EXTI_Line
);

2.3.3、清空中断标志位

1
//
参数:中断线

2
void
EXTI_ClearITPendingBit
(
uint32_t EXTI_Line
);

2.3.4、软件产生中断

1
void
EXTI_GenerateSWInterrupt
(
uint32_t EXTI_Line
)

2.4、中断回调函数

在startup_stm32f10x_xx.s中的中断向量表里:

1
DCD
EXTI0_IRQHandler
;
EXTI
Line
0

2
DCD
EXTI1_IRQHandler
;
EXTI
Line
1

3
DCD
EXTI2_IRQHandler
;
EXTI
Line
2

4
DCD
EXTI3_IRQHandler
;
EXTI
Line
3

5
DCD
EXTI4_IRQHandler
;
EXTI
Line
4
6
DCD
EXTI9_5_IRQHandler
;
EXTI
Line
9..5

7
DCD
EXTI15_10_IRQHandler
;
EXTI
Line
15..10作者:ycjunhua

物联沃分享整理
物联沃-IOTWORD物联网 » STM32嵌套中断向量控制器(NVIC)详解

发表回复