1. 程式人生 > >stm32中斷優先順序設定學習

stm32中斷優先順序設定學習

如果你需要在STM32上移植RTOS,那麼首先必須深入理解它的中斷系統。什麼是NVIC?即巢狀向量中斷控制器(Nested Vectored Interrupt Controller)。STM32的中有一個強大而方便的NVIC,它是屬於Cortex核心的器件,不可遮蔽中斷 (NMI)和外部中斷都由它來處理,而SYSTICK不是由 NVIC來控制的。
特性:

● 60個可遮蔽中斷通道(不包含16個Cortex™-M3的中斷線);

● 16個可程式設計的優先等級(使用了4位中斷優先順序);

● 低延遲的異常和中斷處理;

● 電源管理控制;

● 系統控制暫存器的實現;

1.中斷優先順序分組
STM32(Cortex-M3)中有兩個優先順序的概念–搶佔式優先順序和響應優先順序,有人把響應優先順序稱作’亞優先順序’或’副優先順序’,每個中斷源都需要被指定這兩種優先順序。
具有高搶佔式優先順序的中斷可以在具有低搶佔式優先順序的中斷處理過程中被響應,即中斷巢狀,或者說高搶佔式優先順序的中斷可以巢狀在低搶佔式優先順序的中斷中。
當兩個中斷源的搶佔式優先順序相同時,這兩個中斷將沒有巢狀關係,當一箇中斷到來後,如果正在處理另一箇中斷,這個後到來的中斷就要等到前一箇中斷處理完之後才能被處理。如果這兩個中斷同時到達,則中斷控制器根據他們的響應優先順序高低來決定先處理哪一個;如果他們的搶佔式優先順序和響應優先順序都相等,則根據他們在中斷表中的排位順序決定先處理哪一個。
Cortex核心具有強大的異常響應系統,它把能夠打斷當前程式碼執行流程的事件分為異常(exception)和中斷(interrupt),並把它們用一個表管理起來,編號為0~15的稱為核心異常,而16以上的則稱為外部中斷,這個表就稱為中斷向量表。
正是因為每個中斷源都需要被指定這兩種優先順序,就需要有相應的暫存器位記錄每個中斷的優先順序;在Cortex-M3中定義了8個位元位用於設定中斷源的優先順序,這8個位元位可以有8種分配方式,如下:

  1. 所有8位用於指定響應優先順序

  2. 最高1位用於指定搶佔式優先順序,最低7位用於指定響應優先順序

  3. 最高2位用於指定搶佔式優先順序,最低6位用於指定響應優先順序

  4. 最高3位用於指定搶佔式優先順序,最低5位用於指定響應優先順序

  5. 最高4位用於指定搶佔式優先順序,最低4位用於指定響應優先順序

  6. 最高5位用於指定搶佔式優先順序,最低3位用於指定響應優先順序

  7. 最高6位用於指定搶佔式優先順序,最低2位用於指定響應優先順序

  8. 最高7位用於指定搶佔式優先順序,最低1位用於指定響應優先順序

    以上便是優先順序分組的概念,但是Cortex-M3允許具有較少中斷源時使用較少的暫存器位指定中斷源的優先順序。

    而STM32對這個表重新進行了編排,把編號從-3至6的中斷向量定義為系統異常,編號為負的核心異常不能被設定優先順序,如復位(Reset)、不可遮蔽中斷 (NMI)、硬錯誤(Hardfault)。從編號 7開始的為外部中斷,這些中斷的優先順序都是可以使用者更改的。詳細的 STM32中斷向量號可以在startup_stm32f10x_XX.s中查詢。

因此STM32把指定中斷優先順序的暫存器位減少到4位,這4個暫存器位的分組方式如下:

第0組:所有4位用於指定響應優先順序(16種)

第1組:最高1位用於指定搶佔式優先順序,最低3位用於指定響應優先順序(8種)

第2組:最高2位用於指定搶佔式優先順序,最低2位用於指定響應優先順序(4種)

第3組:最高3位用於指定搶佔式優先順序,最低1位用於指定響應優先順序(2種)

第4組:所有4位用於指定搶佔式優先順序

  這裡便對於於文章最前提到的韌體庫裡相關的函數了——NVIC_PriorityGroupConfig(u32 NVIC_PriorityGroup),函式的引數共有5種:

這個函式的引數(NVIC_PriorityGroup值)有下列5種:

NVIC_PriorityGroup_0 => 選擇第0組

NVIC_PriorityGroup_1 => 選擇第1組

NVIC_PriorityGroup_2 => 選擇第2組

NVIC_PriorityGroup_3 => 選擇第3組

NVIC_PriorityGroup_4 => 選擇第4組

這其實也很好理解,比如選擇NVIC_PriorityGroup_1,那麼搶佔式優先順序便佔一位,也就是說可以有2^1個級別,可以設定為0和1,而響應優先順序則佔3位,也就是說可以有2^3個選擇,可以設定為0~7;總共來說就可以區別>16種優先順序了。

//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

//NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

舉個例子吧,假如現在有4個外部中斷,還有一個EXTI9_5中斷,那麼如果選擇優先順序分組為第1組,那麼搶佔式優先順序便只有兩種,5箇中斷就至少有3個在搶佔式優先順序上是相同的優先順序上,其他兩個在令一優先級別。接著設定響應優先順序可以有8種選擇;假如現在同時有兩個搶佔式優先級別相同的中斷髮生,那麼處理的順序是誰的響應優先順序高則誰優先進入中斷,另外這點是需要注意的,如果此時進入這個中斷之後又來了一個搶佔式優先順序相同但是響應優先順序更高的中斷,這時也是不會打斷已有的中斷的。

void NVIC_Config(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

#ifdef  VECT_TAB_RAM

//Set the Vector Table base location at 0x20000000 

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else

//Set the Vector Table base location at 0x08000000 

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); 

#endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  //中斷優先順序組 :1組(整個系統為同一組)

// 設定搶佔優先順序0~1,響應優先順序0~7

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;             // TIM2 全域性中斷

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   // 搶佔優先順序 1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          // 響應優先順序 0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             // IRQ通道被使能

NVIC_Init(&NVIC_InitStructure);

//* Enable the TIM3 Interrupt

NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;             // TIM3 全域性中斷

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   // 搶佔優先順序 1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          // 響應優先順序 1

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             // IRQ通道被使能

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;           // USART1 全域性中斷

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   // 搶佔優先順序   0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          // 響應優先順序   0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             // IRQ通道被使能

NVIC_Init(&NVIC_InitStructure);

}

說明:假如TIM3是正在執行的中斷,如果USART1中斷也發生了,則優先處理,TIM3被巢狀並掛起;如果TIM2中斷髮生了,則需要等到TIM3處理完之後再處理TIM2。這就是搶佔優先順序和響應優先順序的區別。