NVIC是什么
NVIC的英文全称是Nested Vectored Interrupt Controller翻译过来就是嵌套向量中断控制器,字面意思理解它就是一个控制器这个控制器是控制中断的为什么前面加个嵌套修饰符呢,是因为中断是抢占cpu的一种机制,嵌套的含义在于不同的中断是可以相互抢夺的。
An interrupt controller called NVIC (Nested Vectored Interrupt Controller)supporting up to 240 interrupt requests and from 8 to 256 interrupt priority levels(dependent on the actual device implementation);这个中断控制器支持多大240个中断请求8到256个中断优先级,当然这取决于实际的设备实现。
The number of interrupts supported by each Cortex-M3 or Cortex-M4 device isdetermined by the microcontroller vendors when the chips are designed.
每个 Cortex-M3 或 Cortex-M4 设备支持的中断数量由微控制器供应商在设计芯片时确定。
NVIC在什么地方
NVIC 是 Cortex -M 处理器的一部分。 它是可编程的,它的寄存器位于内存映射的系统控制空间 (SCS) 中(见图 4.18)。
NVIC 处理异常和中断配置、优先级和中断屏蔽。
NVIC的四个特点:
灵活的异常和中断管理( Flexible exception and interrupt management)
嵌套异常/中断支持( Nested exception/interrupt support)
向量异常/中断入口(Vectored exception/interrupt entry)
中断屏蔽(Interrupt masking)
每个中断(除了 NMI 之外)都可以启用或禁用,并且可以有自己的由软件设置或清除的挂起状态。 NVIC 可以处理各种类型的
中断源:
• 脉冲中断请求的长度至少为一个时钟周期。
当 NVIC 在其中断输入端接收到一个脉冲时,挂起状态被设置
并保持到中断得到服务。
• 电平触发中断请求中断源将请求保持为高电平
直到中断服务。
NVIC 输入端的信号电平为高电平有效。
然而,实际的外部微控制器上的中断输入可以有不同的设计和转换
通过片上逻辑到一个有效的高信号电平。(边沿控制器)
每个异常都有一个优先级。 某些异常(例如中断)具有可编程优先级,而其他一些异常(例如 NMI)具有固定优先级。
当异常发生时,NVIC 会将此异常的优先级与当前级别进行比较。 如果新的异常具有更高的优先级,则当前
正在运行的任务将被暂停。 一些寄存器将存储在堆栈中。并且处理器将开始执行新的异常处理程序。 这个过程称为“抢占”。 当更高优先级的异常处理程序完成,它以异常返回操作终止,处理器自动从堆栈中恢复寄存器并恢复之前的任务
之前运行。 这种机制允许嵌套异常服务而无需任何软件开销。
中断如何用
If a peripheral is to be used with interrupt operations, youwill need to program the interrupt controller on the Cortex-M3/M4 processor
(NVIC) to enable the interrupt and to configure the interrupt priority level.
如果外设要与中断操作一起使用,您需要在 Cortex-M3/M4 处理器上编程中断控制器(NVIC) 来启用中断并配置中断优先级。
也就是说如果使用一个中断比如最简单的外部中断我们需要启动中断并且给中断一个优先级。
In the Cortex-M processors, interrupt handlers can be written as normal C functions. Since interrupt prioritization and nesting of interrupts is handled by the NVIC and the exception entry is vectored, there is no need to use the software to check which interrupt needs to be served, or to handle nested interrupts explicitly. All you need to do is to assign a priority level to each interrupt and system exception.
在 Cortex-M 处理器中,中断处理程序可以编写为普通的 C 函数。 由于中断优先级和中断嵌套由 NVIC 处理,并且异常条目是向量化的,因此无需使用软件来检查需要服务哪个中断,或明确处理嵌套中断。 您需要做的就是为每个中断和系统异常分配一个优先级。
我们需要给中断一个优先级 并且实现一个中断处理的C语言函数就可以使用中断了。
在典型的 Cortex-M 微控制器中,NVIC 接收来自各种来源的中断请求,如下图所示
NMI:不可屏蔽中断 (Non-Maskable Interrupt)
IRQs:中断请求 (Interrupt Requests)
Systick timer:系统滴答定时器 (system tick timer)
System Exceptions:系统异常 (System Exceptions)
1.NMI 通常由看门狗定时器或者由掉电外设生成检测器(BOD)。
2.大多数 IRQ 是由定时器、I/O 端口和通信接口(例如 UART、I2C)等外设生成的。
3.其余的异常来自处理器内核。
4.也可以使用软件产生中断。
异常编号:
1-15
中断编号16-255
每个异常源都有一个异常编号。 异常编号 1 到 15 属于系统异常,异常编号 16 及以上属于中断。 Cortex-M3 和 Cortex-M4 处理器中的 NVIC 设计最多可支持 240 个中断输入。 但是,实际上设计中实现的中断输入的数量要少得多,通常在 16 到 100 的范围内。
操作中断的接口
void NVIC_EnableIRQ (IRQn_Type IRQn)
启用外部中断(Enable an external interrupt)
void NVIC_DisableIRQ (IRQn_Type IRQn)
禁用外部中断(Disable an external interrupt)
void NVIC_SetPriority (IRQn_Type IRQn,uint32_t priority)
设置中断的优先级(Set the priority of an interrupt)
void __enable_irq(void)
清除 PRIMASK 以启用中断(Clear PRIMASK to enable interrupts)
void __disable_irq(void)
设置 PRIMASK 以禁用所有中断(Set PRIMASK to disable all interrupts)
void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
设置优先分组配置(Set priority grouping configuration)
配置中断的一般步骤
设置所需中断的优先级(此步骤可选)
在触发中断的外设中启用中断生成控制
在 NVIC 中启用中断
编写对应的中断服务函数ISR
在 Cortex -M 处理器(ARMv6-M 和 ARMv7-M)中,是否以及何时处理器可以接受异常并执行其处理程序取决于异常的优先级和处理器的当前优先级。
优先级中较小的数字具有更高优先级
优先级中的较大数字具有较低优先级,嵌套的异常或者中断可以抢占。
一些异常(重置、NMI 和 HardFault)具有固定优先级。它们的优先级用负数表示
表明它们比其他异常具有更高的优先级。
可用可编程优先级的实际数量由硅芯片设计者决定。这里特指芯片厂商。
这是因为拥有大量优先级会增加NVIC 可以增加功耗并降低设计速度。在
大多数情况下,应用程序只需要少量的可编程优先级。因此,硅芯片设计人员需要基于以下因素定制他们的处理器设计目标应用程序中的优先级数量。这种水平的降低是通过删除优先级配置寄存器的最低有效位 (LSB) 部分来实现。
中断优先级由优先级寄存器控制,宽度为3位到 8 位。
可能的优先级为 0x00、0x20、0x40、0x60、0x80、0xA0、0xC0、0xE0
类似地,如果在设计中实现了 4 位优先级,这允许 16 个级别的可编程优先级
32中就是使用4个bit来划分优先级的。
库函数的写法
#define NVIC_PriorityGroup_0 ((uint32_t)0x7) /*!< 0 bits for pre-emption priority 4 bits for subpriority */
#define NVIC_PriorityGroup_1 ((uint32_t)0x6) /*!< 1 bits for pre-emption priority 3 bits for subpriority */
#define NVIC_PriorityGroup_2 ((uint32_t)0x5) /*!< 2 bits for pre-emption priority 2 bits for subpriority */
#define NVIC_PriorityGroup_3 ((uint32_t)0x4) /*!< 3 bits for pre-emption priority 1 bits for subpriority */
#define NVIC_PriorityGroup_4 ((uint32_t)0x3) /*!< 4 bits for pre-emption priority 0 bits for subpriority */
中断分组表
NVIC_SetPriorityGrouping(2);
设置分组2组
Group = NVIC_GetPriorityGrouping();
得到分组
priority1 = NVIC_EncodePriority(Group,0,1);编码优先级
NVIC_SetPriority(EXTI0_IRQn,priority1);设置优先级
NVIC_EnableIRQ(EXTI0_IRQn);中断打开 能够响应中断
中断服务函数
void EXTI0_IRQHandler(void)
{
EXTI->PR |= (0x1<<0); //清除EXTI0中断标志位
LED1_Tog();
printf("按键1上升沿中断发生!\r\n");
}
void EXTI2_IRQHandler(void)
{
EXTI->PR |= (0x1<<2);
LED2_Tog();
printf("按键2下降沿中断发生!\r\n");
}
void EXTI3_IRQHandler(void) //PE3
{
EXTI->PR |= (0x1<<3);
LED3_Tog();
printf("按键3下降沿中断发生!\r\n");
}
void EXTI4_IRQHandler(void) //PE3
{
EXTI->PR |= (0x1<<4);
LED4_Tog();
printf("按键4下降沿中断发生!\r\n");
}
Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window WatchDog 看门狗中断函数名字
DCD PVD_IRQHandler ; PVD through EXTI Line detection
DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
DCD FLASH_IRQHandler ; FLASH
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line0
DCD EXTI1_IRQHandler ; EXTI Line1
DCD EXTI2_IRQHandler ; EXTI Line2
DCD EXTI3_IRQHandler ; EXTI Line3
DCD EXTI4_IRQHandler ; EXTI Line4
DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0
DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1
DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2
DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3
DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4
DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5
DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6
DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s
DCD CAN1_TX_IRQHandler ; CAN1 TX
DCD CAN1_RX0_IRQHandler ; CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; External Line[9:5]s
DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9
DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10
DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; External Line[15:10]s
DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line
DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12
DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13
DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14
DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare
DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
DCD FSMC_IRQHandler ; FSMC
DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5
DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors
DCD TIM7_IRQHandler ; TIM7
DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0
DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1
DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2
DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3
DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4
DCD ETH_IRQHandler ; Ethernet
DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line
DCD CAN2_TX_IRQHandler ; CAN2 TX
DCD CAN2_RX0_IRQHandler ; CAN2 RX0
DCD CAN2_RX1_IRQHandler ; CAN2 RX1
DCD CAN2_SCE_IRQHandler ; CAN2 SCE
DCD OTG_FS_IRQHandler ; USB OTG FS
DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5
DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6
DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7
DCD USART6_IRQHandler ; USART6
DCD I2C3_EV_IRQHandler ; I2C3 event
DCD I2C3_ER_IRQHandler ; I2C3 error
DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out
DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In
DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI
DCD OTG_HS_IRQHandler ; USB OTG HS
DCD DCMI_IRQHandler ; DCMI
DCD CRYP_IRQHandler ; CRYP crypto
DCD HASH_RNG_IRQHandler ; Hash and Rng
DCD FPU_IRQHandler ; FPU