中斷管理控制器NVIC與stm32中斷使用
什么是NVIC?即嵌套向量中斷控制器(Nested Vectored Interrupt Controller)。它是屬于Cortex內(nèi)核的器件,是非常強(qiáng)大與方便的嵌套向量中斷控制器,不可屏蔽中斷 (NMI)和外部中斷都由它來處理,而SYSTICK不是由NVIC來控制的。
NVIC特性
嵌套向量中斷控制器 NVIC 包含以下特性:
● STM32F405xx/07xx 和 STM32F415xx/17xx 具有 82 個(gè)可屏蔽中斷通道, STM32F42xxx
和 STM32F43xxx 具有多達(dá) 86 個(gè)可屏蔽中斷通道(不包括 Cortex?-M4F 的 16 根中
斷線)
● 16 個(gè)可編程優(yōu)先級(jí)(stm32F4只使用了 4 位中斷優(yōu)先級(jí))
● 低延遲異常和中斷處理
● 電源管理控制
● 系統(tǒng)控制寄存器的實(shí)現(xiàn)
嵌套向量中斷控制器 (NVIC) 和處理器內(nèi)核接口緊密配合,可以實(shí)現(xiàn)低延遲的中斷處理和晚
到中斷的高效處理。
包括內(nèi)核異常在內(nèi)的所有中斷均通過 NVIC 進(jìn)行管理。更多關(guān)于異常和 NVIC 編程的說明,
請(qǐng)參考《 ARM Cortex?-M4F 技術(shù)參考手冊(cè)》中的第5 章:異常和第8 章:嵌套向量中斷控
制器。
通過閱讀《STM32xxx參考手冊(cè)》中“中斷與事件”一章我們可以知道ST公司生產(chǎn)的stm32芯片對(duì)cotex內(nèi)核的嵌套向量中斷控制器NVIC 的使用進(jìn)行了一些小的改動(dòng),
改動(dòng)一:減少了用于設(shè)置優(yōu)先級(jí)的比特位。stm32只用了4個(gè)比特位來表示中斷的優(yōu)先級(jí)
1.中斷優(yōu)先級(jí)分組
Cortex-M3中有兩個(gè)優(yōu)先級(jí)的概念--搶占式優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí),有人把響應(yīng)優(yōu)先級(jí)稱作'亞優(yōu)先級(jí)'或'副優(yōu)先級(jí)',每個(gè)中斷源都需要被指定
這兩種優(yōu)先級(jí)。
具有高搶占式優(yōu)先級(jí)的中斷可以在具有低搶占式優(yōu)先級(jí)的中斷處理過程中被響應(yīng),即中斷嵌套,或者說高搶占式優(yōu)先級(jí)的中斷可以嵌套在
低搶占式優(yōu)先級(jí)的中斷中。
當(dāng)兩個(gè)中斷源的搶占式優(yōu)先級(jí)相同時(shí),這兩個(gè)中斷將沒有嵌套關(guān)系,當(dāng)一個(gè)中斷到來后,如果正在處理另一個(gè)中斷,這個(gè)后到來的中斷就要等到
前一個(gè)中斷處理完之后才能被處理。如果這兩個(gè)中斷同時(shí)到達(dá),則中斷控制器根據(jù)他們的響應(yīng)優(yōu)先級(jí)高低來決定先處理哪一個(gè);如果他們的搶占
優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)都相等,則根據(jù)他們?cè)谥袛啾碇械呐盼豁樞驔Q定先處理哪一個(gè)。
Cortex內(nèi)核具有強(qiáng)大的異常響應(yīng)系統(tǒng),它把能夠打斷當(dāng)前代碼執(zhí)行流程的事件分為異常(exception)和中斷(interrupt),并把它們用一個(gè)表
管理起來,編號(hào)為0~15的稱為內(nèi)核異常,而16以上的則稱為外部中斷這個(gè)表就稱為中斷向量表。
正是因?yàn)槊總€(gè)中斷源都需要被指定這兩種優(yōu)先級(jí),就需要有相應(yīng)的寄存器位記錄每個(gè)中斷的優(yōu)先級(jí);在Cortex-M3中定義了8個(gè)比特位用于設(shè)置
中斷源的優(yōu)先級(jí),這8個(gè)比特位可以有8種分配方式,如下:
1. 所有8位用于指定響應(yīng)優(yōu)先級(jí)
2. 最高1位用于指定搶占式優(yōu)先級(jí),最低7位用于指定響應(yīng)優(yōu)先級(jí)
3. 最高2位用于指定搶占式優(yōu)先級(jí),最低6位用于指定響應(yīng)優(yōu)先級(jí)
4. 最高3位用于指定搶占式優(yōu)先級(jí),最低5位用于指定響應(yīng)優(yōu)先級(jí)
5. 最高4位用于指定搶占式優(yōu)先級(jí),最低4位用于指定響應(yīng)優(yōu)先級(jí)
6. 最高5位用于指定搶占式優(yōu)先級(jí),最低3位用于指定響應(yīng)優(yōu)先級(jí)
7. 最高6位用于指定搶占式優(yōu)先級(jí),最低2位用于指定響應(yīng)優(yōu)先級(jí)
8. 最高7位用于指定搶占式優(yōu)先級(jí),最低1位用于指定響應(yīng)優(yōu)先級(jí)
以上便是優(yōu)先級(jí)分組的概念,但是Cortex-M3允許具有較少中斷源時(shí)使用較少的寄存器位指定中斷源的優(yōu)先級(jí)。
而 STM32對(duì)這個(gè)表重新進(jìn)行了編排,把編號(hào)從-3至6的中斷向量定義為系統(tǒng)異常,編號(hào)為負(fù)的內(nèi)核異常不能被設(shè)置優(yōu)先級(jí),如復(fù)位(Reset)、
不可屏蔽中斷 (NMI)、硬錯(cuò)誤(Hardfault)。從編號(hào) 7開始的為外部中斷,這些中斷的優(yōu)先級(jí)都是可以用戶更改的。詳細(xì)的 STM32中斷向量號(hào)
可以在startup_stm32f10x_XX.s中查找。
因此STM32把指定中斷優(yōu)先級(jí)的寄存器位減少到4位,這4個(gè)寄存器位的分組方式如下:
第0組:所有4位用于指定響應(yīng)優(yōu)先級(jí)(16種)
第1組:最高1位用于指定搶占式優(yōu)先級(jí),最低3位用于指定響應(yīng)優(yōu)先級(jí)(8種)
第2組:最高2位用于指定搶占式優(yōu)先級(jí),最低2位用于指定響應(yīng)優(yōu)先級(jí)(4種)
第3組:最高3位用于指定搶占式優(yōu)先級(jí),最低1位用于指定響應(yīng)優(yōu)先級(jí)(2種)
第4組:所有4位用于指定搶占式優(yōu)先級(jí)
改動(dòng)二:stm32增加了外部中斷/事件控制器(EXTI)
EXTI主要特性
EXTI控制器的主要特性如下:
●每個(gè)中斷/事件線上都具有獨(dú)立的觸發(fā)和屏蔽
●每個(gè)中斷線都具有專用的狀態(tài)位
●支持多達(dá) 23 個(gè)軟件事件/中斷請(qǐng)求
●檢測(cè)脈沖寬度低于 APB2 時(shí)鐘寬度的外部信號(hào)。有關(guān)此參數(shù)的詳細(xì)信息,請(qǐng)參見
STM32F4xx數(shù)據(jù)手冊(cè)的電氣特性部分。
外部中斷/事件線映射
多達(dá) 140個(gè) GPIO(STM32F405xx/07xx和 STM32F415xx/17xx)通過以下方式連接到16 個(gè) 外部中斷/事件線:
另外七根EXTI 線連接方式如下:
● EXTI 線16 連接到 PVD輸出
● EXTI 線17 連接到 RTC鬧鐘事件
● EXTI 線18 連接到 USB OTG FS喚醒事件
● EXTI 線19 連接到以太網(wǎng)喚醒事件
● EXTI 線20 連接到 USB OTG HS(在FS 中配置)喚醒事件
● EXTI 線21 連接到 RTC入侵和時(shí)間戳事件
● EXTI線 22 連接到 RTC 喚醒事件
那么NVIC能夠管理高達(dá)86個(gè)可屏蔽中斷,那么都有哪些中斷通道呢?我們可以到"stm32f4xx.h"這個(gè)文件中查看,這個(gè)頭文件中定義了一個(gè)所有通道的枚舉結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體包含了所有NVIC能夠管理的的中斷通道。如下所示。前面八個(gè)是不可屏蔽中斷,后面的是可屏蔽中斷,紅色字體部分是EXTI類型中斷通道,由NVIC 與EXIT寄存器共同控制。
/**
* @brief Configuration of the Cortex-M4 Processor and Core Peripherals
*/
#define __CM4_REV 0x0001 /*!< Core revision r0p1 */
#define __MPU_PRESENT 1 /*!< STM32F4XX provides an MPU */
#define __NVIC_PRIO_BITS 4 /*!< STM32F4XX uses 4 Bits for the Priority Levels */
#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
#define __FPU_PRESENT 1 /*!< FPU present */
/**
* @brief STM32F4XX Interrupt Number Definition, according to the selected device
* in @ref Library_configuration_section
*/
typedef enum IRQn
{
/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers **********************************************************************/
WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */
RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */
FLASH_IRQn = 4, /*!< FLASH global Interrupt */
RCC_IRQn = 5, /*!< RCC global Interrupt */
EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */
DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */
DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */
DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */
DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */
DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */
DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */
ADC_IRQn = 18, /*!< ADC1, ADC2 and ADC3 global Interrupts */
#if defined (STM32F40_41xxx)
CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */
CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */
CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */
CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */
EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break interrupt and TIM9 global interrupt */
TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global interrupt */
TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */
TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */
TIM2_IRQn = 28, /*!< TIM2 global Interrupt */
TIM3_IRQn = 29, /*!< TIM3 global Interrupt */
TIM4_IRQn = 30, /*!< TIM4 global Interrupt */
I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */
I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */
I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */
I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */
SPI1_IRQn = 35, /*!< SPI1 global Interrupt */
SPI2_IRQn = 36, /*!< SPI2 global Interrupt */
USART1_IRQn = 37, /*!< USART1 global Interrupt */
USART2_IRQn = 38, /*!< USART2 global Interrupt */
USART3_IRQn = 39, /*!< USART3 global Interrupt */
EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */
OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */
TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */
TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */
TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */
DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */
FSMC_IRQn = 48, /*!< FSMC global Interrupt */
SDIO_IRQn = 49, /*!< SDIO global Interrupt */
TIM5_IRQn = 50, /*!< TIM5 global Interrupt */
SPI3_IRQn = 51, /*!< SPI3 global Interrupt */
UART4_IRQn = 52, /*!< UART4 global Interrupt */
UART5_IRQn = 53, /*!< UART5 global Interrupt */
TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */
TIM7_IRQn = 55, /*!< TIM7 global interrupt */
DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */
DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */
DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */
DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */
DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */
ETH_IRQn = 61, /*!< Ethernet global Interrupt */
ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */
CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */
CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */
CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */
CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */
OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */
DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */
DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */
DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */
USART6_IRQn = 71, /*!< USART6 global interrupt */
I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */
I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */
OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */
OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */
OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */
OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */
DCMI_IRQn = 78, /*!< DCMI global interrupt */
CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */
HASH_RNG_IRQn = 80, /*!< Hash and Rng global interrupt */
FPU_IRQn = 81 /*!< FPU global interrupt */
#endif /* STM32F40_41xxx */
} IRQn_Type;