嵌套向量中斷控制器(NVIC)詳解


引言

在平時的工作中,我們經常會遇到這樣的情況:有人來找你做一些事情,而且這些事情要比手頭的工作更重要。那現在就需要停下手中的工作,先去完成突然到來的這部分工作。這樣的情況也類似於圖論中的關鍵路徑中,突然在當前事件之前插入了一個新的事件,那我們不得不先去完成之前的那個任務,才能繼續完成后面的工作。

上述情況是非常常見的,那在STM32中,我們如果遇到了比當前任務更緊急的事情需要去處理,我們應該怎么辦呢?這個時候,我們需要通過中斷來完成這樣的任務。

在現實生活中,突然出現的任務一定有輕重緩急之分。如果同時出現許多的臨時任務,我們一定會首先評估他們誰更需要先被處理掉,然后再依次進行處理。在STM32中,我們也需要這樣的功能,多個中斷來臨的時候,我們需要首先判斷這個中斷緊不緊急,然后再考慮處理的先后順序。那我們是由什么來控制這樣的順序的呢?毫無疑問,這就是通過嵌套向量中斷控制器(NVIC)完成的。




NVIC簡介

CM3內核支持256個中斷,包括16個內核中斷和250個外部中斷,同時具有256級的可編程中斷設置。而STM32只使用了一部分。STM32擁有84個中斷,包括16個內核中斷和68個可屏蔽中斷(STM32F107系列才使用了68個可屏蔽中斷),還擁有16級可編程的中斷優先級。STM32F103系列只使用了60個可屏蔽中斷。

STM32中控制中斷優先級的寄存器組是IP[240]。是由240個8bit的寄存器組成的。而STM32F103只用了前六十個(0 ~ 59)。在STM32F103系列單片機中,這8bit也沒有全部使用,而是只使用了其高四位(4 ~ 7位)。下圖是中斷分組的分配情況。

優先級分組 搶占優先級 響應優先級 高四位描述
0 0級 0 ~ 15級 0bit用於搶占優先級
4bit用於響應優先級
1 0 ~ 1級 0 ~ 7級 1bit用於搶占優先級
3bit用於響應優先級
2 0 ~ 3級 0 ~ 3級 2bit用於搶占優先級
2bit用於響應優先級
3 0 ~ 7級 0 ~ 1級 3bit用於搶占優先級
1bit用於響應優先級
4 0 ~ 15級 0級 4bit用於搶占優先級
0bit用於響應優先級

響應優先級又稱為子優先級。
數值越小,優先級越高。

這里需要關注的是,搶占優先級的級別高於子優先級。高搶占優先級的中斷可以在低搶占優先級中斷執行的過程中被響應,反之則不行。這就是所謂的中斷嵌套。換句話說呢,就是高搶占優先級中斷可以搶占低搶占優先級中斷的執行。當多個中斷同時到來,而且他們的搶占優先級相同,則先進入子優先級更高的中斷。

但是,當搶占優先級相同的情況下,高子優先級中斷不能打斷低子優先級中斷,也就是不能實現中斷嵌套。這種情況下,高子優先級中斷必須先等待低子優先級中斷執行完成,在進行自己的中斷。




軟件部分

配置某個中斷優先級的步驟如下:

  • 配置中斷優先級分組
  • 配置某一中斷的優先級

配置中斷優先級分組

這一步可以通過函數 NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) 來完成。關於優先級分組的內容上文已經做過了講解。這里提供一個使用范例:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

配置某一個中斷的優先級

這一步我們需要用到一個函數 NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) 。里面的結構體的成員變量如下:

typedef struct
{
	uint8_t NVIC_IRQChannel;			//中斷名稱
	uint8_t NVIC_IRQChannelPreemptionPriority;	//搶占優先級
	uint8_t NVIC_IRQChannelSubPriority;		//響應優先級
	FunctionalState NVIC_IRQChannelCmd;		//中斷使能

}NVIC_InitTypeDef;

因此,配置某一中斷優先級的步驟如下:

  • 聲明上述結構體
  • 配置結構體成員變量的值
  • 利用 NVIC_Init 函數初始化

這里給出一個范例:

NVIC_InitTypeDef NVIC_InitStructure;	//聲明結構體

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                  //聲明中斷名稱
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;      //設置搶占優先級為2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;             //設置響應優先級為3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		          //使能中斷

NVIC_Init(&NVIC_InitStructure);			//對上述配置進行初始化

至此,我們就完成了對某一中斷優先級的配置,再根據不同的中斷配置不同的觸發條件等信息,就可以完成在特定條件下的中斷。這里不再展開敘述。


關於NVIC和中斷嵌套的更多的神奇理解可以參考下面這篇文章的后半部分:STM32 NVIC


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM